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),
81 iNeedFullFrameUpdate(true),
82 iRequest(ERequestNone),iPowerOn(false)
89 GP1212A01A::~GP1212A01A()
100 iNeedFullFrameUpdate=true;
105 int GP1212A01A::Open()
107 int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
110 //Allocate both frames
113 iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
117 iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
119 iCurrentFrame=iFrameAlpha;
120 iNextFrame=iFrameBeta;
121 //To make sure it is synced properly
122 iNeedFullFrameUpdate=true;
125 //Since we can't get our display position we force it to our default
126 //This makes sure frames are in sync from the start
127 //Clever clients will have taken care of putting back frame (0,0) before closing
128 SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
135 void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
138 //int byteOffset=(aX*HeightInPixels()+aY)/8;
139 //int bitOffset=(aX*HeightInPixels()+aY)%8;
140 //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
146 iNextFrame->SetBit(aX*HeightInPixels()+aY);
150 iNextFrame->ClearBit(aX*HeightInPixels()+aY);
155 //Just specify a one pixel block
156 SetPixelBlock(aX,aY,0x00,0x01,aOn);
162 void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
164 //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
165 for (int i=0;i<aSrcWidth;i++)
167 for (int j=0;j<aSrcHeight;j++)
169 iNextFrame->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
175 Set all pixels on our screen to the desired value.
176 This operation is performed off screen to avoid tearing.
177 @param 8 pixels pattern
179 void GP1212A01A::SetAllPixels(unsigned char aPattern)
181 //With a single buffer
182 //unsigned char screen[2048]; //One screen worth of pixels
183 //memset(screen,0xFF,sizeof(screen));
184 //SetPixelBlock(0,0,63,sizeof(screen),screen);
189 memset(iNextFrame->Ptr(),aPattern,FrameBufferSizeInBytes());
193 //Using pattern SetPixelBlock variant.
194 SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
201 Set the defined pixel block to the given value.
202 @param X coordinate of our pixel block starting point.
203 @param Y coordinate of our pixel block starting point.
204 @param The height of our pixel block.
205 @param The size of our pixel data. Number of pixels divided by 8.
206 @param The value set to 8 pixels used as a pattern.
208 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
210 OffScreenTranslation(aX,aY);
211 FutabaVfdReport report;
212 report[0]=0x00; //Report ID
213 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
214 report[2]=0x1B; //Command ID
215 report[3]=0x5B; //Command ID
216 report[4]=0xF0; //Command ID
219 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.
220 report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
221 report[9]=aSize; //Size of pixel data in bytes (LSB)
222 int sizeWritten=MIN(aSize,report.Size()-10);
223 memset(report.Buffer()+10, aValue, sizeWritten);
226 int remainingSize=aSize;
227 //We need to keep on sending our pixel data until we are done
228 while (report[1]==64)
231 remainingSize-=sizeWritten;
232 report[0]=0x00; //Report ID
233 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
234 sizeWritten=(report[1]==64?63:report[1]);
235 memset(report.Buffer()+2, aValue, sizeWritten);
241 Set the defined pixel block to the given value.
242 @param X coordinate of our pixel block starting point.
243 @param Y coordinate of our pixel block starting point.
244 @param The height of our pixel block.
245 @param The size of our pixel data. Number of pixels divided by 8.
246 @param Pointer to our pixel data.
248 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
250 OffScreenTranslation(aX,aY);
251 FutabaVfdReport report;
252 report[0]=0x00; //Report ID
253 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
254 report[2]=0x1B; //Command ID
255 report[3]=0x5B; //Command ID
256 report[4]=0xF0; //Command ID
259 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.
260 report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
261 report[9]=aSize; //Size of pixel data in bytes (LSB)
262 int sizeWritten=MIN(aSize,report.Size()-10);
263 memcpy(report.Buffer()+10, aPixels, sizeWritten);
266 int remainingSize=aSize;
267 //We need to keep on sending our pixel data until we are done
268 while (report[1]==64)
271 remainingSize-=sizeWritten;
272 report[0]=0x00; //Report ID
273 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
274 sizeWritten=(report[1]==64?63:report[1]);
275 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
282 Clear our client side back buffer.
283 Call to SwapBuffers must follow to actually clear the display.
285 void GP1212A01A::Clear()
287 //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
290 iNextFrame->ClearAll();
299 Using this function is advised against as is causes tearing.
302 void GP1212A01A::SendClearCommand()
305 //Send Clear Display Command
306 FutabaVfdReport report;
307 report[0]=0x00; //Report ID
308 report[1]=0x04; //Report length
309 report[2]=0x1B; //Command ID
310 report[3]=0x5B; //Command ID
311 report[4]=0x32; //Command ID
312 report[5]=0x4A; //Command ID
317 Change our display position within our buffer.
319 void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
322 //Send Display Position Settings Command
323 FutabaVfdReport report;
324 report[0]=0x00; //Report ID
325 report[1]=0x05; //Report length
326 report[2]=0x1B; //Command ID
327 report[3]=0x5B; //Command ID
328 report[4]=aDw; //Specify our DW
329 report[5]=aX; //X coordinate of our DW top-left corner
330 report[6]=aY; //Y coordinate of our DW top-left corner
335 Change our display position within our buffer.
337 void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
339 //Specs apparently says both DW should remain the same
341 SetDisplayPosition(GP1212A01A::DW1,aX,aY);
342 SetDisplayPosition(GP1212A01A::DW2,aX,aY);
343 iDisplayPositionX=aX;
344 iDisplayPositionY=aY;
348 Provide Y coordinate of our off screen buffer.
350 unsigned char GP1212A01A::OffScreenY() const
352 //Overflowing is fine this is just what we want
353 return iDisplayPositionY+HeightInPixels();
357 Put our off screen buffer on screen.
358 On screen buffer goes off screen.
360 void GP1212A01A::SwapBuffers()
362 //Only perform buffer swapping if off screen mode is enabled
365 //Send host back buffer to device back buffer
366 if (iNeedFullFrameUpdate)
368 //TODO: enable this once SendModifiedPixelBlocks works
369 //iNeedFullFrameUpdate=false;
370 SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iNextFrame->Ptr());
374 SendModifiedPixelBlocks();
376 //Swap device front and back buffer
377 SetDisplayPosition(iDisplayPositionX,OffScreenY());
379 BitArray* nextFrame=iCurrentFrame;
380 iCurrentFrame = iNextFrame;
381 iNextFrame = nextFrame;
387 * @brief GP1212A01A::SendModifiedPixelBlocks
388 * Compare our back and front buffer and send to the device only the modified pixels.
389 * TODO: Get this working at some point.
391 void GP1212A01A::SendModifiedPixelBlocks()
393 //The largest pixel block we can sanely send with one report is 16*16
394 //const int KBlocksPerRow = WidthInPixels()/16; //16
395 //const int KBlocksPerColumn = HeightInPixels()/16; //4
397 int w=WidthInPixels();
398 int h=HeightInPixels();
400 BitArray block(16*16);
401 //TODO: optimize with memcmp and 16 inc
402 for (int i=0;i<w;i+=16)
404 for (int j=0;j<h;j+=16)
406 //aX*HeightInPixels()+aY
407 int offset=(i*w/8)+(j/8);
408 if (memcmp(iNextFrame->Ptr()+offset,iCurrentFrame->Ptr()+offset,32 /*(16*16/8)*/))
410 //We need to update that block
412 for (int x=i;x<i+16;x++)
414 for (int y=i;y<j+16;y++)
416 block.SetBitValue((x-i)*h+(y-j),(*iNextFrame)[x*h+y]);
419 SetPixelBlock(i,j,15,32,block.Ptr());
420 //SetDisplayPosition(iDisplayPositionX,OffScreenY());
421 //SetDisplayPosition(iDisplayPositionX,OffScreenY());
423 //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
431 Translate the given pixel coordinate according to our off screen mode.
433 void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
437 aX+=WidthInPixels()-iDisplayPositionX;
438 aY+=HeightInPixels()-iDisplayPositionY;
445 void GP1212A01A::ResetBuffers()
447 //iNextFrame->ClearAll();
448 //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
449 //memset(iFrameBeta,0x00,sizeof(iFrameBeta));
454 void GP1212A01A::RequestDeviceId()
456 if (RequestPending())
458 //Abort silently for now
462 //1BH,5BH,63H,49H,44H
463 //Send Read ID command
464 FutabaVfdReport report;
465 report[0]=0x00; //Report ID
466 report[1]=0x05; //Report length
467 report[2]=0x1B; //Command ID
468 report[3]=0x5B; //Command ID
469 report[4]=0x63; //Command ID
470 report[5]=0x49; //Command ID
471 report[6]=0x44; //Command ID
472 if (Write(report)==report.Size())
474 iRequest=ERequestDeviceId;
480 void GP1212A01A::RequestFirmwareRevision()
482 if (RequestPending())
484 //Abort silently for now
488 //1BH,5BH,63H,46H,52H
489 //Send Software Revision Read Command
490 FutabaVfdReport report;
491 report[0]=0x00; //Report ID
492 report[1]=0x05; //Report length
493 report[2]=0x1B; //Command ID
494 report[3]=0x5B; //Command ID
495 report[4]=0x63; //Command ID
496 report[5]=0x46; //Command ID
497 report[6]=0x52; //Command ID
498 if (Write(report)==report.Size())
500 iRequest=ERequestFirmwareRevision;
506 void GP1212A01A::RequestPowerSupplyStatus()
508 if (RequestPending())
510 //Abort silently for now
513 //1BH,5BH,63H,50H,4DH
514 //Send Power Suppply Monitor Command
515 FutabaVfdReport report;
516 report[0]=0x00; //Report ID
517 report[1]=0x05; //Report length
518 report[2]=0x1B; //Command ID
519 report[3]=0x5B; //Command ID
520 report[4]=0x63; //Command ID
521 report[5]=0x50; //Command ID
522 report[6]=0x4D; //Command ID
523 if (Write(report)==report.Size())
525 iRequest=ERequestPowerSupplyStatus;
531 This is for development purposes only.
532 Production application should stick to off-screen mode to avoid tearing.
534 void GP1212A01A::ToggleOffScreenMode()
536 iOffScreenMode=!iOffScreenMode;
537 //Clean up our buffers upon switching modes
538 SetDisplayPosition(0,0);
545 * @brief GP1212A01A::SetOffScreenMode
549 void GP1212A01A::SetOffScreenMode(bool aOn)
551 if (aOn==iOffScreenMode)
559 //Clean up our buffers upon switching modes
560 SetDisplayPosition(0,0);
568 GP1212A01A::Request GP1212A01A::AttemptRequestCompletion()
570 if (!RequestPending())
575 int res=Read(iInputReport);
582 //Process our request
583 if (CurrentRequest()==GP1212A01A::ERequestPowerSupplyStatus)
585 if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
589 else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
595 Request completed=iRequest;
596 //Our request was completed
597 iRequest=ERequestNone;
604 Set our screen brightness.
605 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
607 void GP1212A01A::SetBrightness(int aBrightness)
609 if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
611 //Brightness out of range.
612 //Just ignore that request.
616 FutabaVfdReport report;
617 report[0]=0x00; //Report ID
618 report[1]=0x06; //Report size
619 report[2]=0x1B; //Command ID
620 report[3]=0x5C; //Command ID
621 report[4]=0x3F; //Command ID
622 report[5]=0x4C; //Command ID
623 report[6]=0x44; //Command ID
624 report[7]=0x30+aBrightness; //Brightness level