More cleanup.
5 #include "FutabaMDM166AA.h"
12 static void sleep(unsigned int mseconds)
14 clock_t goal = mseconds + clock();
15 while (goal > clock());
32 iFirmwareRevision[0]=0;
58 int success = HidDevice::Open(KTargaVendorId,KFutabaProductIdMDM166AA,NULL);
61 //Allocate both frames
64 iFrameAlpha=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
68 iFrameBeta=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
72 iFrameGamma=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
74 iFrameNext=iFrameAlpha;
75 iFrameCurrent=iFrameBeta;
76 iFramePrevious=iFrameGamma;
90 void MDM166AA::SetPixel(unsigned char aX, unsigned char aY, unsigned int aPixel)
93 //int byteOffset=(aX*HeightInPixels()+aY)/8;
94 //int bitOffset=(aX*HeightInPixels()+aY)%8;
95 //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
97 //Pixel is on if any of the non-alpha component is not null
98 bool on = (aPixel&0x00FFFFFF)!=0x00000000;
104 iFrameNext->SetBit(aX*HeightInPixels()+aY);
108 iFrameNext->ClearBit(aX*HeightInPixels()+aY);
113 //Just specify a one pixel block
121 void MDM166AA::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
123 //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
124 for (int i=0;i<aSrcWidth;i++)
126 for (int j=0;j<aSrcHeight;j++)
128 iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
135 Clear our client side back buffer.
136 Call to SwapBuffers must follow to actually clear the display.
138 void MDM166AA::Clear()
140 //That one also clear the symbols
146 Must be followed by a SwapBuffers call.
148 void MDM166AA::Fill()
154 Set all pixels on our screen to the desired value.
155 This operation is performed off screen to avoid tearing.
156 @param 8 pixels pattern
158 void MDM166AA::SetAllPixels(unsigned char aPattern)
160 //With a single buffer
161 //unsigned char screen[2048]; //One screen worth of pixels
162 //memset(screen,0xFF,sizeof(screen));
163 //SetPixelBlock(0,0,63,sizeof(screen),screen);
168 memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
172 //Using pattern SetPixelBlock variant.
184 Whole display RAM areas including invisible area are filled with 00H data.
186 SL: Though there is no invisible area with that device.
188 void MDM166AA::SendCommandClear()
190 //Send Clear Display Command
191 FutabaVfdReport report;
192 report[0]=0x00; //Report ID
193 report[1]=0x02; //Report length
194 report[2]=0x1B; //Command ID
195 report[3]=0x50; //Command ID
200 Put our off screen buffer on screen.
201 On screen buffer goes off screen.
203 void MDM166AA::SwapBuffers()
205 //Only perform buffer swapping if off screen mode is enabled
208 //Send next frame to our display RAM
209 //We could attempt to implement a frame differencing algorithm much like we did for GP1212A01.
210 //However we see little point doing that since we already run at above 20 FPS.
211 SendCommandWriteGraphicData(FrameBufferSizeInBytes(),iFrameNext->Ptr());
213 //Cycle through our frame buffers
214 //We keep track of previous frame which is in fact our device back buffer.
215 //We can then compare previous and next frame and send only the differences to our device.
216 //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
217 //Keep our previous frame pointer
218 BitArrayLow* previousFrame=iFramePrevious;
219 //Current frame becomes the previous one
220 iFramePrevious = iFrameCurrent;
221 //Next frame becomes the current one
222 iFrameCurrent = iFrameNext;
223 //Next frame is now our former previous
224 iFrameNext = previousFrame;
229 //Define the edge of our pixel block
230 //Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
231 //Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
232 const int KPixelBlockEdge = 32;
233 const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
234 const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
239 void MDM166AA::Request(TMiniDisplayRequest aRequest)
243 case EMiniDisplayRequestDeviceId:
246 case EMiniDisplayRequestFirmwareRevision:
247 RequestFirmwareRevision();
249 case EMiniDisplayRequestPowerSupplyStatus:
250 RequestPowerSupplyStatus();
261 void MDM166AA::ResetBuffers()
263 //iNextFrame->ClearAll();
264 //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
265 //memset(iFrameBeta,0x00,sizeof(iFrameBeta));
270 void MDM166AA::RequestDeviceId()
277 void MDM166AA::RequestFirmwareRevision()
284 void MDM166AA::RequestPowerSupplyStatus()
291 This is for development purposes only.
292 Production application should stick to off-screen mode to avoid tearing.
294 void MDM166AA::ToggleOffScreenMode()
296 SetOffScreenMode(!iOffScreenMode);
300 * @brief MDM166AA::SetOffScreenMode
304 void MDM166AA::SetOffScreenMode(bool aOn)
306 if (aOn==iOffScreenMode)
314 //Clean up our buffers upon switching modes
321 Set our screen brightness.
322 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
324 void MDM166AA::SetBrightness(int aBrightness)
326 if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
328 //Brightness out of range.
329 //Just ignore that request.
333 FutabaVfdReport report;
334 report[0]=0x00; //Report ID
335 report[1]=0x03; //Report size
336 report[2]=0x1B; //Command ID
337 report[3]=0x40; //Command ID
338 report[4]=aBrightness; //Brightness level
345 void MDM166AA::ShowClock()
348 SendCommandClockDisplay(EClockLarge,EClock24);
353 void MDM166AA::HideClock()
363 [Function]Setting the clock data. The setting data is cleared, if the Reset command is input or power is turned off.
367 void MDM166AA::SendCommandSetClockData(unsigned char aHour, unsigned char aMinute)
369 FutabaVfdReport report;
370 report[0]=0x00; //Report ID
371 report[1]=0x04; //Report size
372 report[2]=0x1B; //Command ID
373 report[3]=0x00; //Command ID
375 //Minutes and Hours needs to be in hexadecimal view
376 //To get 21:59 you need to pass in 0x21:0x59
377 //Weirdest format ever, I know
378 report[4]=(aMinute/10*16)+aMinute%10;
379 report[5]=(aHour/10*16)+aHour%10;
386 Set display clock data according to local system time.
387 This needs to be redone whenever we open or turn on our display.
389 void MDM166AA::SetClockData()
392 struct tm * timeinfo;
395 timeinfo = localtime ( &rawtime );
396 //Adjust minute as best as we can so that we have a 30 seconds offset at most rather a than a full minute.
397 if (timeinfo->tm_sec>30)
399 //Use the next minute then
401 if (timeinfo->tm_min==60)
403 //Use the next hour then
406 if (timeinfo->tm_hour==24)
408 //Move to the next day then
414 //Send hours and minutes to our display
415 SendCommandSetClockData(timeinfo->tm_hour,timeinfo->tm_min);
421 [Code] 1BH,Ps,aL,aH,Pf
422 [Function] Clock is displayed small or big.
424 void MDM166AA::SendCommandClockDisplay(TClockSize aClockSize, TClockFormat aClockFormat)
426 FutabaVfdReport report;
427 report[0]=0x00; //Report ID
428 report[1]=0x03; //Report size
429 report[2]=0x1B; //Command ID
430 report[3]=aClockSize; //
431 report[4]=aClockFormat; //
438 Display RAM filled with 00H.
439 Address Counter is set by 00H.
440 Dimming is set to 50%.
442 void MDM166AA::SendCommandReset()
444 FutabaVfdReport report;
445 report[0]=0x00; //Report ID
446 report[1]=0x01; //Report length.
447 report[2]=0x1F; //Command ID
449 //Wait until reset is done. Is that needed?
455 Set Address Counter (AC) values: 1BH + 60H + xxH
457 AC value represents the start address for graphic data.
458 There are 192 bytes as display RAM. It can be set on anywhere even if AC value is not visible area.
459 The default value is 00H.
461 When clock is displayed, AC value is set 00H.
463 void MDM166AA::SendCommandSetAddressCounter(unsigned char aAddressCounter)
465 FutabaVfdReport report;
466 report[0]=0x00; //Report ID
467 report[1]=0x03; //Report length.
468 report[2]=0x1B; //Command ID
469 report[3]=0x60; //Command ID
470 report[4]=aAddressCounter;
476 Set the defined pixel block to the given value.
478 @param The size of our pixel data. Number of pixels divided by 8.
479 @param Pointer to our pixel data.
481 void MDM166AA::SendCommandWriteGraphicData(int aSize, unsigned char* aPixels)
483 //TODO: Remove that at some point
484 SendCommandSetAddressCounter(0);
486 const int KMaxPixelBytes=48;
487 const int KHeaderSize=3;
489 int remainingSize=aSize;
492 while (remainingSize>0)
494 //Only send a maximum of 48 bytes worth of pixels per report
495 const int KPixelDataSize=(remainingSize<=KMaxPixelBytes?remainingSize:KMaxPixelBytes);
497 FutabaVfdReport report;
498 report[0]=0x00; //Report ID
499 report[1]=KPixelDataSize+KHeaderSize; //Report length. +3 is for our header first 3 bytes.
500 report[2]=0x1B; //Command ID
501 report[3]=0x70; //Command ID
502 report[4]=KPixelDataSize; //Size of pixel data in bytes
503 memcpy(report.Buffer()+5, aPixels+sizeWritten, KPixelDataSize);
506 sizeWritten+=KPixelDataSize;
507 remainingSize-=KPixelDataSize;