sl@4: sl@4: #include "FutabaVfd.h" sl@4: //#include sl@4: #include sl@4: sl@4: sl@4: // sl@4: // sl@4: // sl@4: sl@4: sl@4: sl@4: sl@4: sl@4: // sl@4: // sl@4: // sl@4: sl@4: FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0) sl@4: { sl@4: } sl@4: sl@4: FutabaVfdCommand::~FutabaVfdCommand() sl@4: { sl@4: //Delete(); sl@4: } sl@4: sl@4: sl@4: /** sl@4: sl@4: */ sl@4: void FutabaVfdCommand::Reset() sl@4: { sl@4: memset(iReports,0,sizeof(iReports)); sl@4: } sl@4: sl@4: sl@4: sl@4: /** sl@4: sl@4: */ sl@4: /* sl@4: void FutabaVfdCommand::Create(int aMaxSize) sl@4: { sl@4: iBuffer=new unsigned char[aMaxSize]; sl@4: if (iBuffer) sl@4: { sl@4: iMaxSize = aMaxSize; sl@4: iSize = 0; sl@4: } sl@4: } sl@4: */ sl@4: sl@4: /** sl@4: sl@4: */ sl@4: /* sl@4: void FutabaVfdCommand::Delete() sl@4: { sl@4: delete[] iBuffer; sl@4: iBuffer = NULL; sl@4: iMaxSize = 0; sl@4: iSize = 0; sl@4: } sl@4: */ sl@4: sl@4: sl@4: sl@4: sl@4: // sl@4: // class GP1212A01A sl@4: // sl@4: sl@4: GP1212A01A::GP1212A01A(): sl@4: iDisplayPositionX(0),iDisplayPositionY(0), sl@4: iOffScreenMode(true),iFrameBuffer(NULL) sl@4: { sl@4: //ResetBuffers(); sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: GP1212A01A::~GP1212A01A() sl@4: { sl@4: delete iFrameBuffer; sl@4: iFrameBuffer=NULL; sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: int GP1212A01A::Open() sl@4: { sl@4: int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL); sl@4: if (success) sl@4: { sl@4: delete iFrameBuffer; sl@4: iFrameBuffer = NULL; sl@4: iFrameBuffer=new BitArray(KGP12xFrameBufferPixelCount); sl@4: SetNonBlocking(1); sl@4: //Since we can't get our display position we for it to our default sl@4: //This makes sure frames are in sync from the start sl@4: SetDisplayPosition(iDisplayPositionX,iDisplayPositionY); sl@4: //Now clear both front and back buffer on host and device sl@4: Clear(); sl@4: SwapBuffers(); sl@4: Clear(); sl@4: SwapBuffers(); sl@4: } sl@4: return success; sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn) sl@4: { sl@4: //Just specify a one pixel block sl@4: //SetPixelBlock(aX,aY,0x00,0x01,aOn); sl@4: // sl@4: //int byteOffset=(aX*HeightInPixels()+aY)/8; sl@4: //int bitOffset=(aX*HeightInPixels()+aY)%8; sl@4: //iFrameBuffer[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset ); sl@4: if (aOn) sl@4: { sl@4: iFrameBuffer->SetBit(aX*HeightInPixels()+aY); sl@4: } sl@4: else sl@4: { sl@4: iFrameBuffer->ClearBit(aX*HeightInPixels()+aY); sl@4: } sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: void GP1212A01A::BitBlit(BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const sl@4: { sl@4: //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions. sl@4: for (int i=0;iSetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]); sl@4: } sl@4: } sl@4: } sl@4: sl@4: /** sl@4: Set all pixels on our screen to the desired value. sl@4: This operation is performed off screen to avoid tearing. sl@4: @param 8 pixels pattern sl@4: */ sl@4: void GP1212A01A::SetAllPixels(unsigned char aPattern) sl@4: { sl@4: //With a single buffer sl@4: //unsigned char screen[2048]; //One screen worth of pixels sl@4: //memset(screen,0xFF,sizeof(screen)); sl@4: //SetPixelBlock(0,0,63,sizeof(screen),screen); sl@4: sl@4: //Using pattern SetPixelBlock variant. sl@4: memset(iFrameBuffer->Ptr(),aPattern,FrameBufferSizeInBytes()); sl@4: // sl@4: sl@4: sl@4: } sl@4: sl@4: /** sl@4: Set our screen brightness. sl@4: @param The desired brightness level. Must be between MinBrightness and MaxBrightness. sl@4: */ sl@4: void GP1212A01A::SetBrightness(int aBrightness) sl@4: { sl@4: if (aBrightnessMaxBrightness()) sl@4: { sl@4: //Brightness out of range. sl@4: //Just ignore that request. sl@4: return; sl@4: } sl@4: sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=0x06; //Report size sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5C; //Command ID sl@4: report[4]=0x3F; //Command ID sl@4: report[5]=0x4C; //Command ID sl@4: report[6]=0x44; //Command ID sl@4: report[7]=0x30+aBrightness; //Brightness level sl@4: Write(report); sl@4: sl@4: } sl@4: sl@4: /** sl@4: Set the defined pixel block to the given value. sl@4: @param X coordinate of our pixel block starting point. sl@4: @param Y coordinate of our pixel block starting point. sl@4: @param The height of our pixel block. sl@4: @param The size of our pixel data. Number of pixels divided by 8. sl@4: @param The value set to 8 pixels used as a pattern. sl@4: */ sl@4: void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue) sl@4: { sl@4: OffScreenTranslation(aX,aY); sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: 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 sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=0xF0; //Command ID sl@4: report[5]=aX; //X sl@4: report[6]=aY; //Y sl@4: 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. sl@4: report[8]=aSize>>8; //Size of pixel data in bytes (MSB) sl@4: report[9]=aSize; //Size of pixel data in bytes (LSB) sl@4: int sizeWritten=MIN(aSize,report.Size()-10); sl@4: memset(report.Buffer()+10, aValue, sizeWritten); sl@4: Write(report); sl@4: sl@4: int remainingSize=aSize; sl@4: //We need to keep on sending our pixel data until we are done sl@4: while (report[1]==64) sl@4: { sl@4: report.Reset(); sl@4: remainingSize-=sizeWritten; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size sl@4: sizeWritten=(report[1]==64?63:report[1]); sl@4: memset(report.Buffer()+2, aValue, sizeWritten); sl@4: Write(report); sl@4: } sl@4: } sl@4: sl@4: /** sl@4: Set the defined pixel block to the given value. sl@4: @param X coordinate of our pixel block starting point. sl@4: @param Y coordinate of our pixel block starting point. sl@4: @param The height of our pixel block. sl@4: @param The size of our pixel data. Number of pixels divided by 8. sl@4: @param Pointer to our pixel data. sl@4: */ sl@4: void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels) sl@4: { sl@4: OffScreenTranslation(aX,aY); sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: 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 sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=0xF0; //Command ID sl@4: report[5]=aX; //X sl@4: report[6]=aY; //Y sl@4: 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. sl@4: report[8]=aSize>>8; //Size of pixel data in bytes (MSB) sl@4: report[9]=aSize; //Size of pixel data in bytes (LSB) sl@4: int sizeWritten=MIN(aSize,report.Size()-10); sl@4: memcpy(report.Buffer()+10, aPixels, sizeWritten); sl@4: Write(report); sl@4: sl@4: int remainingSize=aSize; sl@4: //We need to keep on sending our pixel data until we are done sl@4: while (report[1]==64) sl@4: { sl@4: report.Reset(); sl@4: remainingSize-=sizeWritten; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size sl@4: sizeWritten=(report[1]==64?63:report[1]); sl@4: memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten); sl@4: Write(report); sl@4: } sl@4: } sl@4: sl@4: sl@4: /** sl@4: Clear our client side back buffer. sl@4: Call to SwapBuffers must follow to actually clear the display. sl@4: */ sl@4: void GP1212A01A::Clear() sl@4: { sl@4: //memset(iFrameBuffer->Ptr(),0x00,FrameBufferSizeInBytes()); sl@4: iFrameBuffer->ClearAll(); sl@4: } sl@4: sl@4: /** sl@4: Using this function is advised against as is causes tearing. sl@4: Use Clear instead. sl@4: */ sl@4: void GP1212A01A::SendClearCommand() sl@4: { sl@4: //1BH,5BH,32H,4AH sl@4: //Send Clear Display Command sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=0x04; //Report length sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=0x32; //Command ID sl@4: report[5]=0x4A; //Command ID sl@4: Write(report); sl@4: } sl@4: sl@4: /** sl@4: Change our display position within our buffer. sl@4: */ sl@4: void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY) sl@4: { sl@4: //1BH,5BH,Dw,Px,Py sl@4: //Send Display Position Settings Command sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=0x05; //Report length sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=aDw; //Specify our DW sl@4: report[5]=aX; //X coordinate of our DW top-left corner sl@4: report[6]=aY; //Y coordinate of our DW top-left corner sl@4: Write(report); sl@4: } sl@4: sl@4: /** sl@4: Change our display position within our buffer. sl@4: */ sl@4: void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY) sl@4: { sl@4: //Specs apparently says both DW should remain the same sl@4: //Just don't ask sl@4: SetDisplayPosition(GP1212A01A::DW1,aX,aY); sl@4: SetDisplayPosition(GP1212A01A::DW2,aX,aY); sl@4: iDisplayPositionX=aX; sl@4: iDisplayPositionY=aY; sl@4: } sl@4: sl@4: /** sl@4: Provide Y coordinate of our off screen buffer. sl@4: */ sl@4: unsigned char GP1212A01A::OffScreenY() const sl@4: { sl@4: //Overflowing is fine this is just what we want sl@4: return iDisplayPositionY+HeightInPixels(); sl@4: } sl@4: sl@4: /** sl@4: Put our off screen buffer on screen. sl@4: On screen buffer goes off screen. sl@4: */ sl@4: void GP1212A01A::SwapBuffers() sl@4: { sl@4: //Only perform buffer swapping if off screen mode is enabled sl@4: if (OffScreenMode()) sl@4: { sl@4: //Send host back buffer to device back buffer sl@4: SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameBuffer->Ptr()); sl@4: //Swap device front and back buffer sl@4: SetDisplayPosition(iDisplayPositionX,OffScreenY()); sl@4: //Swap host buffers sl@4: //unsigned char* backBuffer=iBackBuffer; sl@4: //iBackBuffer = iFrontBuffer; sl@4: //iFrontBuffer = backBuffer; sl@4: } sl@4: } sl@4: sl@4: /** sl@4: Translate the given pixel coordinate according to our off screen mode. sl@4: */ sl@4: void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY) sl@4: { sl@4: if (OffScreenMode()) sl@4: { sl@4: aX+=WidthInPixels()-iDisplayPositionX; sl@4: aY+=HeightInPixels()-iDisplayPositionY; sl@4: } sl@4: } sl@4: sl@4: sl@4: /** sl@4: */ sl@4: void GP1212A01A::ResetBuffers() sl@4: { sl@4: //iFrameBuffer->ClearAll(); sl@4: //memset(iFrameBuffer,0x00,sizeof(iFrameBuffer)); sl@4: //memset(iFrameBeta,0x00,sizeof(iFrameBeta)); sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: void GP1212A01A::RequestId() sl@4: { sl@4: //1BH,5BH,63H,49H,44H sl@4: //Send Read ID command sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=0x05; //Report length sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=0x63; //Command ID sl@4: report[5]=0x49; //Command ID sl@4: report[6]=0x44; //Command ID sl@4: Write(report); sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: void GP1212A01A::RequestFirmwareRevision() sl@4: { sl@4: //1BH,5BH,63H,46H,52H sl@4: //Send Software Revision Read Command sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=0x05; //Report length sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=0x63; //Command ID sl@4: report[5]=0x46; //Command ID sl@4: report[6]=0x52; //Command ID sl@4: Write(report); sl@4: } sl@4: sl@4: /** sl@4: */ sl@4: void GP1212A01A::RequestPowerSupplyStatus() sl@4: { sl@4: //1BH,5BH,63H,50H,4DH sl@4: //Send Power Suppply Monitor Command sl@4: FutabaVfdReport report; sl@4: report[0]=0x00; //Report ID sl@4: report[1]=0x05; //Report length sl@4: report[2]=0x1B; //Command ID sl@4: report[3]=0x5B; //Command ID sl@4: report[4]=0x63; //Command ID sl@4: report[5]=0x50; //Command ID sl@4: report[6]=0x4D; //Command ID sl@4: Write(report); sl@4: } sl@4: sl@4: sl@4: /** sl@4: This is for development purposes only. sl@4: Production application should stick to off-screen mode to avoid tearing. sl@4: */ sl@4: void GP1212A01A::ToggleOffScreenMode() sl@4: { sl@4: iOffScreenMode=!iOffScreenMode; sl@4: //Clean up our buffers upon switching modes sl@4: SetDisplayPosition(0,0); sl@4: Clear(); sl@4: SwapBuffers(); sl@4: Clear(); sl@4: }