Pixel diff logic for frame rate improvment now working.
It's still working on a per pixels bases so too slow with full screen update.
Thus it's still disabled.
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),
83 iNeedFullFrameUpdate(0),
84 iRequest(ERequestNone),iPowerOn(false)
91 GP1212A01A::~GP1212A01A()
106 iNeedFullFrameUpdate=0;
111 int GP1212A01A::Open()
113 int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
116 //Allocate both frames
119 iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
123 iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
127 iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount);
129 iFrameNext=iFrameAlpha;
130 iFrameCurrent=iFrameBeta;
131 iFramePrevious=iFrameGamma;
134 //To make sure it is synced properly
135 iNeedFullFrameUpdate=0;
138 //Since we can't get our display position we force it to our default
139 //This makes sure frames are in sync from the start
140 //Clever clients will have taken care of putting back frame (0,0) before closing
141 SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
148 void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
151 //int byteOffset=(aX*HeightInPixels()+aY)/8;
152 //int bitOffset=(aX*HeightInPixels()+aY)%8;
153 //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
159 iFrameNext->SetBit(aX*HeightInPixels()+aY);
163 iFrameNext->ClearBit(aX*HeightInPixels()+aY);
168 //Just specify a one pixel block
169 SetPixelBlock(aX,aY,0x00,0x01,aOn);
175 void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
177 //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
178 for (int i=0;i<aSrcWidth;i++)
180 for (int j=0;j<aSrcHeight;j++)
182 iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
188 Clear our client side back buffer.
189 Call to SwapBuffers must follow to actually clear the display.
191 void GP1212A01A::Clear()
193 //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
196 iFrameNext->ClearAll();
205 Set all pixels on our screen to the desired value.
206 This operation is performed off screen to avoid tearing.
207 @param 8 pixels pattern
209 void GP1212A01A::SetAllPixels(unsigned char aPattern)
211 //With a single buffer
212 //unsigned char screen[2048]; //One screen worth of pixels
213 //memset(screen,0xFF,sizeof(screen));
214 //SetPixelBlock(0,0,63,sizeof(screen),screen);
219 memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
223 //Using pattern SetPixelBlock variant.
224 SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
231 Set the defined pixel block to the given value.
232 @param X coordinate of our pixel block starting point.
233 @param Y coordinate of our pixel block starting point.
234 @param The height of our pixel block.
235 @param The size of our pixel data. Number of pixels divided by 8.
236 @param The value set to 8 pixels used as a pattern.
238 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
240 OffScreenTranslation(aX,aY);
241 FutabaVfdReport report;
242 report[0]=0x00; //Report ID
243 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
244 report[2]=0x1B; //Command ID
245 report[3]=0x5B; //Command ID
246 report[4]=0xF0; //Command ID
249 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.
250 report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
251 report[9]=aSize; //Size of pixel data in bytes (LSB)
252 int sizeWritten=MIN(aSize,report.Size()-10);
253 memset(report.Buffer()+10, aValue, sizeWritten);
256 int remainingSize=aSize;
257 //We need to keep on sending our pixel data until we are done
258 while (report[1]==64)
261 remainingSize-=sizeWritten;
262 report[0]=0x00; //Report ID
263 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
264 sizeWritten=(report[1]==64?63:report[1]);
265 memset(report.Buffer()+2, aValue, sizeWritten);
271 Set the defined pixel block to the given value.
272 @param X coordinate of our pixel block starting point.
273 @param Y coordinate of our pixel block starting point.
274 @param The height of our pixel block.
275 @param The size of our pixel data. Number of pixels divided by 8.
276 @param Pointer to our pixel data.
278 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
280 OffScreenTranslation(aX,aY);
281 FutabaVfdReport report;
282 report[0]=0x00; //Report ID
283 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
284 report[2]=0x1B; //Command ID
285 report[3]=0x5B; //Command ID
286 report[4]=0xF0; //Command ID
289 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.
290 report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
291 report[9]=aSize; //Size of pixel data in bytes (LSB)
292 int sizeWritten=MIN(aSize,report.Size()-10);
293 memcpy(report.Buffer()+10, aPixels, sizeWritten);
296 int remainingSize=aSize;
297 //We need to keep on sending our pixel data until we are done
298 while (report[1]==64)
301 remainingSize-=sizeWritten;
302 report[0]=0x00; //Report ID
303 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
304 sizeWritten=(report[1]==64?63:report[1]);
305 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
311 Using this function is advised against as is causes tearing.
314 void GP1212A01A::SendClearCommand()
317 //Send Clear Display Command
318 FutabaVfdReport report;
319 report[0]=0x00; //Report ID
320 report[1]=0x04; //Report length
321 report[2]=0x1B; //Command ID
322 report[3]=0x5B; //Command ID
323 report[4]=0x32; //Command ID
324 report[5]=0x4A; //Command ID
329 Change our display position within our buffer.
331 void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
334 //Send Display Position Settings Command
335 FutabaVfdReport report;
336 report[0]=0x00; //Report ID
337 report[1]=0x05; //Report length
338 report[2]=0x1B; //Command ID
339 report[3]=0x5B; //Command ID
340 report[4]=aDw; //Specify our DW
341 report[5]=aX; //X coordinate of our DW top-left corner
342 report[6]=aY; //Y coordinate of our DW top-left corner
347 Change our display position within our buffer.
349 void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
351 //Specs apparently says both DW should remain the same
353 SetDisplayPosition(GP1212A01A::DW1,aX,aY);
354 SetDisplayPosition(GP1212A01A::DW2,aX,aY);
355 iDisplayPositionX=aX;
356 iDisplayPositionY=aY;
360 Provide Y coordinate of our off screen buffer.
362 unsigned char GP1212A01A::OffScreenY() const
364 //Overflowing is fine this is just what we want
365 return iDisplayPositionY+HeightInPixels();
369 Put our off screen buffer on screen.
370 On screen buffer goes off screen.
372 void GP1212A01A::SwapBuffers()
374 //Only perform buffer swapping if off screen mode is enabled
377 //Send host back buffer to device back buffer
378 if (iNeedFullFrameUpdate<3)
380 //TODO: enable this once SendModifiedPixelBlocks works
381 //iNeedFullFrameUpdate++;
382 SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameNext->Ptr());
386 SendModifiedPixelBlocks();
388 //Swap device front and back buffer
389 SetDisplayPosition(iDisplayPositionX,OffScreenY());
391 //BitArray* nextFrame=iFrameNext;
392 //iFrameCurrent = iFramePrevious;
393 //iFrameNext = iFramePrevious;
395 BitArray* previousFrame=iFramePrevious;
396 iFramePrevious = iFrameCurrent;
397 iFrameCurrent = iFrameNext;
398 iFrameNext = previousFrame;
404 * @brief GP1212A01A::SendModifiedPixelBlocks
405 * Compare our back and front buffer and send to the device only the modified pixels.
406 * TODO: Get this working at some point.
408 void GP1212A01A::SendModifiedPixelBlocks()
410 //The largest pixel block we can sanely send with one report is 16*16
411 //const int KBlocksPerRow = WidthInPixels()/16; //16
412 //const int KBlocksPerColumn = HeightInPixels()/16; //4
414 int w=WidthInPixels();
415 int h=HeightInPixels();
417 BitArray block(16*16);
420 //TODO: optimize with memcmp and 16 inc
421 for (int i=0;i<w;i++)
423 for (int j=0;j<h;j++)
425 //aX*HeightInPixels()+aY
426 if ((*iFrameNext)[i*h+j]!=(*iFramePrevious)[i*h+j])
428 //We need to update that pixel
429 SetPixelBlock(i,j,0,1,((*iFrameNext)[i*h+j]?0x01:0x00));
430 //SetDisplayPosition(iDisplayPositionX,OffScreenY());
431 //SetDisplayPosition(iDisplayPositionX,OffScreenY());
433 //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
439 for (int i=0;i<w;i+=16)
441 for (int j=0;j<h;j+=16)
443 //aX*HeightInPixels()+aY
444 int offset=(i*w/8)+(j/8);
445 if (memcmp(iNextFrame->Ptr()+offset,iCurrentFrame->Ptr()+offset,32 )) //32=(16*16/8)
447 //We need to update that block
449 for (int x=i;x<i+16;x++)
451 for (int y=i;y<j+16;y++)
453 block.SetBitValue((x-i)*h+(y-j),(*iNextFrame)[x*h+y]);
456 SetPixelBlock(i,j,15,32,block.Ptr());
457 //SetDisplayPosition(iDisplayPositionX,OffScreenY());
458 //SetDisplayPosition(iDisplayPositionX,OffScreenY());
460 //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
469 Translate the given pixel coordinate according to our off screen mode.
471 void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
475 aX+=WidthInPixels()-iDisplayPositionX;
476 aY+=HeightInPixels()-iDisplayPositionY;
483 void GP1212A01A::ResetBuffers()
485 //iNextFrame->ClearAll();
486 //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
487 //memset(iFrameBeta,0x00,sizeof(iFrameBeta));
492 void GP1212A01A::RequestDeviceId()
494 if (RequestPending())
496 //Abort silently for now
500 //1BH,5BH,63H,49H,44H
501 //Send Read ID command
502 FutabaVfdReport report;
503 report[0]=0x00; //Report ID
504 report[1]=0x05; //Report length
505 report[2]=0x1B; //Command ID
506 report[3]=0x5B; //Command ID
507 report[4]=0x63; //Command ID
508 report[5]=0x49; //Command ID
509 report[6]=0x44; //Command ID
510 if (Write(report)==report.Size())
512 iRequest=ERequestDeviceId;
518 void GP1212A01A::RequestFirmwareRevision()
520 if (RequestPending())
522 //Abort silently for now
526 //1BH,5BH,63H,46H,52H
527 //Send Software Revision Read Command
528 FutabaVfdReport report;
529 report[0]=0x00; //Report ID
530 report[1]=0x05; //Report length
531 report[2]=0x1B; //Command ID
532 report[3]=0x5B; //Command ID
533 report[4]=0x63; //Command ID
534 report[5]=0x46; //Command ID
535 report[6]=0x52; //Command ID
536 if (Write(report)==report.Size())
538 iRequest=ERequestFirmwareRevision;
544 void GP1212A01A::RequestPowerSupplyStatus()
546 if (RequestPending())
548 //Abort silently for now
551 //1BH,5BH,63H,50H,4DH
552 //Send Power Suppply Monitor Command
553 FutabaVfdReport report;
554 report[0]=0x00; //Report ID
555 report[1]=0x05; //Report length
556 report[2]=0x1B; //Command ID
557 report[3]=0x5B; //Command ID
558 report[4]=0x63; //Command ID
559 report[5]=0x50; //Command ID
560 report[6]=0x4D; //Command ID
561 if (Write(report)==report.Size())
563 iRequest=ERequestPowerSupplyStatus;
569 This is for development purposes only.
570 Production application should stick to off-screen mode to avoid tearing.
572 void GP1212A01A::ToggleOffScreenMode()
574 SetOffScreenMode(!iOffScreenMode);
578 * @brief GP1212A01A::SetOffScreenMode
582 void GP1212A01A::SetOffScreenMode(bool aOn)
584 if (aOn==iOffScreenMode)
592 //Clean up our buffers upon switching modes
593 SetDisplayPosition(0,0);
601 GP1212A01A::Request GP1212A01A::AttemptRequestCompletion()
603 if (!RequestPending())
608 int res=Read(iInputReport);
615 //Process our request
616 if (CurrentRequest()==GP1212A01A::ERequestPowerSupplyStatus)
618 if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
622 else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
628 Request completed=iRequest;
629 //Our request was completed
630 iRequest=ERequestNone;
637 Set our screen brightness.
638 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
640 void GP1212A01A::SetBrightness(int aBrightness)
642 if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
644 //Brightness out of range.
645 //Just ignore that request.
649 FutabaVfdReport report;
650 report[0]=0x00; //Report ID
651 report[1]=0x06; //Report size
652 report[2]=0x1B; //Command ID
653 report[3]=0x5C; //Command ID
654 report[4]=0x3F; //Command ID
655 report[5]=0x4C; //Command ID
656 report[6]=0x44; //Command ID
657 report[7]=0x30+aBrightness; //Brightness level