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@25: GP1212A01A::GP1212A01A(): sl@25: iDisplayPositionX(0),iDisplayPositionY(0), sl@25: iOffScreenMode(true),iFrameBuffer(NULL) sl@23: { sl@25: //ResetBuffers(); sl@23: } sl@23: sl@25: /** sl@25: */ sl@25: GP1212A01A::~GP1212A01A() sl@25: { sl@25: delete iFrameBuffer; sl@25: iFrameBuffer=NULL; sl@25: } sl@25: sl@25: /** sl@25: */ sl@10: int GP1212A01A::Open() sl@10: { sl@10: int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL); sl@10: if (success) sl@10: { sl@25: delete iFrameBuffer; sl@25: iFrameBuffer = NULL; sl@25: iFrameBuffer=new BitArray(KGP12xFrameBufferPixelCount); 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@25: //Now clear both front and back buffer on host and device sl@25: Clear(); sl@25: SwapBuffers(); sl@25: Clear(); sl@25: SwapBuffers(); 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@25: //SetPixelBlock(aX,aY,0x00,0x01,aOn); sl@25: // sl@25: //int byteOffset=(aX*HeightInPixels()+aY)/8; sl@25: //int bitOffset=(aX*HeightInPixels()+aY)%8; sl@25: //iFrameBuffer[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset ); sl@25: if (aOn) sl@25: { sl@25: iFrameBuffer->SetBit(aX*HeightInPixels()+aY); sl@25: } sl@25: else sl@25: { sl@25: iFrameBuffer->ClearBit(aX*HeightInPixels()+aY); sl@25: } sl@25: } sl@25: sl@25: /** sl@25: */ sl@26: void GP1212A01A::BitBlit(BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const sl@25: { sl@26: //TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions. sl@25: for (int i=0;iSetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]); sl@25: } sl@25: } 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@25: memset(iFrameBuffer->Ptr(),aPattern,FrameBufferSizeInBytes()); sl@25: // sl@25: sl@25: 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@25: Clear our client side back buffer. sl@25: Call to SwapBuffers must follow to actually clear the display. sl@10: */ sl@10: void GP1212A01A::Clear() sl@10: { sl@25: //memset(iFrameBuffer->Ptr(),0x00,FrameBufferSizeInBytes()); sl@25: iFrameBuffer->ClearAll(); 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@25: //Send host back buffer to device back buffer sl@25: SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameBuffer->Ptr()); sl@25: //Swap device front and back buffer sl@23: SetDisplayPosition(iDisplayPositionX,OffScreenY()); sl@25: //Swap host buffers sl@25: //unsigned char* backBuffer=iBackBuffer; sl@25: //iBackBuffer = iFrontBuffer; sl@25: //iFrontBuffer = backBuffer; 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@25: sl@25: sl@25: /** sl@25: */ sl@25: void GP1212A01A::ResetBuffers() sl@25: { sl@25: //iFrameBuffer->ClearAll(); sl@25: //memset(iFrameBuffer,0x00,sizeof(iFrameBuffer)); sl@25: //memset(iFrameBeta,0x00,sizeof(iFrameBeta)); sl@25: } sl@25: 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: }