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