5 #include "FutabaGP1212A02.h"
8 const int KNumberOfFrameBeforeDiffAlgo = 3;
14 GP1212A02A::GP1212A02A():
15 iDisplayPositionX(0),iDisplayPositionY(0),
17 iUseFrameDifferencing(true),
24 iNeedFullFrameUpdate(0),
28 iFirmwareRevision[0]=0;
34 GP1212A02A::~GP1212A02A()
49 iNeedFullFrameUpdate=0;
54 int GP1212A02A::Open()
56 int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A02A,NULL);
59 //Allocate both frames
62 iFrameAlpha=new BitArrayLow(KGP12xFrameBufferPixelCount);
66 iFrameBeta=new BitArrayLow(KGP12xFrameBufferPixelCount);
70 iFrameGamma=new BitArrayLow(KGP12xFrameBufferPixelCount);
72 iFrameNext=iFrameAlpha;
73 iFrameCurrent=iFrameBeta;
74 iFramePrevious=iFrameGamma;
77 //To make sure it is synced properly
78 iNeedFullFrameUpdate=0;
85 BmpBoxSetting(EBmpBoxIdOne,0x0000,256,64);
87 //Select current BMP box
88 BmpBoxSelect(EBmpBoxIdOne);
97 [Code] 1BH,5CH,42H,Pn,aL,aH,Pw,Ph
98 [Function] Setting the BMP box. BMP box can be defined the 3 area to DW. The position of BMP
99 box is set based on the address of DW.
100 * To write data in BMP box, BMP box select is necessary.
101 * Specifiable horizontal size is 256dot (100H) MAX. If horizontal size specify 256dot, Pw = 00H
102 Pn = Number of a BMP box
103 aL = Lower byte of address
104 aH = Upper byte of address
112 0000H <= aL + aH * 100 <= 07FFH
113 01H <= Pw <= 00H (=100H)
116 void GP1212A02A::BmpBoxSetting(TBmpBoxId aBoxId, unsigned short aAddress, int aWidth, int aHeight)
118 //TODO: check parameters validity
119 //1BH,5CH,42H,Pn,aL,aH,Pw,Ph
120 FutabaVfdReport report;
121 report[0]=0x00; //Report ID
122 report[1]=0x08; //Report length.
123 report[2]=0x1B; //Command ID
124 report[3]=0x5C; //Command ID
125 report[4]=0x42; //Command ID
127 report[6]=(unsigned char)aAddress; //aL = DM lower byte
128 report[7]=aAddress>>8; //aH = DM upper byte
129 report[8]=(aWidth==256?0x00:aWidth); //Pw = BMP box width 00==256
130 report[9]=aHeight/8; //Ph = BMP box height.
136 [Function]Select of BMP box
137 * Execution "BMP box select" is necessary before "Setting the Text box".
138 * In case of writing by the specified dot writing, it is necessary to cancel this command.
140 Pn = 30H - Remove the BMP box
145 void GP1212A02A::BmpBoxSelect(TBmpBoxId aBoxId)
147 //TODO: check parameters validity
148 FutabaVfdReport report;
149 report[0]=0x00; //Report ID
150 report[1]=0x04; //Report length.
151 report[2]=0x1B; //Command ID
152 report[3]=0x5C; //Command ID
153 report[4]=0x48; //Command ID
154 report[5]=aBoxId; //BMP box ID
161 void GP1212A02A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
164 //int byteOffset=(aX*HeightInPixels()+aY)/8;
165 //int bitOffset=(aX*HeightInPixels()+aY)%8;
166 //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
172 iFrameNext->SetBit(aX*HeightInPixels()+aY);
176 iFrameNext->ClearBit(aX*HeightInPixels()+aY);
181 //Just specify a one pixel block
189 void GP1212A02A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
191 //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
192 for (int i=0;i<aSrcWidth;i++)
194 for (int j=0;j<aSrcHeight;j++)
196 iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
203 Clear our client side back buffer.
204 Call to SwapBuffers must follow to actually clear the display.
206 void GP1212A02A::Clear()
208 //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
211 iFrameNext->ClearAll();
221 Must be followed by a SwapBuffers call.
223 void GP1212A02A::Fill()
229 Set all pixels on our screen to the desired value.
230 This operation is performed off screen to avoid tearing.
231 @param 8 pixels pattern
233 void GP1212A02A::SetAllPixels(unsigned char aPattern)
235 //With a single buffer
236 //unsigned char screen[2048]; //One screen worth of pixels
237 //memset(screen,0xFF,sizeof(screen));
238 //SetPixelBlock(0,0,63,sizeof(screen),screen);
243 memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
247 //Using pattern SetPixelBlock variant.
258 [Code] 1BH,4AH,Pm,aL,aH,Ps,nL,nH,Pd...Pd
259 [Function] The BMP data is written in the DW(Display Window) or the Data memory.
260 Pm= DW or Data memory
263 Ps = Direction of writing
264 nL = number of BMP data length lower byte
265 nH = number of BMP data length upper byte
267 * If X direction is selected as Ps and data is written in the last address, the data in the last address is
268 overwritten with the remaining data.
269 [Definable area] Pm = 30H : DW
270 Pm = 31H: Data memory
271 0000H <= aL + aH * 100 <= 07FFH (DW)
272 0000H <= aL + aH * 100 <= 4FFFH (Data memory)
273 Ps = 30H: Y direction
274 Ps = 31H: X direction
275 0001H <= nL + nH * 100 <= 0100H(DW: X direction)
276 0001H <= nL + nH * 100 <= 0800H(DW: Y direction)
277 0001H <= nL + nH * 100 <= 0A00H(Data memory: X direction)
278 0001H <= nL + nH * 100 <= 5000H(Data memory: Y direction)
280 void GP1212A02A::BmpDataInput(TTarget aTarget, unsigned short aAddress, TDirection aDirection, unsigned short aSize, unsigned char* aPixels)
282 FutabaVfdReport report;
283 report[0]=0x00; //Report ID
284 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
285 report[2]=0x1B; //Command ID
286 report[3]=0x4A; //Command ID
287 report[4]=aTarget; //Display Window or Data Memory
288 report[5]=(unsigned char)aAddress; //aL = DW lower byte
289 report[6]=aAddress>>8; //aH = DW upper byte
290 report[7]=aDirection; //Direction of writing: Y or X
291 report[8]=(unsigned char)aSize; //Size of pixel data in bytes (LSB)
292 report[9]=aSize>>8; //Size of pixel data in bytes (MSB)
293 int sizeWritten=MIN(aSize,report.Size()-10);
294 memcpy(report.Buffer()+10, aPixels, sizeWritten);
297 int remainingSize=aSize;
298 //We need to keep on sending our pixel data until we are done
299 while (report[1]==64)
302 remainingSize-=sizeWritten;
303 report[0]=0x00; //Report ID
304 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
305 sizeWritten=(report[1]==64?63:report[1]);
306 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
314 [Code] 1BH,5CH,44H,aL,aH
315 [Function] BMP data transfer from Data memory to DW.
316 Although source data is updated, data in BMP box is not updated. To reflect the update,
317 re-executing this command is necessary.
318 aL = Lower byte of address
319 aH = Upper byte of address
321 0000H <= aL + aH * 100 <= 4FFFH
323 void GP1212A02A::BmpBoxDataMemoryTransfer(unsigned short aAddress)
325 FutabaVfdReport report;
326 report[0]=0x00; //Report ID
327 report[1]=0x05; //Report length.
328 report[2]=0x1B; //Command ID
329 report[3]=0x5C; //Command ID
330 report[4]=0x44; //Command ID
331 report[5]=(unsigned char)aAddress; //aL = DM lower byte
332 report[6]=aAddress>>8; //aH = DM upper byte
337 Input BMP data in the BMP box
338 [Code] 1BH,5CH,5DH,nL,nH,Pd...Pd
339 [Function] BMP data is written the BMP box
340 * Number of definable data is due to BMP box size. If the data is over range, the over range data is
341 rewritten the final address.
342 nL = Lower byte of number of definition byte
343 nH = Upper byte of number of definition byte
345 [Definable area] Pn : BMP box size (Pw * Ph)
347 void GP1212A02A::BmpBoxDataInput(unsigned short aSize, unsigned char* aPixels)
349 FutabaVfdReport report;
350 report[0]=0x00; //Report ID
351 report[1]=(aSize<=report.Size()-7?aSize+0x05:64); //Report length. -7 is for our header first 10 bytes. +5 is for our Futaba header size
352 report[2]=0x1B; //Command ID
353 report[3]=0x5C; //Command ID
354 report[4]=0x5D; //Display Window or Data Memory
355 report[5]=(unsigned char)aSize; //Size of pixel data in bytes (LSB)
356 report[6]=aSize>>8; //Size of pixel data in bytes (MSB)
357 int sizeWritten=MIN(aSize,report.Size()-7);
358 memcpy(report.Buffer()+7, aPixels, sizeWritten);
361 int remainingSize=aSize;
362 //We need to keep on sending our pixel data until we are done
363 while (report[1]==64)
366 remainingSize-=sizeWritten;
367 report[0]=0x00; //Report ID
368 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
369 sizeWritten=(report[1]==64?63:report[1]);
370 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
376 Using this function is advised against as is causes tearing.
379 void GP1212A02A::SendClearCommand()
382 //Send Clear Display Command
383 FutabaVfdReport report;
384 report[0]=0x00; //Report ID
385 report[1]=0x04; //Report length
386 report[2]=0x1B; //Command ID
387 report[3]=0x4A; //Command ID
388 report[4]=0x43; //Command ID
389 report[5]=0x44; //Command ID
395 Provide Y coordinate of our off screen buffer.
397 unsigned char GP1212A02A::OffScreenY() const
399 //Overflowing is fine this is just what we want
400 return iDisplayPositionY+HeightInPixels();
404 Put our off screen buffer on screen.
405 On screen buffer goes off screen.
407 void GP1212A02A::SwapBuffers()
409 //Only perform buffer swapping if off screen mode is enabled
412 //Send pixel directly into BMP box
413 BmpBoxDataInput(FrameBufferSizeInBytes(),iFrameNext->Ptr());
414 //Send pixel data directly into the display window
415 //BmpDataInput(ETargetDisplayWindow,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
416 //Send pixel data first to Data Memory then copy into the selected BMP box
417 //BmpDataInput(ETargetDataMemory,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
418 //BmpBoxDataMemoryTransfer(0x0000);
420 //Cycle through our frame buffers
421 //We keep track of previous frame which is in fact our device back buffer.
422 //We can then compare previous and next frame and send only the differences to our device.
423 //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
424 //Keep our previous frame pointer
425 BitArrayLow* previousFrame=iFramePrevious;
426 //Current frame becomes the previous one
427 iFramePrevious = iFrameCurrent;
428 //Next frame becomes the current one
429 iFrameCurrent = iFrameNext;
430 //Next frame is now our former previous
431 iFrameNext = previousFrame;
436 //Define the edge of our pixel block
437 //Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
438 //Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
439 const int KPixelBlockEdge = 32;
440 const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
441 const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
445 Translate the given pixel coordinate according to our off screen mode.
447 void GP1212A02A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
451 aX+=WidthInPixels()-iDisplayPositionX;
452 aY+=HeightInPixels()-iDisplayPositionY;
459 void GP1212A02A::ResetBuffers()
461 //iNextFrame->ClearAll();
462 //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
463 //memset(iFrameBeta,0x00,sizeof(iFrameBeta));
468 void GP1212A02A::RequestDeviceId()
475 void GP1212A02A::RequestFirmwareRevision()
482 void GP1212A02A::RequestPowerSupplyStatus()
489 This is for development purposes only.
490 Production application should stick to off-screen mode to avoid tearing.
492 void GP1212A02A::ToggleOffScreenMode()
494 SetOffScreenMode(!iOffScreenMode);
498 * @brief GP1212A02A::SetOffScreenMode
502 void GP1212A02A::SetOffScreenMode(bool aOn)
504 if (aOn==iOffScreenMode)
512 //Clean up our buffers upon switching modes
519 Tries to complete our current request if we have one pending.
521 TMiniDisplayRequest GP1212A02A::AttemptRequestCompletion()
523 //That display does not support any requests
524 return EMiniDisplayRequestNone;
529 Set our screen brightness.
530 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
532 void GP1212A02A::SetBrightness(int aBrightness)
534 if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
536 //Brightness out of range.
537 //Just ignore that request.
541 FutabaVfdReport report;
542 report[0]=0x00; //Report ID
543 report[1]=0x04; //Report size
544 report[2]=0x1B; //Command ID
545 report[3]=0x4A; //Command ID
546 report[4]=0x44; //Command ID
547 report[5]=0x30+aBrightness; //Brightness level
553 bool GP1212A02A::PowerOn()
560 char* GP1212A02A::DeviceId()
567 char* GP1212A02A::FirmwareRevision()
569 return iFirmwareRevision;