src/FutabaVfd.cpp
author sl
Tue, 27 May 2014 17:49:33 +0200
changeset 27 ee1305f3a6bf
parent 25 233a997193b8
permissions -rw-r--r--
Experimenting with our bitmap to bitarray convertion.
     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():
    75 	iDisplayPositionX(0),iDisplayPositionY(0),
    76 	iOffScreenMode(true),iFrameBuffer(NULL)
    77 	{
    78 	//ResetBuffers();
    79 	}
    80 
    81 /**
    82 */
    83 GP1212A01A::~GP1212A01A()
    84 	{
    85 	delete iFrameBuffer;
    86 	iFrameBuffer=NULL;
    87 	}
    88 
    89 /**
    90 */
    91 int GP1212A01A::Open()
    92 	{
    93 	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    94 	if (success)
    95 		{
    96 		delete iFrameBuffer;
    97 		iFrameBuffer = NULL;
    98 		iFrameBuffer=new BitArray(KGP12xFrameBufferPixelCount);
    99 		SetNonBlocking(1);
   100 		//Since we can't get our display position we for it to our default
   101 		//This makes sure frames are in sync from the start
   102 		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
   103 		//Now clear both front and back buffer on host and device
   104 		Clear();
   105 		SwapBuffers();
   106 		Clear();
   107 		SwapBuffers();
   108 		}
   109 	return success;
   110 	}
   111 
   112 /**
   113 */
   114 void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
   115 	{
   116 	//Just specify a one pixel block
   117 	//SetPixelBlock(aX,aY,0x00,0x01,aOn);
   118 	//
   119 	//int byteOffset=(aX*HeightInPixels()+aY)/8;
   120 	//int bitOffset=(aX*HeightInPixels()+aY)%8;
   121 	//iFrameBuffer[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
   122 	if (aOn)
   123 		{
   124 		iFrameBuffer->SetBit(aX*HeightInPixels()+aY);
   125 		}
   126 	else
   127 		{
   128 		iFrameBuffer->ClearBit(aX*HeightInPixels()+aY);
   129 		}
   130 	}
   131 
   132 /**
   133 */
   134 void GP1212A01A::BitBlit(BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
   135 	{
   136 	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
   137 	for (int i=0;i<aSrcWidth;i++)
   138 		{
   139 		for (int j=0;j<aSrcHeight;j++)
   140 			{
   141 			iFrameBuffer->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
   142 			}
   143 		}
   144 	}
   145 
   146 /**
   147 Set all pixels on our screen to the desired value.
   148 This operation is performed off screen to avoid tearing.
   149 @param 8 pixels pattern
   150 */
   151 void GP1212A01A::SetAllPixels(unsigned char aPattern)
   152 	{
   153 	//With a single buffer
   154 	//unsigned char screen[2048]; //One screen worth of pixels
   155 	//memset(screen,0xFF,sizeof(screen));
   156 	//SetPixelBlock(0,0,63,sizeof(screen),screen);
   157 
   158 	//Using pattern SetPixelBlock variant.
   159 	memset(iFrameBuffer->Ptr(),aPattern,FrameBufferSizeInBytes());
   160 	//
   161 
   162 
   163 	}
   164 
   165 /**
   166 Set our screen brightness.
   167 @param The desired brightness level. Must be between MinBrightness and MaxBrightness.
   168 */
   169 void GP1212A01A::SetBrightness(int aBrightness)
   170     {
   171 	if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
   172         {
   173         //Brightness out of range.
   174         //Just ignore that request.
   175         return;
   176         }
   177 
   178     FutabaVfdReport report;
   179     report[0]=0x00; //Report ID
   180     report[1]=0x06; //Report size
   181     report[2]=0x1B; //Command ID
   182     report[3]=0x5C; //Command ID
   183     report[4]=0x3F; //Command ID
   184     report[5]=0x4C; //Command ID
   185     report[6]=0x44; //Command ID
   186     report[7]=0x30+aBrightness; //Brightness level
   187     Write(report);
   188 
   189 	}
   190 
   191 /**
   192 Set the defined pixel block to the given value.
   193 @param X coordinate of our pixel block starting point.
   194 @param Y coordinate of our pixel block starting point.
   195 @param The height of our pixel block.
   196 @param The size of our pixel data. Number of pixels divided by 8.
   197 @param The value set to 8 pixels used as a pattern.
   198 */
   199 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
   200 	{
   201 	OffScreenTranslation(aX,aY);
   202     FutabaVfdReport report;
   203     report[0]=0x00; //Report ID
   204     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
   205     report[2]=0x1B; //Command ID
   206     report[3]=0x5B; //Command ID
   207     report[4]=0xF0; //Command ID
   208     report[5]=aX;   //X
   209     report[6]=aY;   //Y
   210     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.
   211 	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   212 	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   213     int sizeWritten=MIN(aSize,report.Size()-10);
   214     memset(report.Buffer()+10, aValue, sizeWritten);
   215     Write(report);
   216 
   217     int remainingSize=aSize;
   218     //We need to keep on sending our pixel data until we are done
   219     while (report[1]==64)
   220         {
   221         report.Reset();
   222         remainingSize-=sizeWritten;
   223         report[0]=0x00; //Report ID
   224         report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   225         sizeWritten=(report[1]==64?63:report[1]);
   226         memset(report.Buffer()+2, aValue, sizeWritten);
   227         Write(report);
   228         }
   229 	}
   230 
   231 /**
   232 Set the defined pixel block to the given value.
   233 @param X coordinate of our pixel block starting point.
   234 @param Y coordinate of our pixel block starting point.
   235 @param The height of our pixel block.
   236 @param The size of our pixel data. Number of pixels divided by 8.
   237 @param Pointer to our pixel data.
   238 */
   239 void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   240     {
   241 	OffScreenTranslation(aX,aY);
   242     FutabaVfdReport report;
   243     report[0]=0x00; //Report ID
   244     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
   245     report[2]=0x1B; //Command ID
   246     report[3]=0x5B; //Command ID
   247     report[4]=0xF0; //Command ID
   248     report[5]=aX;   //X
   249     report[6]=aY;   //Y
   250     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.
   251 	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   252 	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   253     int sizeWritten=MIN(aSize,report.Size()-10);
   254     memcpy(report.Buffer()+10, aPixels, sizeWritten);
   255     Write(report);
   256 
   257     int remainingSize=aSize;
   258     //We need to keep on sending our pixel data until we are done
   259     while (report[1]==64)
   260         {
   261         report.Reset();
   262         remainingSize-=sizeWritten;
   263         report[0]=0x00; //Report ID
   264         report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   265         sizeWritten=(report[1]==64?63:report[1]);
   266         memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   267         Write(report);
   268         }
   269     }
   270 
   271 
   272 /**
   273 Clear our client side back buffer.
   274 Call to SwapBuffers must follow to actually clear the display.
   275 */
   276 void GP1212A01A::Clear()
   277 	{
   278 	//memset(iFrameBuffer->Ptr(),0x00,FrameBufferSizeInBytes());
   279 	iFrameBuffer->ClearAll();
   280 	}
   281 
   282 /**
   283 Using this function is advised against as is causes tearing.
   284 Use Clear instead.
   285 */
   286 void GP1212A01A::SendClearCommand()
   287 	{
   288     //1BH,5BH,32H,4AH
   289     //Send Clear Display Command
   290 	FutabaVfdReport report;
   291 	report[0]=0x00; //Report ID
   292 	report[1]=0x04; //Report length
   293 	report[2]=0x1B; //Command ID
   294 	report[3]=0x5B; //Command ID
   295 	report[4]=0x32; //Command ID
   296 	report[5]=0x4A; //Command ID
   297 	Write(report);
   298 	}
   299 
   300 /**
   301 Change our display position within our buffer.
   302 */
   303 void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   304     {
   305     //1BH,5BH,Dw,Px,Py
   306     //Send Display Position Settings Command
   307     FutabaVfdReport report;
   308     report[0]=0x00; //Report ID
   309     report[1]=0x05; //Report length
   310     report[2]=0x1B; //Command ID
   311     report[3]=0x5B; //Command ID
   312     report[4]=aDw;  //Specify our DW
   313     report[5]=aX;   //X coordinate of our DW top-left corner
   314     report[6]=aY;   //Y coordinate of our DW top-left corner
   315     Write(report);
   316     }
   317 
   318 /**
   319 Change our display position within our buffer.
   320 */
   321 void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   322 	{
   323 	//Specs apparently says both DW should remain the same
   324 	//Just don't ask
   325     SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   326     SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   327 	iDisplayPositionX=aX;
   328 	iDisplayPositionY=aY;
   329 	}
   330 
   331 /**
   332 Provide Y coordinate of our off screen buffer.
   333 */
   334 unsigned char GP1212A01A::OffScreenY() const
   335 	{
   336 	//Overflowing is fine this is just what we want
   337 	return iDisplayPositionY+HeightInPixels();
   338 	}
   339 
   340 /**
   341 Put our off screen buffer on screen.
   342 On screen buffer goes off screen.
   343 */
   344 void GP1212A01A::SwapBuffers()
   345 	{
   346 	//Only perform buffer swapping if off screen mode is enabled
   347 	if (OffScreenMode())
   348 		{
   349 		//Send host back buffer to device back buffer
   350 		SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameBuffer->Ptr());
   351 		//Swap device front and back buffer
   352 		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   353 		//Swap host buffers
   354 		//unsigned char* backBuffer=iBackBuffer;
   355 		//iBackBuffer = iFrontBuffer;
   356 		//iFrontBuffer = backBuffer;
   357 		}
   358 	}
   359 
   360 /**
   361 Translate the given pixel coordinate according to our off screen mode.
   362 */
   363 void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   364 	{
   365 	if (OffScreenMode())
   366 		{
   367 		aX+=WidthInPixels()-iDisplayPositionX;
   368 		aY+=HeightInPixels()-iDisplayPositionY;
   369 		}
   370 	}
   371 
   372 
   373 /**
   374 */
   375 void GP1212A01A::ResetBuffers()
   376 	{
   377 	//iFrameBuffer->ClearAll();
   378 	//memset(iFrameBuffer,0x00,sizeof(iFrameBuffer));
   379 	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
   380 	}
   381 
   382 /**
   383 */
   384 void GP1212A01A::RequestId()
   385     {
   386     //1BH,5BH,63H,49H,44H
   387     //Send Read ID command
   388     FutabaVfdReport report;
   389     report[0]=0x00; //Report ID
   390     report[1]=0x05; //Report length
   391     report[2]=0x1B; //Command ID
   392     report[3]=0x5B; //Command ID
   393     report[4]=0x63; //Command ID
   394     report[5]=0x49; //Command ID
   395     report[6]=0x44; //Command ID
   396     Write(report);
   397     }
   398 
   399 /**
   400 */
   401 void GP1212A01A::RequestFirmwareRevision()
   402     {
   403     //1BH,5BH,63H,46H,52H
   404     //Send Software Revision Read Command
   405     FutabaVfdReport report;
   406     report[0]=0x00; //Report ID
   407     report[1]=0x05; //Report length
   408     report[2]=0x1B; //Command ID
   409     report[3]=0x5B; //Command ID
   410     report[4]=0x63; //Command ID
   411     report[5]=0x46; //Command ID
   412     report[6]=0x52; //Command ID
   413     Write(report);
   414     }
   415 
   416 /**
   417 */
   418 void GP1212A01A::RequestPowerSupplyStatus()
   419     {
   420     //1BH,5BH,63H,50H,4DH
   421     //Send Power Suppply Monitor Command
   422     FutabaVfdReport report;
   423     report[0]=0x00; //Report ID
   424     report[1]=0x05; //Report length
   425     report[2]=0x1B; //Command ID
   426     report[3]=0x5B; //Command ID
   427     report[4]=0x63; //Command ID
   428     report[5]=0x50; //Command ID
   429     report[6]=0x4D; //Command ID
   430     Write(report);
   431     }
   432 
   433 
   434 /**
   435 This is for development purposes only.
   436 Production application should stick to off-screen mode to avoid tearing.
   437 */
   438 void GP1212A01A::ToggleOffScreenMode()
   439 	{
   440 	iOffScreenMode=!iOffScreenMode;
   441 	//Clean up our buffers upon switching modes	
   442 	SetDisplayPosition(0,0);
   443 	Clear();
   444 	SwapBuffers();
   445 	Clear();
   446 	}