1.1 --- a/src/FutabaVfd.cpp Thu May 22 16:46:50 2014 +0200
1.2 +++ b/src/FutabaVfd.cpp Thu May 22 21:32:45 2014 +0200
1.3 @@ -71,53 +71,50 @@
1.4 // class GP1212A01A
1.5 //
1.6
1.7 +GP1212A01A::GP1212A01A():iDisplayPositionX(0),iDisplayPositionY(0),iOffScreenMode(true)
1.8 + {
1.9 + }
1.10 +
1.11 int GP1212A01A::Open()
1.12 {
1.13 int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
1.14 if (success)
1.15 {
1.16 SetNonBlocking(1);
1.17 + //Since we can't get our display position we for it to our default
1.18 + //This makes sure frames are in sync from the start
1.19 + SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
1.20 }
1.21 return success;
1.22 }
1.23
1.24 /**
1.25 */
1.26 -void GP1212A01A::SetPixel(int aX, int aY, bool aOn)
1.27 +void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
1.28 {
1.29 //Just specify a one pixel block
1.30 SetPixelBlock(aX,aY,0x00,0x01,aOn);
1.31 }
1.32
1.33 /**
1.34 +Set all pixels on our screen to the desired value.
1.35 +This operation is performed off screen to avoid tearing.
1.36 +@param 8 pixels pattern
1.37 */
1.38 -void GP1212A01A::SetAllPixels(bool aOn)
1.39 +void GP1212A01A::SetAllPixels(unsigned char aPattern)
1.40 {
1.41 - //One pixel at a time
1.42 - /*
1.43 - for (int i=0;i<256;i++)
1.44 - {
1.45 - for (int j=0;j<64;j++)
1.46 - {
1.47 - SetPixel(i,j,0x01);
1.48 - }
1.49 - }
1.50 - */
1.51 + //With a single buffer
1.52 + //unsigned char screen[2048]; //One screen worth of pixels
1.53 + //memset(screen,0xFF,sizeof(screen));
1.54 + //SetPixelBlock(0,0,63,sizeof(screen),screen);
1.55
1.56 - //16x16=256 pixels at a time goes much faster
1.57 - //TODO: use even larger blocks
1.58 - for (int i=0;i<256;i+=16)
1.59 - {
1.60 - for (int j=0;j<64;j+=16)
1.61 - {
1.62 - SetPixelBlock(i,j,15,32,(aOn?0xFF:0x00));
1.63 - //FXThread::sleep(1000000000);
1.64 - }
1.65 - }
1.66 -
1.67 + //Using pattern SetPixelBlock variant.
1.68 + SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
1.69 }
1.70
1.71 /**
1.72 +Set our screen brightness.
1.73 +@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
1.74 */
1.75 void GP1212A01A::SetBrightness(int aBrightness)
1.76 {
1.77 @@ -149,23 +146,36 @@
1.78 @param The size of our pixel data. Number of pixels divided by 8.
1.79 @param The value set to 8 pixels used as a pattern.
1.80 */
1.81 -void GP1212A01A::SetPixelBlock(int aX, int aY, int aHeight, int aSize, unsigned char aValue)
1.82 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
1.83 {
1.84 - //Size must be 63 or below
1.85 - FutabaVfdReport report;
1.86 - report[0]=0x00; //Report ID
1.87 - report[1]=0x08+aSize; //Report length
1.88 - report[2]=0x1B; //
1.89 - report[3]=0x5B; //
1.90 - report[4]=0xF0; //
1.91 - report[5]=aX; //X
1.92 - report[6]=aY; //Y
1.93 - report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
1.94 - report[8]=0x00; //Size of pixel data in bytes (MSB)
1.95 - report[9]=aSize; //Size of pixel data in bytes (LSB)
1.96 - memset(report.Buffer()+10, aValue, aSize);
1.97 - //iOutputReportBuffer[10]=aValue; //Pixel data
1.98 - Write(report);
1.99 + OffScreenTranslation(aX,aY);
1.100 + FutabaVfdReport report;
1.101 + report[0]=0x00; //Report ID
1.102 + report[1]=(aSize<=report.Size()-10?aSize+0x08:64); //Report length. -10 is for our header first 10 bytes. +8 is for our Futaba header size
1.103 + report[2]=0x1B; //Command ID
1.104 + report[3]=0x5B; //Command ID
1.105 + report[4]=0xF0; //Command ID
1.106 + report[5]=aX; //X
1.107 + report[6]=aY; //Y
1.108 + report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
1.109 + report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
1.110 + report[9]=aSize; //Size of pixel data in bytes (LSB)
1.111 + int sizeWritten=MIN(aSize,report.Size()-10);
1.112 + memset(report.Buffer()+10, aValue, sizeWritten);
1.113 + Write(report);
1.114 +
1.115 + int remainingSize=aSize;
1.116 + //We need to keep on sending our pixel data until we are done
1.117 + while (report[1]==64)
1.118 + {
1.119 + report.Reset();
1.120 + remainingSize-=sizeWritten;
1.121 + report[0]=0x00; //Report ID
1.122 + report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
1.123 + sizeWritten=(report[1]==64?63:report[1]);
1.124 + memset(report.Buffer()+2, aValue, sizeWritten);
1.125 + Write(report);
1.126 + }
1.127 }
1.128
1.129 /**
1.130 @@ -176,19 +186,20 @@
1.131 @param The size of our pixel data. Number of pixels divided by 8.
1.132 @param Pointer to our pixel data.
1.133 */
1.134 -void GP1212A01A::SetPixelBlock(int aX, int aY, int aHeight, int aSize, unsigned char* aPixels)
1.135 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
1.136 {
1.137 + OffScreenTranslation(aX,aY);
1.138 FutabaVfdReport report;
1.139 report[0]=0x00; //Report ID
1.140 - report[1]=0x08+(aSize<=report.Size()-10?aSize:64); //Report length. -10 is for our header first 10 bytes
1.141 + report[1]=(aSize<=report.Size()-10?aSize+0x08:64); //Report length. -10 is for our header first 10 bytes. +8 is for our Futaba header size
1.142 report[2]=0x1B; //Command ID
1.143 report[3]=0x5B; //Command ID
1.144 report[4]=0xF0; //Command ID
1.145 report[5]=aX; //X
1.146 report[6]=aY; //Y
1.147 report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
1.148 - unsigned short* sizePtr=(unsigned short*)report.Buffer()+8; //Size of pixel data in bytes (MSB)
1.149 - *sizePtr=aSize; //Put our size over 2 bytes
1.150 + report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
1.151 + report[9]=aSize; //Size of pixel data in bytes (LSB)
1.152 int sizeWritten=MIN(aSize,report.Size()-10);
1.153 memcpy(report.Buffer()+10, aPixels, sizeWritten);
1.154 Write(report);
1.155 @@ -200,7 +211,7 @@
1.156 report.Reset();
1.157 remainingSize-=sizeWritten;
1.158 report[0]=0x00; //Report ID
1.159 - report[1]=(remainingSize<=report.Size()-2?aSize:64); //Report length, should be 64 or the remaining size
1.160 + report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
1.161 sizeWritten=(report[1]==64?63:report[1]);
1.162 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
1.163 Write(report);
1.164 @@ -210,9 +221,21 @@
1.165
1.166 /**
1.167 Clear our display's screen.
1.168 +This operation is performed off screen to avoid tearing.
1.169 */
1.170 void GP1212A01A::Clear()
1.171 {
1.172 + //Using pattern SetPixelBlock variant.
1.173 + //First fill our off screen buffer with the desired values
1.174 + SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),(unsigned char)0x00);
1.175 + }
1.176 +
1.177 +/**
1.178 +Using this function is advised against as is causes tearing.
1.179 +Use Clear instead.
1.180 +*/
1.181 +void GP1212A01A::SendClearCommand()
1.182 + {
1.183 //1BH,5BH,32H,4AH
1.184 //Send Clear Display Command
1.185 FutabaVfdReport report;
1.186 @@ -228,7 +251,7 @@
1.187 /**
1.188 Change our display position within our buffer.
1.189 */
1.190 -void GP1212A01A::SetDisplayPosition(DW aDw,int aX, int aY)
1.191 +void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
1.192 {
1.193 //1BH,5BH,Dw,Px,Py
1.194 //Send Display Position Settings Command
1.195 @@ -246,12 +269,48 @@
1.196 /**
1.197 Change our display position within our buffer.
1.198 */
1.199 -void GP1212A01A::SetDisplayPosition(int aX, int aY)
1.200 +void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
1.201 {
1.202 //Specs apparently says both DW should remain the same
1.203 //Just don't ask
1.204 SetDisplayPosition(GP1212A01A::DW1,aX,aY);
1.205 SetDisplayPosition(GP1212A01A::DW2,aX,aY);
1.206 + iDisplayPositionX=aX;
1.207 + iDisplayPositionY=aY;
1.208 + }
1.209 +
1.210 +/**
1.211 +Provide Y coordinate of our off screen buffer.
1.212 +*/
1.213 +unsigned char GP1212A01A::OffScreenY() const
1.214 + {
1.215 + //Overflowing is fine this is just what we want
1.216 + return iDisplayPositionY+HeightInPixels();
1.217 + }
1.218 +
1.219 +/**
1.220 +Put our off screen buffer on screen.
1.221 +On screen buffer goes off screen.
1.222 +*/
1.223 +void GP1212A01A::SwapBuffers()
1.224 + {
1.225 + //Only perform buffer swapping if off screen mode is enabled
1.226 + if (OffScreenMode())
1.227 + {
1.228 + SetDisplayPosition(iDisplayPositionX,OffScreenY());
1.229 + }
1.230 + }
1.231 +
1.232 +/**
1.233 +Translate the given pixel coordinate according to our off screen mode.
1.234 +*/
1.235 +void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
1.236 + {
1.237 + if (OffScreenMode())
1.238 + {
1.239 + aX+=WidthInPixels()-iDisplayPositionX;
1.240 + aY+=HeightInPixels()-iDisplayPositionY;
1.241 + }
1.242 }
1.243 /**
1.244 */
1.245 @@ -302,4 +361,19 @@
1.246 report[5]=0x50; //Command ID
1.247 report[6]=0x4D; //Command ID
1.248 Write(report);
1.249 - }
1.250 \ No newline at end of file
1.251 + }
1.252 +
1.253 +
1.254 +/**
1.255 +This is for development purposes only.
1.256 +Production application should stick to off-screen mode to avoid tearing.
1.257 +*/
1.258 +void GP1212A01A::ToggleOffScreenMode()
1.259 + {
1.260 + iOffScreenMode=!iOffScreenMode;
1.261 + //Clean up our buffers upon switching modes
1.262 + SetDisplayPosition(0,0);
1.263 + Clear();
1.264 + SwapBuffers();
1.265 + Clear();
1.266 + }
1.267 \ No newline at end of file