Trying to sort out our interop nicely.
2 // Copyright (C) 2014-2015 Stéphane Lenclud.
4 // This file is part of MiniDisplay.
6 // MiniDisplay is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // MiniDisplay is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with MiniDisplay. If not, see <http://www.gnu.org/licenses/>.
20 #include "FutabaGP1212A02.h"
25 const unsigned short KMaxDataMemoryAddress = 0x4FFF;
26 const unsigned short KFrameSizeInBytes = 0x800;
29 static void sleep(unsigned int mseconds)
31 clock_t goal = mseconds + clock();
32 while (goal > clock());
39 GP1212A02A::GP1212A02A():
40 iDisplayPositionX(0),iDisplayPositionY(0),
42 iUseFrameDifferencing(true),
49 iNeedFullFrameUpdate(0)
52 iFirmwareRevision[0]=0;
58 GP1212A02A::~GP1212A02A()
73 iNeedFullFrameUpdate=0;
78 int GP1212A02A::Open()
80 int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A02A,NULL);
83 //Allocate both frames
86 iFrameAlpha=new BitArrayLow(KGP12xFrameBufferPixelCount);
90 iFrameBeta=new BitArrayLow(KGP12xFrameBufferPixelCount);
94 iFrameGamma=new BitArrayLow(KGP12xFrameBufferPixelCount);
96 iFrameNext=iFrameAlpha;
97 iFrameCurrent=iFrameBeta;
98 iFramePrevious=iFrameGamma;
101 //To make sure it is synced properly
102 iNeedFullFrameUpdate=0;
110 //BMP box setup could be removed if we don't use it anymore
112 BmpBoxSetting(EBmpBoxIdOne,0x0000,256,64);
113 //Select current BMP box
114 BmpBoxSelect(EBmpBoxIdOne);
116 iNextFrameAddress = 0x0000;
120 SendCommandFontAction(EFontDelete);
122 //SendCommandSelectFontSize(EFontLarge);
123 //SendCommandReset();
127 unsigned char charPixels[]={ 0xFF,0xFF,0xFF,0xFF,
142 0xFF,0xFF,0xFF,0xFF};
145 //SendCommandFontAction(EFontStore);
146 for (unsigned short i=0;i<16;i++)
148 //SendCommandFontAction(EFontDelete);
150 SendCommandDefineCharacter(EFont16x32,0x0030+i,charPixels);
151 //SendCommandFontAction(EFontStore);
157 //SendCommandFontAction(EFontTransfer);
160 //SendCommandDefineCharacter(EFont16x32,0x0031,charPixels);
161 //SendCommandFontAction(EFontStore);
174 [Code] 1BH,5CH,42H,Pn,aL,aH,Pw,Ph
175 [Function] Setting the BMP box. BMP box can be defined the 3 area to DW. The position of BMP
176 box is set based on the address of DW.
177 * To write data in BMP box, BMP box select is necessary.
178 * Specifiable horizontal size is 256dot (100H) MAX. If horizontal size specify 256dot, Pw = 00H
179 Pn = Number of a BMP box
180 aL = Lower byte of address
181 aH = Upper byte of address
189 0000H <= aL + aH * 100 <= 07FFH
190 01H <= Pw <= 00H (=100H)
193 void GP1212A02A::BmpBoxSetting(TBmpBoxId aBoxId, unsigned short aAddress, int aWidth, int aHeight)
195 //TODO: check parameters validity
196 //1BH,5CH,42H,Pn,aL,aH,Pw,Ph
197 FutabaVfdReport report;
198 report[0]=0x00; //Report ID
199 report[1]=0x08; //Report length.
200 report[2]=0x1B; //Command ID
201 report[3]=0x5C; //Command ID
202 report[4]=0x42; //Command ID
204 report[6]=(unsigned char)aAddress; //aL = DM lower byte
205 report[7]=aAddress>>8; //aH = DM upper byte
206 report[8]=(aWidth==256?0x00:aWidth); //Pw = BMP box width 00==256
207 report[9]=aHeight/8; //Ph = BMP box height.
213 [Function]Select of BMP box
214 * Execution "BMP box select" is necessary before "Setting the Text box".
215 * In case of writing by the specified dot writing, it is necessary to cancel this command.
217 Pn = 30H - Remove the BMP box
222 void GP1212A02A::BmpBoxSelect(TBmpBoxId aBoxId)
224 //TODO: check parameters validity
225 FutabaVfdReport report;
226 report[0]=0x00; //Report ID
227 report[1]=0x04; //Report length.
228 report[2]=0x1B; //Command ID
229 report[3]=0x5C; //Command ID
230 report[4]=0x48; //Command ID
231 report[5]=aBoxId; //BMP box ID
238 void GP1212A02A::SetPixel(unsigned char aX, unsigned char aY, unsigned int aPixel)
241 //int byteOffset=(aX*HeightInPixels()+aY)/8;
242 //int bitOffset=(aX*HeightInPixels()+aY)%8;
243 //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
245 //Pixel is on if any of the non-alpha component is not null
246 bool on = (aPixel&0x00FFFFFF)!=0x00000000;
252 iFrameNext->SetBit(aX*HeightInPixels()+aY);
256 iFrameNext->ClearBit(aX*HeightInPixels()+aY);
261 //Just specify a one pixel block
269 void GP1212A02A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
271 //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
272 for (int i=0;i<aSrcWidth;i++)
274 for (int j=0;j<aSrcHeight;j++)
276 iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
283 Clear our client side back buffer.
284 Call to SwapBuffers must follow to actually clear the display.
286 void GP1212A02A::Clear()
288 //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
291 iFrameNext->ClearAll();
301 Must be followed by a SwapBuffers call.
303 void GP1212A02A::Fill()
309 Set all pixels on our screen to the desired value.
310 This operation is performed off screen to avoid tearing.
311 @param 8 pixels pattern
313 void GP1212A02A::SetAllPixels(unsigned char aPattern)
315 //With a single buffer
316 //unsigned char screen[2048]; //One screen worth of pixels
317 //memset(screen,0xFF,sizeof(screen));
318 //SetPixelBlock(0,0,63,sizeof(screen),screen);
323 memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
327 //Using pattern SetPixelBlock variant.
338 [Code] 1BH,4AH,Pm,aL,aH,Ps,nL,nH,Pd...Pd
339 [Function] The BMP data is written in the DW(Display Window) or the Data memory.
340 Pm= DW or Data memory
343 Ps = Direction of writing
344 nL = number of BMP data length lower byte
345 nH = number of BMP data length upper byte
347 * If X direction is selected as Ps and data is written in the last address, the data in the last address is
348 overwritten with the remaining data.
349 [Definable area] Pm = 30H : DW
350 Pm = 31H: Data memory
351 0000H <= aL + aH * 100 <= 07FFH (DW)
352 0000H <= aL + aH * 100 <= 4FFFH (Data memory)
353 Ps = 30H: Y direction
354 Ps = 31H: X direction
355 0001H <= nL + nH * 100 <= 0100H(DW: X direction)
356 0001H <= nL + nH * 100 <= 0800H(DW: Y direction)
357 0001H <= nL + nH * 100 <= 0A00H(Data memory: X direction)
358 0001H <= nL + nH * 100 <= 5000H(Data memory: Y direction)
360 void GP1212A02A::BmpDataInput(TTarget aTarget, unsigned short aAddress, TDirection aDirection, unsigned short aSize, unsigned char* aPixels)
362 FutabaVfdReport report;
363 report[0]=0x00; //Report ID
364 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
365 report[2]=0x1B; //Command ID
366 report[3]=0x4A; //Command ID
367 report[4]=aTarget; //Display Window or Data Memory
368 report[5]=(unsigned char)aAddress; //aL = DW lower byte
369 report[6]=aAddress>>8; //aH = DW upper byte
370 report[7]=aDirection; //Direction of writing: Y or X
371 report[8]=(unsigned char)aSize; //Size of pixel data in bytes (LSB)
372 report[9]=aSize>>8; //Size of pixel data in bytes (MSB)
373 int sizeWritten=MIN(aSize,report.Size()-10);
374 memcpy(report.Buffer()+10, aPixels, sizeWritten);
377 int remainingSize=aSize;
378 //We need to keep on sending our pixel data until we are done
379 while (report[1]==64)
382 remainingSize-=sizeWritten;
383 report[0]=0x00; //Report ID
384 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
385 sizeWritten=(report[1]==64?63:report[1]);
386 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
394 [Code] 1BH,5CH,44H,aL,aH
395 [Function] BMP data transfer from Data memory to DW.
396 Although source data is updated, data in BMP box is not updated. To reflect the update,
397 re-executing this command is necessary.
398 aL = Lower byte of address
399 aH = Upper byte of address
401 0000H <= aL + aH * 100 <= 4FFFH
403 void GP1212A02A::BmpBoxDataMemoryTransfer(unsigned short aAddress)
405 FutabaVfdReport report;
406 report[0]=0x00; //Report ID
407 report[1]=0x05; //Report length.
408 report[2]=0x1B; //Command ID
409 report[3]=0x5C; //Command ID
410 report[4]=0x44; //Command ID
411 report[5]=(unsigned char)aAddress; //aL = DM lower byte
412 report[6]=aAddress>>8; //aH = DM upper byte
417 Input BMP data in the BMP box
418 [Code] 1BH,5CH,5DH,nL,nH,Pd...Pd
419 [Function] BMP data is written the BMP box
420 * Number of definable data is due to BMP box size. If the data is over range, the over range data is
421 rewritten the final address.
422 nL = Lower byte of number of definition byte
423 nH = Upper byte of number of definition byte
425 [Definable area] Pn : BMP box size (Pw * Ph)
427 void GP1212A02A::BmpBoxDataInput(unsigned short aSize, unsigned char* aPixels)
429 FutabaVfdReport report;
430 report[0]=0x00; //Report ID
431 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
432 report[2]=0x1B; //Command ID
433 report[3]=0x5C; //Command ID
434 report[4]=0x5D; //Display Window or Data Memory
435 report[5]=(unsigned char)aSize; //Size of pixel data in bytes (LSB)
436 report[6]=aSize>>8; //Size of pixel data in bytes (MSB)
437 int sizeWritten=MIN(aSize,report.Size()-7);
438 memcpy(report.Buffer()+7, aPixels, sizeWritten);
441 int remainingSize=aSize;
442 //We need to keep on sending our pixel data until we are done
443 while (report[1]==64)
446 remainingSize-=sizeWritten;
447 report[0]=0x00; //Report ID
448 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
449 sizeWritten=(report[1]==64?63:report[1]);
450 memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
456 Using this function is advised against as is causes tearing.
459 void GP1212A02A::SendCommandClear()
462 //Send Clear Display Command
463 FutabaVfdReport report;
464 report[0]=0x00; //Report ID
465 report[1]=0x04; //Report length
466 report[2]=0x1B; //Command ID
467 report[3]=0x4A; //Command ID
468 report[4]=0x43; //Command ID
469 report[5]=0x44; //Command ID
475 Returns to default setting.
476 * The other command is not receive until this command complete. Please don’t send the any data
477 from a host during “BUSY”
478 * Delete the User definable font to the RAM.
479 * If the VFD Power Off, VFD Power turn ON after the RESET command.
481 void GP1212A02A::SendCommandReset()
484 //Send Clear Display Command
485 FutabaVfdReport report;
486 report[0]=0x00; //Report ID
487 report[1]=0x04; //Report length
488 report[2]=0x1B; //Command ID
489 report[3]=0x4A; //Command ID
490 report[4]=0x52; //Command ID
491 report[5]=0x53; //Command ID
493 //Wait until reset is done. Is that needed?
500 Provide Y coordinate of our off screen buffer.
502 unsigned char GP1212A02A::OffScreenY() const
504 //Overflowing is fine this is just what we want
505 return iDisplayPositionY+HeightInPixels();
509 Put our off screen buffer on screen.
510 On screen buffer goes off screen.
512 void GP1212A02A::SwapBuffers()
514 //Only perform buffer swapping if off screen mode is enabled
517 //Send pixel directly into BMP box
518 //BmpBoxDataInput(FrameBufferSizeInBytes(),iFrameNext->Ptr());
520 //This appears to be the fastest scheme when running on our HTPC
521 //Send pixel data directly into the display window
522 BmpDataInput(ETargetDisplayWindow,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
524 //Send pixel data first to Data Memory then copy into the selected BMP box
525 //BmpDataInput(ETargetDataMemory,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
526 //BmpBoxDataMemoryTransfer(0x0000);
528 //Send pixel data first to Data Memory then copy into the selected BMP box, cycling through our Data Memory frame
530 BmpDataInput(ETargetDataMemory,iNextFrameAddress,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
531 BmpBoxDataMemoryTransfer(iNextFrameAddress);
532 iNextFrameAddress+=KFrameSizeInBytes;
533 if (iNextFrameAddress>KMaxDataMemoryAddress)
535 iNextFrameAddress=0x0000;
539 //Cycle through our frame buffers
540 //We keep track of previous frame which is in fact our device back buffer.
541 //We can then compare previous and next frame and send only the differences to our device.
542 //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
543 //Keep our previous frame pointer
544 BitArrayLow* previousFrame=iFramePrevious;
545 //Current frame becomes the previous one
546 iFramePrevious = iFrameCurrent;
547 //Next frame becomes the current one
548 iFrameCurrent = iFrameNext;
549 //Next frame is now our former previous
550 iFrameNext = previousFrame;
555 //Define the edge of our pixel block
556 //Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
557 //Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
558 const int KPixelBlockEdge = 32;
559 const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
560 const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
564 Translate the given pixel coordinate according to our off screen mode.
566 void GP1212A02A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
570 aX+=WidthInPixels()-iDisplayPositionX;
571 aY+=HeightInPixels()-iDisplayPositionY;
578 void GP1212A02A::Request(TMiniDisplayRequest aRequest)
582 case EMiniDisplayRequestDeviceId:
585 case EMiniDisplayRequestFirmwareRevision:
586 RequestFirmwareRevision();
588 case EMiniDisplayRequestPowerSupplyStatus:
589 RequestPowerSupplyStatus();
600 void GP1212A02A::ResetBuffers()
602 //iNextFrame->ClearAll();
603 //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
604 //memset(iFrameBeta,0x00,sizeof(iFrameBeta));
609 void GP1212A02A::RequestDeviceId()
616 [Code] 1BH,6AH,49H,44H
617 [Function] Send the ID code to the Host system. ID code is software version.
619 void GP1212A02A::RequestFirmwareRevision()
621 if (RequestPending())
623 //Abort silently for now
628 //Send Software Revision Read Command
629 FutabaVfdReport report;
630 report[0]=0x00; //Report ID
631 report[1]=0x04; //Report length
632 report[2]=0x1B; //Command ID
633 report[3]=0x6A; //Command ID
634 report[4]=0x49; //Command ID
635 report[5]=0x44; //Command ID
636 if (Write(report)==report.Size())
638 SetRequest(EMiniDisplayRequestFirmwareRevision);
645 void GP1212A02A::RequestPowerSupplyStatus()
652 This is for development purposes only.
653 Production application should stick to off-screen mode to avoid tearing.
655 void GP1212A02A::ToggleOffScreenMode()
657 SetOffScreenMode(!iOffScreenMode);
661 * @brief GP1212A02A::SetOffScreenMode
665 void GP1212A02A::SetOffScreenMode(bool aOn)
667 if (aOn==iOffScreenMode)
675 //Clean up our buffers upon switching modes
682 Tries to complete our current request if we have one pending.
684 TMiniDisplayRequest GP1212A02A::AttemptRequestCompletion()
686 if (!RequestPending())
688 return EMiniDisplayRequestNone;
691 int res=Read(iInputReport);
695 return EMiniDisplayRequestNone;
698 //Process our request
699 if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision)
701 unsigned char* ptr=&iInputReport[2];
702 iInputReport[7]=0x00;
703 strcpy(iFirmwareRevision,(const char*)ptr);
706 TMiniDisplayRequest completed=CurrentRequest();
707 //Our request was completed
708 SetRequest(EMiniDisplayRequestNone);
715 Set our screen brightness.
716 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
718 void GP1212A02A::SetBrightness(int aBrightness)
720 if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
722 //Brightness out of range.
723 //Just ignore that request.
727 FutabaVfdReport report;
728 report[0]=0x00; //Report ID
729 report[1]=0x04; //Report size
730 report[2]=0x1B; //Command ID
731 report[3]=0x4A; //Command ID
732 report[4]=0x44; //Command ID
733 report[5]=0x30+aBrightness; //Brightness level
740 [Function]Control of the power supply for VFD
741 * If VFD power ON or OFF, at interval of 10s or more.
742 * When the VFD power off, VFD display is turn off, but the module can receive a data and
744 Ps = VFD Power control
746 Ps = 30H : VFD Power OFF
747 Ps = 31H : VFD Power ON (Default)
749 void GP1212A02A::SendCommandPower(TPowerStatus aPowerStatus)
751 FutabaVfdReport report;
752 report[0]=0x00; //Report ID
753 report[1]=0x04; //Report size
754 report[2]=0x1B; //Command ID
755 report[3]=0x4A; //Command ID
756 report[4]=0x42; //Command ID
757 report[5]=aPowerStatus; //ON or OFF
763 void GP1212A02A::TurnPowerOn()
765 SendCommandPower(EPowerOn);
771 void GP1212A02A::TurnPowerOff()
773 SendCommandPower(EPowerOff);
778 Provide the length of our character string for the given clock format.
779 @param The clock format to evaluate.
780 @return Number of characters for the given clock format.
782 int GP1212A02A::ClockCharCount(TClockFormat aFormat)
800 @return Clock character width in pixels.
802 int GP1212A02A::ClockCharWidthInPixels(TFontSizeLogical aSize)
820 @return Clock character height in pixels.
822 int GP1212A02A::ClockCharHeightInPixels(TFontSizeLogical aSize)
840 Return the Display Window address for centering the clock corresponding to the given parameters.
842 unsigned short GP1212A02A::ClockCenterAddress(TClockFormat aFormat, TFontSizeLogical aSize)
844 int charCount=ClockCharCount(aFormat);
845 int halfWidth=(ClockCharWidthInPixels(aSize)*charCount)/2;
846 int halfHeight=(ClockCharHeightInPixels(aSize))/2;
847 int x=(WidthInPixels()/2)-halfWidth;
848 int y=(HeightInPixels()/2)-halfHeight;
851 int xOffset=x*8; //Not sure why...
853 unsigned short address = yOffset+xOffset;
860 void GP1212A02A::ShowClock()
862 SendCommandClockDisplay(EClock24,ClockCenterAddress(EClock24,EFontLarge),EFontLarge);
867 void GP1212A02A::HideClock()
869 SendCommandClockCancel();
875 [Code]1BH,6BH,53H,Pd,Ph,Pm
876 [Function]Setting the clock data. The setting data is cleared, if the Reset command is input or power
886 * Clock setting is canceled, when Pd is input value that is larger than 07H, or Ph is input value that is
887 larger than 18H,or Pm is input value that is larger than 3CH.
889 void GP1212A02A::SendCommandClockSetting(TWeekDay aWeekDay, unsigned char aHour, unsigned char aMinute)
891 FutabaVfdReport report;
892 report[0]=0x00; //Report ID
893 report[1]=0x06; //Report size
894 report[2]=0x1B; //Command ID
895 report[3]=0x6B; //Command ID
896 report[4]=0x53; //Command ID
897 report[5]=aWeekDay; //Sunday to Saturday
906 Set display clock settings according to local system time.
907 This needs to be redone whenever we open or turn on our display.
909 void GP1212A02A::SetClockSetting()
912 struct tm * timeinfo;
915 timeinfo = localtime ( &rawtime );
917 SendCommandClockSetting((TWeekDay)timeinfo->tm_wday,timeinfo->tm_hour,timeinfo->tm_min);
923 [Code] 1BH,6BH,55H,Ps,aL,aH,Pf
924 [Function] Clock is displayed. The display position and the font size can be freely decided.
925 Ps = Display type select
927 Pf = Font size select
929 Ps = 00H : 24hour Ex.[12:34]
930 Ps = 01H : 24hour + day of the week Ex.[Wed._12:34]
931 Ps = 10H : 12hour Ex.[PM_00:34]
932 Ps = 11H : 12hour + day of the week Ex.[Wed._PM_00:34]
937 * When the clock data is not input, clock is not displayed.
938 * The clock display is maintained until Clock display cancel "Clear display" RESET command is input
939 or power is turned off.
940 The clock display area
941 Graphic can be displayed excluding the clock display area.
942 The self adjustment for the position
943 that cannot be displayed.
944 * Excluding the clock display area can be input other display commands.
946 void GP1212A02A::SendCommandClockDisplay(TClockFormat aClockFormat, unsigned short aAddress, TFontSizeLogical aSize)
948 FutabaVfdReport report;
949 report[0]=0x00; //Report ID
950 report[1]=0x07; //Report size
951 report[2]=0x1B; //Command ID
952 report[3]=0x6B; //Command ID
953 report[4]=0x55; //Command ID
954 report[5]=aClockFormat; //
955 report[6]=(unsigned char)aAddress; //aL
956 report[7]=aAddress>>8; //aH
965 [Code] 1BH,6BH,3DH,58H
966 [Function] Clock display is canceled.
968 void GP1212A02A::SendCommandClockCancel()
970 FutabaVfdReport report;
971 report[0]=0x00; //Report ID
972 report[1]=0x04; //Report size
973 report[2]=0x1B; //Command ID
974 report[3]=0x6B; //Command ID
975 report[4]=0x3D; //Command ID
983 @return Size in bytes of a character for a given font size.
985 int GP1212A02A::CharacterSizeInBytes(TFontSize aFontSize)
1009 Define the User definable font (RAM)
1010 [Code] 1BH,6AH,47H,Pf,cL,(cH),Pd...Pd
1011 [Function] Define the User definable font into RAM. A maximum 16 characters can be defined
1012 within each font size.
1013 The User definable fonts are displayed the defined code. It is a same process to normal fonts.
1014 The User definable fonts are valid until they redefined, Reset command, or the power off.
1015 If define the user definable font over 16 characters, at first defined user definable font is removed
1016 If the defined code is specified, existing data is re-written.
1017 If the 16x16, 24x24, 32x32 size define, it must specify the “cH”
1019 cL = Lower byte of User definable font code
1020 cH = Upper byte of User definable font code
1021 Pd = Definition data
1023 Pf = 30H : 6x8 dot (Pd=6 byte)
1024 Pf = 31H : 8x16 dot (Pd=16 byte)
1025 Pf = 32H : 12x24 dot (Pd=36 byte)
1026 Pf = 33H : 16x32 dot (Pd=64 byte)
1027 Pf = 34H : 16x16 dot (Pd=32 byte)
1028 Pf = 35H : 24x24 dot (Pd=72 byte)
1029 Pf = 36H : 32x32 dot (Pd=128 byte)
1030 cL = ANK code (Pf=30H~33H : 1 byte code)
1031 cL,cH = Shift-JIS code (Pf=34H~36H : 2 byte code)
1033 void GP1212A02A::SendCommandDefineCharacter(TFontSize aFontSize, unsigned short aCharacterCode, unsigned char* aPixels)
1035 unsigned char reportSize=0;
1036 unsigned char headerSize=0;
1037 unsigned char dataSize=CharacterSizeInBytes(aFontSize);
1038 FutabaVfdReport report;
1040 if (aFontSize>=EFont16x16)
1044 reportSize = (dataSize<=report.Size()-headerSize?dataSize+0x06:64); //Report length. -7 is for our header first 7 bytes. +5 is for our Futaba header size
1045 report[7] = aCharacterCode>>8;
1051 reportSize = (dataSize<=report.Size()-headerSize?dataSize+0x05:64); //Report length. -7 is for our header first 7 bytes. +5 is for our Futaba header size
1055 report[0]=0x00; //Report ID
1056 report[1]=reportSize; //Report size
1057 report[2]=0x1B; //Command ID
1058 report[3]=0x6A; //Command ID
1059 report[4]=0x47; //Command ID
1060 report[5]=aFontSize; //
1061 report[6] = (unsigned char) aCharacterCode;
1062 //7th byte was set above already
1063 int sizeWritten=MIN(dataSize,report.Size()-headerSize);
1064 memcpy(report.Buffer()+headerSize, aPixels, sizeWritten);
1067 int remainingSize=dataSize;
1068 //We need to keep on sending our pixel data until we are done
1069 while (report[1]==64)
1072 remainingSize-=sizeWritten;
1073 report[0]=0x00; //Report ID
1074 report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
1075 sizeWritten=(report[1]==64?63:report[1]);
1076 memcpy(report.Buffer()+2, aPixels+(dataSize-remainingSize), sizeWritten);
1083 User definable font store / transfer / delete
1084 [Code] 1BH,6AH,45H,Ps
1085 [Function] Store, transfer, or delete the User definable font to FROM.
1086 * Define the user definable font, after the user definable font is stored
1087 * The user definable font store is stored the all defined user definable font data.
1088 * The use definable font delete is deleted the all defined to FROM and RAM user definable font data.
1089 Ps = store / transfer / delete
1095 void GP1212A02A::SendCommandFontAction(TFontAction aFontAction)
1097 FutabaVfdReport report;
1098 report[0]=0x00; //Report ID
1099 report[1]=0x04; //Report size
1100 report[2]=0x1B; //Command ID
1101 report[3]=0x6A; //Command ID
1102 report[4]=0x45; //Command ID
1103 report[5]=aFontAction; //Ps
1110 [Code]1BH,4AH,46H,Pf
1111 [Function]Setting the font size
1115 Pf = 31H?8x16dot and 16x16 dot
1116 Pf = 32H?12x24 dot and 24x24 dot
1117 Pf = 33H?16x32 dot and 32x32 dot
1119 void GP1212A02A::SendCommandSelectFontSize(TFontSizeLogical aFontSoze)
1121 FutabaVfdReport report;
1122 report[0]=0x00; //Report ID
1123 report[1]=0x04; //Report size
1124 report[2]=0x1B; //Command ID
1125 report[3]=0x4A; //Command ID
1126 report[4]=0x46; //Command ID
1127 report[5]=aFontSoze; //Pf