src/FutabaVfd.cpp
author sl
Thu, 22 May 2014 21:32:45 +0200
changeset 23 d4e164906a1b
parent 22 efa6ff02287c
child 25 233a997193b8
permissions -rw-r--r--
Fixing our multiple report pixel transfer.
Implementing support for off screen mode which is now the default.
On screen mode is there for debug pruposes.
     1 
     2 #include "FutabaVfd.h"
     3 //#include <stdlib.h>
     4 #include <string.h>
     5 
     6 
     7 //
     8 //
     9 //
    10 
    11 
    12 
    13 
    14 
    15 //
    16 //
    17 //
    18 
    19 FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0)
    20     {
    21     }
    22 
    23 FutabaVfdCommand::~FutabaVfdCommand()
    24     {
    25     //Delete();
    26     }
    27 
    28 
    29 /**
    30 
    31 */
    32 void FutabaVfdCommand::Reset()
    33     {
    34     memset(iReports,0,sizeof(iReports));
    35     }
    36 
    37 
    38 
    39 /**
    40 
    41 */
    42 /*
    43 void FutabaVfdCommand::Create(int aMaxSize)
    44     {
    45     iBuffer=new unsigned char[aMaxSize];
    46     if (iBuffer)
    47         {
    48         iMaxSize = aMaxSize;
    49         iSize = 0;
    50         }
    51     }
    52 */
    53 
    54 /**
    55 
    56 */
    57 /*
    58 void FutabaVfdCommand::Delete()
    59 {
    60     delete[] iBuffer;
    61     iBuffer = NULL;
    62     iMaxSize = 0;
    63     iSize = 0;
    64 }
    65 */
    66 
    67 
    68 
    69 
    70 //
    71 // class GP1212A01A
    72 //
    73 
    74 GP1212A01A::GP1212A01A():iDisplayPositionX(0),iDisplayPositionY(0),iOffScreenMode(true)
    75 	{
    76 	}
    77 
    78 int GP1212A01A::Open()
    79 	{
    80 	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    81 	if (success)
    82 		{
    83 		SetNonBlocking(1);
    84 		//Since we can't get our display position we for it to our default
    85 		//This makes sure frames are in sync from the start
    86 		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
    87 		}
    88 	return success;
    89 	}
    90 
    91 /**
    92 */
    93 void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
    94 	{
    95 	//Just specify a one pixel block
    96 	SetPixelBlock(aX,aY,0x00,0x01,aOn);
    97 	}
    98 
    99 /**
   100 Set all pixels on our screen to the desired value.
   101 This operation is performed off screen to avoid tearing.
   102 @param 8 pixels pattern
   103 */
   104 void GP1212A01A::SetAllPixels(unsigned char aPattern)
   105 	{
   106 	//With a single buffer
   107 	//unsigned char screen[2048]; //One screen worth of pixels
   108 	//memset(screen,0xFF,sizeof(screen));
   109 	//SetPixelBlock(0,0,63,sizeof(screen),screen);
   110 
   111 	//Using pattern SetPixelBlock variant.
   112 	SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
   113 	}
   114 
   115 /**
   116 Set our screen brightness.
   117 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
   118 */
   119 void GP1212A01A::SetBrightness(int aBrightness)
   120     {
   121 	if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
   122         {
   123         //Brightness out of range.
   124         //Just ignore that request.
   125         return;
   126         }
   127 
   128     FutabaVfdReport report;
   129     report[0]=0x00; //Report ID
   130     report[1]=0x06; //Report size
   131     report[2]=0x1B; //Command ID
   132     report[3]=0x5C; //Command ID
   133     report[4]=0x3F; //Command ID
   134     report[5]=0x4C; //Command ID
   135     report[6]=0x44; //Command ID
   136     report[7]=0x30+aBrightness; //Brightness level
   137     Write(report);
   138 
   139 	}
   140 
   141 /**
   142 Set the defined pixel block to the given value.
   143 @param X coordinate of our pixel block starting point.
   144 @param Y coordinate of our pixel block starting point.
   145 @param The height of our pixel block.
   146 @param The size of our pixel data. Number of pixels divided by 8.
   147 @param The value set to 8 pixels used as a pattern.
   148 */
   149 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
   150 	{
   151 	OffScreenTranslation(aX,aY);
   152     FutabaVfdReport report;
   153     report[0]=0x00; //Report ID
   154     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
   155     report[2]=0x1B; //Command ID
   156     report[3]=0x5B; //Command ID
   157     report[4]=0xF0; //Command ID
   158     report[5]=aX;   //X
   159     report[6]=aY;   //Y
   160     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.
   161 	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   162 	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   163     int sizeWritten=MIN(aSize,report.Size()-10);
   164     memset(report.Buffer()+10, aValue, sizeWritten);
   165     Write(report);
   166 
   167     int remainingSize=aSize;
   168     //We need to keep on sending our pixel data until we are done
   169     while (report[1]==64)
   170         {
   171         report.Reset();
   172         remainingSize-=sizeWritten;
   173         report[0]=0x00; //Report ID
   174         report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   175         sizeWritten=(report[1]==64?63:report[1]);
   176         memset(report.Buffer()+2, aValue, sizeWritten);
   177         Write(report);
   178         }
   179 	}
   180 
   181 /**
   182 Set the defined pixel block to the given value.
   183 @param X coordinate of our pixel block starting point.
   184 @param Y coordinate of our pixel block starting point.
   185 @param The height of our pixel block.
   186 @param The size of our pixel data. Number of pixels divided by 8.
   187 @param Pointer to our pixel data.
   188 */
   189 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   190     {
   191 	OffScreenTranslation(aX,aY);
   192     FutabaVfdReport report;
   193     report[0]=0x00; //Report ID
   194     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
   195     report[2]=0x1B; //Command ID
   196     report[3]=0x5B; //Command ID
   197     report[4]=0xF0; //Command ID
   198     report[5]=aX;   //X
   199     report[6]=aY;   //Y
   200     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.
   201 	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   202 	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   203     int sizeWritten=MIN(aSize,report.Size()-10);
   204     memcpy(report.Buffer()+10, aPixels, sizeWritten);
   205     Write(report);
   206 
   207     int remainingSize=aSize;
   208     //We need to keep on sending our pixel data until we are done
   209     while (report[1]==64)
   210         {
   211         report.Reset();
   212         remainingSize-=sizeWritten;
   213         report[0]=0x00; //Report ID
   214         report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   215         sizeWritten=(report[1]==64?63:report[1]);
   216         memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   217         Write(report);
   218         }
   219     }
   220 
   221 
   222 /**
   223 Clear our display's screen.
   224 This operation is performed off screen to avoid tearing.
   225 */
   226 void GP1212A01A::Clear()
   227 	{
   228 	//Using pattern SetPixelBlock variant.
   229 	//First fill our off screen buffer with the desired values
   230 	SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),(unsigned char)0x00);
   231 	}
   232 
   233 /**
   234 Using this function is advised against as is causes tearing.
   235 Use Clear instead.
   236 */
   237 void GP1212A01A::SendClearCommand()
   238 	{
   239     //1BH,5BH,32H,4AH
   240     //Send Clear Display Command
   241 	FutabaVfdReport report;
   242 	report[0]=0x00; //Report ID
   243 	report[1]=0x04; //Report length
   244 	report[2]=0x1B; //Command ID
   245 	report[3]=0x5B; //Command ID
   246 	report[4]=0x32; //Command ID
   247 	report[5]=0x4A; //Command ID
   248 	Write(report);
   249 	}
   250 
   251 /**
   252 Change our display position within our buffer.
   253 */
   254 void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   255     {
   256     //1BH,5BH,Dw,Px,Py
   257     //Send Display Position Settings Command
   258     FutabaVfdReport report;
   259     report[0]=0x00; //Report ID
   260     report[1]=0x05; //Report length
   261     report[2]=0x1B; //Command ID
   262     report[3]=0x5B; //Command ID
   263     report[4]=aDw;  //Specify our DW
   264     report[5]=aX;   //X coordinate of our DW top-left corner
   265     report[6]=aY;   //Y coordinate of our DW top-left corner
   266     Write(report);
   267     }
   268 
   269 /**
   270 Change our display position within our buffer.
   271 */
   272 void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   273 	{
   274 	//Specs apparently says both DW should remain the same
   275 	//Just don't ask
   276     SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   277     SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   278 	iDisplayPositionX=aX;
   279 	iDisplayPositionY=aY;
   280 	}
   281 
   282 /**
   283 Provide Y coordinate of our off screen buffer.
   284 */
   285 unsigned char GP1212A01A::OffScreenY() const
   286 	{
   287 	//Overflowing is fine this is just what we want
   288 	return iDisplayPositionY+HeightInPixels();
   289 	}
   290 
   291 /**
   292 Put our off screen buffer on screen.
   293 On screen buffer goes off screen.
   294 */
   295 void GP1212A01A::SwapBuffers()
   296 	{
   297 	//Only perform buffer swapping if off screen mode is enabled
   298 	if (OffScreenMode())
   299 		{
   300 		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   301 		}
   302 	}
   303 
   304 /**
   305 Translate the given pixel coordinate according to our off screen mode.
   306 */
   307 void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   308 	{
   309 	if (OffScreenMode())
   310 		{
   311 		aX+=WidthInPixels()-iDisplayPositionX;
   312 		aY+=HeightInPixels()-iDisplayPositionY;
   313 		}
   314 	}
   315 /**
   316 */
   317 void GP1212A01A::RequestId()
   318     {
   319     //1BH,5BH,63H,49H,44H
   320     //Send Read ID command
   321     FutabaVfdReport report;
   322     report[0]=0x00; //Report ID
   323     report[1]=0x05; //Report length
   324     report[2]=0x1B; //Command ID
   325     report[3]=0x5B; //Command ID
   326     report[4]=0x63; //Command ID
   327     report[5]=0x49; //Command ID
   328     report[6]=0x44; //Command ID
   329     Write(report);
   330     }
   331 
   332 /**
   333 */
   334 void GP1212A01A::RequestFirmwareRevision()
   335     {
   336     //1BH,5BH,63H,46H,52H
   337     //Send Software Revision Read Command
   338     FutabaVfdReport report;
   339     report[0]=0x00; //Report ID
   340     report[1]=0x05; //Report length
   341     report[2]=0x1B; //Command ID
   342     report[3]=0x5B; //Command ID
   343     report[4]=0x63; //Command ID
   344     report[5]=0x46; //Command ID
   345     report[6]=0x52; //Command ID
   346     Write(report);
   347     }
   348 
   349 /**
   350 */
   351 void GP1212A01A::RequestPowerSupplyStatus()
   352     {
   353     //1BH,5BH,63H,50H,4DH
   354     //Send Power Suppply Monitor Command
   355     FutabaVfdReport report;
   356     report[0]=0x00; //Report ID
   357     report[1]=0x05; //Report length
   358     report[2]=0x1B; //Command ID
   359     report[3]=0x5B; //Command ID
   360     report[4]=0x63; //Command ID
   361     report[5]=0x50; //Command ID
   362     report[6]=0x4D; //Command ID
   363     Write(report);
   364     }
   365 
   366 
   367 /**
   368 This is for development purposes only.
   369 Production application should stick to off-screen mode to avoid tearing.
   370 */
   371 void GP1212A01A::ToggleOffScreenMode()
   372 	{
   373 	iOffScreenMode=!iOffScreenMode;
   374 	//Clean up our buffers upon switching modes	
   375 	SetDisplayPosition(0,0);
   376 	Clear();
   377 	SwapBuffers();
   378 	Clear();
   379 	}