Restoring some of our on-screen functionality for debug purposes.
We could prove that updating a single pixel is much faster than updating our
whole screen. Single pixel updates runs at full 24 FPS.
19 FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0)
23 FutabaVfdCommand::~FutabaVfdCommand()
32 void FutabaVfdCommand::Reset()
34 memset(iReports,0,sizeof(iReports));
43 void FutabaVfdCommand::Create(int aMaxSize)
45 iBuffer=new unsigned char[aMaxSize];
58 void FutabaVfdCommand::Delete()
74 GP1212A01A::GP1212A01A():
75 iDisplayPositionX(0),iDisplayPositionY(0),
76 iOffScreenMode(true),iFrameBuffer(NULL),iRequest(ERequestNone),iPowerOn(false)
83 GP1212A01A::~GP1212A01A()
91 int GP1212A01A::Open()
93 int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
98 iFrameBuffer=new BitArray(KGP12xFrameBufferPixelCount);
100 //Since we can't get our display position we force it to our default
101 //This makes sure frames are in sync from the start
102 //Clever clients will have taken care of putting back frame (0,0) before closing
103 SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
110 void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
113 //int byteOffset=(aX*HeightInPixels()+aY)/8;
114 //int bitOffset=(aX*HeightInPixels()+aY)%8;
115 //iFrameBuffer[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
121 iFrameBuffer->SetBit(aX*HeightInPixels()+aY);
125 iFrameBuffer->ClearBit(aX*HeightInPixels()+aY);
130 //Just specify a one pixel block
131 SetPixelBlock(aX,aY,0x00,0x01,aOn);
137 void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
139 //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
140 for (int i=0;i<aSrcWidth;i++)
142 for (int j=0;j<aSrcHeight;j++)
144 iFrameBuffer->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
150 Set all pixels on our screen to the desired value.
151 This operation is performed off screen to avoid tearing.
152 @param 8 pixels pattern
154 void GP1212A01A::SetAllPixels(unsigned char aPattern)
156 //With a single buffer
157 //unsigned char screen[2048]; //One screen worth of pixels
158 //memset(screen,0xFF,sizeof(screen));
159 //SetPixelBlock(0,0,63,sizeof(screen),screen);
164 memset(iFrameBuffer->Ptr(),aPattern,FrameBufferSizeInBytes());
168 //Using pattern SetPixelBlock variant.
169 SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
176 Set the defined pixel block to the given value.
177 @param X coordinate of our pixel block starting point.
178 @param Y coordinate of our pixel block starting point.
179 @param The height of our pixel block.
180 @param The size of our pixel data. Number of pixels divided by 8.
181 @param The value set to 8 pixels used as a pattern.
183 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
185 OffScreenTranslation(aX,aY);
186 FutabaVfdReport report;
187 report[0]=0x00; //Report ID
188 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
189 report[2]=0x1B; //Command ID
190 report[3]=0x5B; //Command ID
191 report[4]=0xF0; //Command ID
194 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.
195 report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
196 report[9]=aSize; //Size of pixel data in bytes (LSB)
197 int sizeWritten=MIN(aSize,report.Size()-10);
198 memset(report.Buffer()+10, aValue, sizeWritten);
201 int remainingSize=aSize;
202 //We need to keep on sending our pixel data until we are done
203 while (report[1]==64)
206 remainingSize-=sizeWritten;
207 report[0]=0x00; //Report ID
208 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
209 sizeWritten=(report[1]==64?63:report[1]);
210 memset(report.Buffer()+2, aValue, sizeWritten);
216 Set the defined pixel block to the given value.
217 @param X coordinate of our pixel block starting point.
218 @param Y coordinate of our pixel block starting point.
219 @param The height of our pixel block.
220 @param The size of our pixel data. Number of pixels divided by 8.
221 @param Pointer to our pixel data.
223 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
225 OffScreenTranslation(aX,aY);
226 FutabaVfdReport report;
227 report[0]=0x00; //Report ID
228 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
229 report[2]=0x1B; //Command ID
230 report[3]=0x5B; //Command ID
231 report[4]=0xF0; //Command ID
234 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.
235 report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
236 report[9]=aSize; //Size of pixel data in bytes (LSB)
237 int sizeWritten=MIN(aSize,report.Size()-10);
238 memcpy(report.Buffer()+10, aPixels, sizeWritten);
241 int remainingSize=aSize;
242 //We need to keep on sending our pixel data until we are done
243 while (report[1]==64)
246 remainingSize-=sizeWritten;
247 report[0]=0x00; //Report ID
248 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
249 sizeWritten=(report[1]==64?63:report[1]);
250 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
257 Clear our client side back buffer.
258 Call to SwapBuffers must follow to actually clear the display.
260 void GP1212A01A::Clear()
262 //memset(iFrameBuffer->Ptr(),0x00,FrameBufferSizeInBytes());
265 iFrameBuffer->ClearAll();
274 Using this function is advised against as is causes tearing.
277 void GP1212A01A::SendClearCommand()
280 //Send Clear Display Command
281 FutabaVfdReport report;
282 report[0]=0x00; //Report ID
283 report[1]=0x04; //Report length
284 report[2]=0x1B; //Command ID
285 report[3]=0x5B; //Command ID
286 report[4]=0x32; //Command ID
287 report[5]=0x4A; //Command ID
292 Change our display position within our buffer.
294 void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
297 //Send Display Position Settings Command
298 FutabaVfdReport report;
299 report[0]=0x00; //Report ID
300 report[1]=0x05; //Report length
301 report[2]=0x1B; //Command ID
302 report[3]=0x5B; //Command ID
303 report[4]=aDw; //Specify our DW
304 report[5]=aX; //X coordinate of our DW top-left corner
305 report[6]=aY; //Y coordinate of our DW top-left corner
310 Change our display position within our buffer.
312 void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
314 //Specs apparently says both DW should remain the same
316 SetDisplayPosition(GP1212A01A::DW1,aX,aY);
317 SetDisplayPosition(GP1212A01A::DW2,aX,aY);
318 iDisplayPositionX=aX;
319 iDisplayPositionY=aY;
323 Provide Y coordinate of our off screen buffer.
325 unsigned char GP1212A01A::OffScreenY() const
327 //Overflowing is fine this is just what we want
328 return iDisplayPositionY+HeightInPixels();
332 Put our off screen buffer on screen.
333 On screen buffer goes off screen.
335 void GP1212A01A::SwapBuffers()
337 //Only perform buffer swapping if off screen mode is enabled
340 //Send host back buffer to device back buffer
341 SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameBuffer->Ptr());
342 //Swap device front and back buffer
343 SetDisplayPosition(iDisplayPositionX,OffScreenY());
345 //unsigned char* backBuffer=iBackBuffer;
346 //iBackBuffer = iFrontBuffer;
347 //iFrontBuffer = backBuffer;
352 Translate the given pixel coordinate according to our off screen mode.
354 void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
358 aX+=WidthInPixels()-iDisplayPositionX;
359 aY+=HeightInPixels()-iDisplayPositionY;
366 void GP1212A01A::ResetBuffers()
368 //iFrameBuffer->ClearAll();
369 //memset(iFrameBuffer,0x00,sizeof(iFrameBuffer));
370 //memset(iFrameBeta,0x00,sizeof(iFrameBeta));
375 void GP1212A01A::RequestDeviceId()
377 if (RequestPending())
379 //Abort silently for now
383 //1BH,5BH,63H,49H,44H
384 //Send Read ID command
385 FutabaVfdReport report;
386 report[0]=0x00; //Report ID
387 report[1]=0x05; //Report length
388 report[2]=0x1B; //Command ID
389 report[3]=0x5B; //Command ID
390 report[4]=0x63; //Command ID
391 report[5]=0x49; //Command ID
392 report[6]=0x44; //Command ID
393 if (Write(report)==report.Size())
395 iRequest=ERequestDeviceId;
401 void GP1212A01A::RequestFirmwareRevision()
403 if (RequestPending())
405 //Abort silently for now
409 //1BH,5BH,63H,46H,52H
410 //Send Software Revision Read Command
411 FutabaVfdReport report;
412 report[0]=0x00; //Report ID
413 report[1]=0x05; //Report length
414 report[2]=0x1B; //Command ID
415 report[3]=0x5B; //Command ID
416 report[4]=0x63; //Command ID
417 report[5]=0x46; //Command ID
418 report[6]=0x52; //Command ID
419 if (Write(report)==report.Size())
421 iRequest=ERequestFirmwareRevision;
427 void GP1212A01A::RequestPowerSupplyStatus()
429 if (RequestPending())
431 //Abort silently for now
434 //1BH,5BH,63H,50H,4DH
435 //Send Power Suppply Monitor Command
436 FutabaVfdReport report;
437 report[0]=0x00; //Report ID
438 report[1]=0x05; //Report length
439 report[2]=0x1B; //Command ID
440 report[3]=0x5B; //Command ID
441 report[4]=0x63; //Command ID
442 report[5]=0x50; //Command ID
443 report[6]=0x4D; //Command ID
444 if (Write(report)==report.Size())
446 iRequest=ERequestPowerSupplyStatus;
452 This is for development purposes only.
453 Production application should stick to off-screen mode to avoid tearing.
455 void GP1212A01A::ToggleOffScreenMode()
457 iOffScreenMode=!iOffScreenMode;
458 //Clean up our buffers upon switching modes
459 SetDisplayPosition(0,0);
466 * @brief GP1212A01A::SetOffScreenMode
470 void GP1212A01A::SetOffScreenMode(bool aOn)
472 if (aOn==iOffScreenMode)
480 //Clean up our buffers upon switching modes
481 SetDisplayPosition(0,0);
489 GP1212A01A::Request GP1212A01A::AttemptRequestCompletion()
491 if (!RequestPending())
496 int res=Read(iInputReport);
503 //Process our request
504 if (CurrentRequest()==GP1212A01A::ERequestPowerSupplyStatus)
506 if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
510 else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
516 Request completed=iRequest;
517 //Our request was completed
518 iRequest=ERequestNone;
525 Set our screen brightness.
526 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
528 void GP1212A01A::SetBrightness(int aBrightness)
530 if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
532 //Brightness out of range.
533 //Just ignore that request.
537 FutabaVfdReport report;
538 report[0]=0x00; //Report ID
539 report[1]=0x06; //Report size
540 report[2]=0x1B; //Command ID
541 report[3]=0x5C; //Command ID
542 report[4]=0x3F; //Command ID
543 report[5]=0x4C; //Command ID
544 report[6]=0x44; //Command ID
545 report[7]=0x30+aBrightness; //Brightness level