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