# HG changeset patch # User sl # Date 1408649438 -7200 # Node ID 5a9dbbc40c6b3681a8996b4d922a27cdfa8c16d1 # Parent 8bac7aac665ca1d5ded6ace72ed6c1c977bd12c1 Ground work to support multiple type of display, notably GP1212A02 diff -r 8bac7aac665c -r 5a9dbbc40c6b CMakeLists.txt --- a/CMakeLists.txt Sat Jul 12 13:15:31 2014 +0200 +++ b/CMakeLists.txt Thu Aug 21 21:30:38 2014 +0200 @@ -10,10 +10,26 @@ set (LIB_TYPE SHARED) endif (MD_SHARED_LIB) -set(SOURCES BitArray.cpp FutabaVfd.cpp HidDevice.cpp MiniDisplay.cpp ../../GitHub/hidapi/windows/hid.c) +set(SOURCES BitArray.cpp + FutabaVfd.cpp + FutabaGP1212.cpp + FutabaGP1212A01.cpp + FutabaGP1212A02.cpp + HidDevice.cpp + MiniDisplay.cpp + ../../GitHub/hidapi/windows/hid.c) + source_group(Souces FILES ${SOURCES}) -set(INCLUDES BitArray.h FutabaVfd.h HidDevice.h HidReport.h MiniDisplay.h) +set(INCLUDES BitArray.h + FutabaVfd.h + FutabaGP1212.h + FutabaGP1212A01.h + FutabaGP1212A02.h + HidDevice.h + HidReport.h + MiniDisplay.h) + source_group(Includes FILES ${INCLUDES}) include_directories(../../GitHub/hidapi/hidapi) diff -r 8bac7aac665c -r 5a9dbbc40c6b Display.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Display.h Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,39 @@ +// +// +// + +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "HidDevice.h" + +/** +Define an interface to some basic display functionality +*/ +class DisplayBase : public HidDevice + { +public: + virtual int MinBrightness() const=0; + virtual int MaxBrightness() const=0; + virtual void SetBrightness(int aBrightness)=0; + virtual void Clear()=0; + }; + + +/** +*/ +class GraphicDisplay : public DisplayBase + { +public: + virtual int WidthInPixels() const=0; + virtual int HeightInPixels() const=0; + virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn)=0; + virtual void SetAllPixels(unsigned char aOn)=0; + virtual int FrameBufferSizeInBytes() const=0; + //virtual int BitBlit(unsigned char* aSrc, unsigned char aSrcWidth, unsigned char aSrcHeight, unsigned char aTargetX, unsigned char aTargetY) const=0; + + }; + + + +#endif diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaGP1212.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FutabaGP1212.cpp Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,5 @@ +// +// +// + +#include "FutabaGP1212.h" \ No newline at end of file diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaGP1212.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FutabaGP1212.h Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,24 @@ +// +// +// + +#ifndef FUTABA_GP1212_H +#define FUTABA_GP1212_H + +#include "Display.h" + + +/** +Common functionality between GP1212A01A and GP1212A02A +*/ +class GP1212XXXX : public GraphicDisplay + { +public: + //From FutabaVfd + virtual int MinBrightness() const {return 0;} + virtual int MaxBrightness() const {return 5;} + }; + + + +#endif diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaGP1212A01.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FutabaGP1212A01.cpp Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,670 @@ +// +// +// + +#include "FutabaGP1212A01.h" + +const int KNumberOfFrameBeforeDiffAlgo = 3; + +// +// class GP1212A01A +// + +GP1212A01A::GP1212A01A(): + iDisplayPositionX(0),iDisplayPositionY(0), + iOffScreenMode(true), + iUseFrameDifferencing(true), + iFrameNext(NULL), + iFrameCurrent(NULL), + iFramePrevious(NULL), + iFrameAlpha(NULL), + iFrameBeta(NULL), + iFrameGamma(NULL), + iNeedFullFrameUpdate(0), + iRequest(EMiniDisplayRequestNone),iPowerOn(false) + { + iDeviceId[0]=0; + iFirmwareRevision[0]=0; + //ResetBuffers(); + } + +/** +*/ +GP1212A01A::~GP1212A01A() + { + delete iFrameAlpha; + iFrameAlpha=NULL; + // + delete iFrameBeta; + iFrameBeta=NULL; + // + delete iFrameGamma; + iFrameGamma=NULL; + // + iFrameNext=NULL; + iFrameCurrent=NULL; + iFramePrevious=NULL; + // + iNeedFullFrameUpdate=0; + } + +/** +*/ +int GP1212A01A::Open() + { + int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL); + if (success) + { + //Allocate both frames + delete iFrameAlpha; + iFrameAlpha=NULL; + iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount); + // + delete iFrameBeta; + iFrameBeta=NULL; + iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount); + // + delete iFrameGamma; + iFrameGamma=NULL; + iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount); + // + iFrameNext=iFrameAlpha; + iFrameCurrent=iFrameBeta; + iFramePrevious=iFrameGamma; + + + //To make sure it is synced properly + iNeedFullFrameUpdate=0; + // + SetNonBlocking(1); + //Since we can't get our display position we force it to our default + //This makes sure frames are in sync from the start + //Clever clients will have taken care of putting back frame (0,0) before closing + SetDisplayPosition(iDisplayPositionX,iDisplayPositionY); + } + return success; + } + +/** +*/ +void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn) + { + // + //int byteOffset=(aX*HeightInPixels()+aY)/8; + //int bitOffset=(aX*HeightInPixels()+aY)%8; + //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset ); + + if (iOffScreenMode) + { + if (aOn) + { + iFrameNext->SetBit(aX*HeightInPixels()+aY); + } + else + { + iFrameNext->ClearBit(aX*HeightInPixels()+aY); + } + } + else + { + //Just specify a one pixel block + SetPixelBlock(aX,aY,0x00,0x01,aOn); + } + } + +/** +*/ +void GP1212A01A::BitBlit(const 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]); + } + } + } + +/** +Clear our client side back buffer. +Call to SwapBuffers must follow to actually clear the display. +*/ +void GP1212A01A::Clear() + { + //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes()); + if (iOffScreenMode) + { + iFrameNext->ClearAll(); + } + else + { + SendClearCommand(); + } + } + +/** +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); + + + if (iOffScreenMode) + { + memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes()); + } + else + { + //Using pattern SetPixelBlock variant. + SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern); + } + // + } + + +/** +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); + } + } + +/** +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 + if (!iUseFrameDifferencing || iNeedFullFrameUpdatePtr()); + } + else + { + //Frame diff algo is enabled + //We are going to send to our device only the differences between next frame and previous frame + SendModifiedPixelBlocks(); + } + //Swap device front and back buffer + SetDisplayPosition(iDisplayPositionX,OffScreenY()); + + //Cycle through our frame buffers + //We keep track of previous frame which is in fact our device back buffer. + //We can then compare previous and next frame and send only the differences to our device. + //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS. + //Keep our previous frame pointer + BitArray* previousFrame=iFramePrevious; + //Current frame becomes the previous one + iFramePrevious = iFrameCurrent; + //Next frame becomes the current one + iFrameCurrent = iFrameNext; + //Next frame is now our former previous + iFrameNext = previousFrame; + } + } + + +//Define the edge of our pixel block +//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii. +//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be. +const int KPixelBlockEdge = 32; +const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge; +const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8; + + +/** + * @brief GP1212A01A::SendModifiedPixelBlocks + * Compare our back and front buffer and send to the device only the modified pixels. + */ +void GP1212A01A::SendModifiedPixelBlocks() + { + int w=WidthInPixels(); + int h=HeightInPixels(); + + + //TODO: optimize with memcmp and 16 inc + /* + + for (int i=0;iPtr()+offset); + } + } + } + */ + + BitArray nextBlock(KPixelBlockSizeInBits); + BitArray previousBlock(KPixelBlockSizeInBits); + + for (int i=0;iPtr()+offset,iFramePrevious->Ptr()+offset,32 )) //32=(16*16/8) + if (memcmp(nextBlock.Ptr(),previousBlock.Ptr(),KPixelBlockSizeInBytes)!=0) + { + //We need to update that block + SetPixelBlock(i,j,KPixelBlockEdge-1,KPixelBlockSizeInBytes,nextBlock.Ptr()); + //SetPixelBlock(i,j,15,32,0xFF/*nextBlock.Ptr()*/); + //SetDisplayPosition(iDisplayPositionX,OffScreenY()); + //SetDisplayPosition(iDisplayPositionX,OffScreenY()); + + //SetPixelBlock(i,j,15,32,iFrameNext->Ptr()+offset); + } + } + } + + } + +/** +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() + { + //iNextFrame->ClearAll(); + //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha)); + //memset(iFrameBeta,0x00,sizeof(iFrameBeta)); + } + +/** +*/ +void GP1212A01A::RequestDeviceId() + { + if (RequestPending()) + { + //Abort silently for now + return; + } + + //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 + if (Write(report)==report.Size()) + { + iRequest=EMiniDisplayRequestDeviceId; + } + } + +/** +*/ +void GP1212A01A::RequestFirmwareRevision() + { + if (RequestPending()) + { + //Abort silently for now + return; + } + + //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 + if (Write(report)==report.Size()) + { + iRequest=EMiniDisplayRequestFirmwareRevision; + } + } + +/** +*/ +void GP1212A01A::RequestPowerSupplyStatus() + { + if (RequestPending()) + { + //Abort silently for now + return; + } + //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 + if (Write(report)==report.Size()) + { + iRequest=EMiniDisplayRequestPowerSupplyStatus; + } + } + + +/** +This is for development purposes only. +Production application should stick to off-screen mode to avoid tearing. +*/ +void GP1212A01A::ToggleOffScreenMode() + { + SetOffScreenMode(!iOffScreenMode); + } + +/** + * @brief GP1212A01A::SetOffScreenMode + * @param aOn + * @return + */ +void GP1212A01A::SetOffScreenMode(bool aOn) + { + if (aOn==iOffScreenMode) + { + //Nothing to do here + return; + } + + iOffScreenMode=aOn; + + //Clean up our buffers upon switching modes + SetDisplayPosition(0,0); + Clear(); + SwapBuffers(); + Clear(); + } + +/** +Tries to complete our current request if we have one pending. + */ +TMiniDisplayRequest GP1212A01A::AttemptRequestCompletion() + { + if (!RequestPending()) + { + return EMiniDisplayRequestNone; + } + + int res=Read(iInputReport); + + if (!res) + { + return EMiniDisplayRequestNone; + } + + //Process our request + if (CurrentRequest()==EMiniDisplayRequestPowerSupplyStatus) + { + if (iInputReport[1]==0x4F && iInputReport[2]==0x4E) + { + iPowerOn = true; + } + else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46) + { + iPowerOn = false; + } + } + else if (CurrentRequest()==EMiniDisplayRequestDeviceId) + { + unsigned char* ptr=&iInputReport[1]; + strcpy(iDeviceId,(const char*)ptr); + } + else if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision) + { + unsigned char* ptr=&iInputReport[1]; + strcpy(iFirmwareRevision,(const char*)ptr); + } + + TMiniDisplayRequest completed=iRequest; + //Our request was completed + iRequest=EMiniDisplayRequestNone; + + return completed; + } + + +/** +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); + } + +/** +*/ +bool GP1212A01A::PowerOn() + { + return iPowerOn; + } + +/** +*/ +char* GP1212A01A::DeviceId() + { + return iDeviceId; + } + +/** +*/ +char* GP1212A01A::FirmwareRevision() + { + return iFirmwareRevision; + } diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaGP1212A01.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FutabaGP1212A01.h Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,115 @@ +// +// +// + +#ifndef FUTABA_GP1212A01_H +#define FUTABA_GP1212A01_H + +#include "FutabaGP1212.h" +#include "FutabaVfd.h" + +/** +GP1212A01A is a graphic display module using a FUTABA 256x64dots VFD. +The module do not include character ROM, the customer will compile the character +by themselves (from main system). +*/ +class GP1212A01A : public GP1212XXXX + { +public: + + +public: + GP1212A01A(); + ~GP1212A01A(); + + // + int Open(); + //From FutabaGraphicVfd + virtual int WidthInPixels() const {return KGP12xWidthInPixels;} + virtual int HeightInPixels() const {return KGP12xHeightInPixels;} + virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn); + virtual void SetAllPixels(unsigned char aPattern); + virtual int FrameBufferSizeInBytes() const {return KGP12xFrameBufferSizeInBytes;} + virtual void BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const; + //From FutabaVfd + virtual void SetBrightness(int aBrightness); + virtual void Clear(); + + //Specific to GP1212A01A + void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue); + void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels); + //Define display position within our display RAM + void SetDisplayPosition(unsigned char aX, unsigned char aY); + unsigned char DisplayPositionX() const {return iDisplayPositionX;} + unsigned char DisplayPositionY() const {return iDisplayPositionY;} + // + void SwapBuffers(); + // + void RequestDeviceId(); + void RequestFirmwareRevision(); + void RequestPowerSupplyStatus(); + // + void ToggleOffScreenMode(); + void SetOffScreenMode(bool aOn); + bool OffScreenMode() const {return iOffScreenMode;} + // + void SetFrameDifferencing(bool aOn){iUseFrameDifferencing=aOn;} + bool FrameDifferencing() const {return iUseFrameDifferencing;} + // + bool RequestPending(){return iRequest!=EMiniDisplayRequestNone;} + TMiniDisplayRequest CurrentRequest(){return iRequest;} + void CancelRequest(){iRequest=EMiniDisplayRequestNone;} + TMiniDisplayRequest AttemptRequestCompletion(); + FutabaVfdReport& InputReport() {return iInputReport;} + bool PowerOn(); + char* DeviceId(); + char* FirmwareRevision(); + +private: + enum DW + { + DW1=0xC0, + DW2=0xD0 + }; + + void SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY); + unsigned char OffScreenY() const; + void SendClearCommand(); + void OffScreenTranslation(unsigned char& aX, unsigned char& aY); + void ResetBuffers(); + void SendModifiedPixelBlocks(); + +private: + unsigned char iDisplayPositionX; + unsigned char iDisplayPositionY; + ///Off screen mode is the recommended default settings to avoid tearing. + ///Though turning it off can be useful for debugging + bool iOffScreenMode; + ///Frame differences algo is used to reduce USB bus traffic and improve frame rate in typical use case + bool iUseFrameDifferencing; + /// + //FutabaVfdReport iReport; + /// + //unsigned char iFrameBuffer[256*64]; + BitArray* iFrameNext; + BitArray* iFrameCurrent; + BitArray* iFramePrevious; + // + BitArray* iFrameAlpha; + BitArray* iFrameBeta; + BitArray* iFrameGamma; + // + int iNeedFullFrameUpdate; + //unsigned char iFrameBeta[256*64]; + //unsigned char *iFrontBuffer; + //unsigned char *iBackBuffer; + TMiniDisplayRequest iRequest; + FutabaVfdReport iInputReport; + // + char iDeviceId[KFutabaMaxHidReportSize]; + char iFirmwareRevision[KFutabaMaxHidReportSize]; + bool iPowerOn; + }; + + +#endif diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaGP1212A02.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FutabaGP1212A02.cpp Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,5 @@ +// +// +// + +#include "FutabaGP1212A02.h" \ No newline at end of file diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaGP1212A02.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FutabaGP1212A02.h Thu Aug 21 21:30:38 2014 +0200 @@ -0,0 +1,12 @@ +// +// +// + +#ifndef FUTABA_GP1212A02_H +#define FUTABA_GP1212A02_H + +#include "FutabaGP1212.h" + + + +#endif diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaVfd.cpp --- a/FutabaVfd.cpp Sat Jul 12 13:15:31 2014 +0200 +++ b/FutabaVfd.cpp Thu Aug 21 21:30:38 2014 +0200 @@ -10,7 +10,7 @@ #endif -const int KNumberOfFrameBeforeDiffAlgo = 3; + // // @@ -67,668 +67,6 @@ -// -// class GP1212A01A -// -GP1212A01A::GP1212A01A(): - iDisplayPositionX(0),iDisplayPositionY(0), - iOffScreenMode(true), - iUseFrameDifferencing(true), - iFrameNext(NULL), - iFrameCurrent(NULL), - iFramePrevious(NULL), - iFrameAlpha(NULL), - iFrameBeta(NULL), - iFrameGamma(NULL), - iNeedFullFrameUpdate(0), - iRequest(EMiniDisplayRequestNone),iPowerOn(false) - { - iDeviceId[0]=0; - iFirmwareRevision[0]=0; - //ResetBuffers(); - } -/** -*/ -GP1212A01A::~GP1212A01A() - { - delete iFrameAlpha; - iFrameAlpha=NULL; - // - delete iFrameBeta; - iFrameBeta=NULL; - // - delete iFrameGamma; - iFrameGamma=NULL; - // - iFrameNext=NULL; - iFrameCurrent=NULL; - iFramePrevious=NULL; - // - iNeedFullFrameUpdate=0; - } -/** -*/ -int GP1212A01A::Open() - { - int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL); - if (success) - { - //Allocate both frames - delete iFrameAlpha; - iFrameAlpha=NULL; - iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount); - // - delete iFrameBeta; - iFrameBeta=NULL; - iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount); - // - delete iFrameGamma; - iFrameGamma=NULL; - iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount); - // - iFrameNext=iFrameAlpha; - iFrameCurrent=iFrameBeta; - iFramePrevious=iFrameGamma; - - - //To make sure it is synced properly - iNeedFullFrameUpdate=0; - // - SetNonBlocking(1); - //Since we can't get our display position we force it to our default - //This makes sure frames are in sync from the start - //Clever clients will have taken care of putting back frame (0,0) before closing - SetDisplayPosition(iDisplayPositionX,iDisplayPositionY); - } - return success; - } - -/** -*/ -void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn) - { - // - //int byteOffset=(aX*HeightInPixels()+aY)/8; - //int bitOffset=(aX*HeightInPixels()+aY)%8; - //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset ); - - if (iOffScreenMode) - { - if (aOn) - { - iFrameNext->SetBit(aX*HeightInPixels()+aY); - } - else - { - iFrameNext->ClearBit(aX*HeightInPixels()+aY); - } - } - else - { - //Just specify a one pixel block - SetPixelBlock(aX,aY,0x00,0x01,aOn); - } - } - -/** -*/ -void GP1212A01A::BitBlit(const 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]); - } - } - } - -/** -Clear our client side back buffer. -Call to SwapBuffers must follow to actually clear the display. -*/ -void GP1212A01A::Clear() - { - //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes()); - if (iOffScreenMode) - { - iFrameNext->ClearAll(); - } - else - { - SendClearCommand(); - } - } - -/** -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); - - - if (iOffScreenMode) - { - memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes()); - } - else - { - //Using pattern SetPixelBlock variant. - SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern); - } - // - } - - -/** -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); - } - } - -/** -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 - if (!iUseFrameDifferencing || iNeedFullFrameUpdatePtr()); - } - else - { - //Frame diff algo is enabled - //We are going to send to our device only the differences between next frame and previous frame - SendModifiedPixelBlocks(); - } - //Swap device front and back buffer - SetDisplayPosition(iDisplayPositionX,OffScreenY()); - - //Cycle through our frame buffers - //We keep track of previous frame which is in fact our device back buffer. - //We can then compare previous and next frame and send only the differences to our device. - //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS. - //Keep our previous frame pointer - BitArray* previousFrame=iFramePrevious; - //Current frame becomes the previous one - iFramePrevious = iFrameCurrent; - //Next frame becomes the current one - iFrameCurrent = iFrameNext; - //Next frame is now our former previous - iFrameNext = previousFrame; - } - } - - -//Define the edge of our pixel block -//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii. -//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be. -const int KPixelBlockEdge = 32; -const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge; -const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8; - - -/** - * @brief GP1212A01A::SendModifiedPixelBlocks - * Compare our back and front buffer and send to the device only the modified pixels. - */ -void GP1212A01A::SendModifiedPixelBlocks() - { - int w=WidthInPixels(); - int h=HeightInPixels(); - - - //TODO: optimize with memcmp and 16 inc - /* - - for (int i=0;iPtr()+offset); - } - } - } - */ - - BitArray nextBlock(KPixelBlockSizeInBits); - BitArray previousBlock(KPixelBlockSizeInBits); - - for (int i=0;iPtr()+offset,iFramePrevious->Ptr()+offset,32 )) //32=(16*16/8) - if (memcmp(nextBlock.Ptr(),previousBlock.Ptr(),KPixelBlockSizeInBytes)!=0) - { - //We need to update that block - SetPixelBlock(i,j,KPixelBlockEdge-1,KPixelBlockSizeInBytes,nextBlock.Ptr()); - //SetPixelBlock(i,j,15,32,0xFF/*nextBlock.Ptr()*/); - //SetDisplayPosition(iDisplayPositionX,OffScreenY()); - //SetDisplayPosition(iDisplayPositionX,OffScreenY()); - - //SetPixelBlock(i,j,15,32,iFrameNext->Ptr()+offset); - } - } - } - - } - -/** -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() - { - //iNextFrame->ClearAll(); - //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha)); - //memset(iFrameBeta,0x00,sizeof(iFrameBeta)); - } - -/** -*/ -void GP1212A01A::RequestDeviceId() - { - if (RequestPending()) - { - //Abort silently for now - return; - } - - //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 - if (Write(report)==report.Size()) - { - iRequest=EMiniDisplayRequestDeviceId; - } - } - -/** -*/ -void GP1212A01A::RequestFirmwareRevision() - { - if (RequestPending()) - { - //Abort silently for now - return; - } - - //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 - if (Write(report)==report.Size()) - { - iRequest=EMiniDisplayRequestFirmwareRevision; - } - } - -/** -*/ -void GP1212A01A::RequestPowerSupplyStatus() - { - if (RequestPending()) - { - //Abort silently for now - return; - } - //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 - if (Write(report)==report.Size()) - { - iRequest=EMiniDisplayRequestPowerSupplyStatus; - } - } - - -/** -This is for development purposes only. -Production application should stick to off-screen mode to avoid tearing. -*/ -void GP1212A01A::ToggleOffScreenMode() - { - SetOffScreenMode(!iOffScreenMode); - } - -/** - * @brief GP1212A01A::SetOffScreenMode - * @param aOn - * @return - */ -void GP1212A01A::SetOffScreenMode(bool aOn) - { - if (aOn==iOffScreenMode) - { - //Nothing to do here - return; - } - - iOffScreenMode=aOn; - - //Clean up our buffers upon switching modes - SetDisplayPosition(0,0); - Clear(); - SwapBuffers(); - Clear(); - } - -/** -Tries to complete our current request if we have one pending. - */ -TMiniDisplayRequest GP1212A01A::AttemptRequestCompletion() - { - if (!RequestPending()) - { - return EMiniDisplayRequestNone; - } - - int res=Read(iInputReport); - - if (!res) - { - return EMiniDisplayRequestNone; - } - - //Process our request - if (CurrentRequest()==EMiniDisplayRequestPowerSupplyStatus) - { - if (iInputReport[1]==0x4F && iInputReport[2]==0x4E) - { - iPowerOn = true; - } - else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46) - { - iPowerOn = false; - } - } - else if (CurrentRequest()==EMiniDisplayRequestDeviceId) - { - unsigned char* ptr=&iInputReport[1]; - strcpy(iDeviceId,(const char*)ptr); - } - else if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision) - { - unsigned char* ptr=&iInputReport[1]; - strcpy(iFirmwareRevision,(const char*)ptr); - } - - TMiniDisplayRequest completed=iRequest; - //Our request was completed - iRequest=EMiniDisplayRequestNone; - - return completed; - } - - -/** -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); - } - -/** -*/ -bool GP1212A01A::PowerOn() - { - return iPowerOn; - } - -/** -*/ -char* GP1212A01A::DeviceId() - { - return iDeviceId; - } - -/** -*/ -char* GP1212A01A::FirmwareRevision() - { - return iFirmwareRevision; - } - - - diff -r 8bac7aac665c -r 5a9dbbc40c6b FutabaVfd.h --- a/FutabaVfd.h Sat Jul 12 13:15:31 2014 +0200 +++ b/FutabaVfd.h Thu Aug 21 21:30:38 2014 +0200 @@ -73,145 +73,5 @@ int iMaxSize; }; -/** -*/ -class FutabaVfd : public HidDevice - { -public: - virtual int MinBrightness() const=0; - virtual int MaxBrightness() const=0; - virtual void SetBrightness(int aBrightness)=0; - virtual void Clear()=0; - }; - - -/** -*/ -class FutabaGraphicVfd : public FutabaVfd - { -public: - virtual int WidthInPixels() const=0; - virtual int HeightInPixels() const=0; - virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn)=0; - virtual void SetAllPixels(unsigned char aOn)=0; - virtual int FrameBufferSizeInBytes() const=0; - //virtual int BitBlit(unsigned char* aSrc, unsigned char aSrcWidth, unsigned char aSrcHeight, unsigned char aTargetX, unsigned char aTargetY) const=0; - - }; - -/** -Common functionality between GP1212A01A and GP1212A02A -*/ -class GP1212XXXX : public FutabaGraphicVfd - { -public: - //From FutabaVfd - virtual int MinBrightness() const {return 0;} - virtual int MaxBrightness() const {return 5;} - }; - -/** -GP1212A01A is a graphic display module using a FUTABA 256x64dots VFD. -The module do not include character ROM, the customer will compile the character -by themselves (from main system). -*/ -class GP1212A01A : public GP1212XXXX - { -public: - - -public: - GP1212A01A(); - ~GP1212A01A(); - - // - int Open(); - //From FutabaGraphicVfd - virtual int WidthInPixels() const {return KGP12xWidthInPixels;} - virtual int HeightInPixels() const {return KGP12xHeightInPixels;} - virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn); - virtual void SetAllPixels(unsigned char aPattern); - virtual int FrameBufferSizeInBytes() const {return KGP12xFrameBufferSizeInBytes;} - virtual void BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const; - //From FutabaVfd - virtual void SetBrightness(int aBrightness); - virtual void Clear(); - - //Specific to GP1212A01A - void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue); - void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels); - //Define display position within our display RAM - void SetDisplayPosition(unsigned char aX, unsigned char aY); - unsigned char DisplayPositionX() const {return iDisplayPositionX;} - unsigned char DisplayPositionY() const {return iDisplayPositionY;} - // - void SwapBuffers(); - // - void RequestDeviceId(); - void RequestFirmwareRevision(); - void RequestPowerSupplyStatus(); - // - void ToggleOffScreenMode(); - void SetOffScreenMode(bool aOn); - bool OffScreenMode() const {return iOffScreenMode;} - // - void SetFrameDifferencing(bool aOn){iUseFrameDifferencing=aOn;} - bool FrameDifferencing() const {return iUseFrameDifferencing;} - // - bool RequestPending(){return iRequest!=EMiniDisplayRequestNone;} - TMiniDisplayRequest CurrentRequest(){return iRequest;} - void CancelRequest(){iRequest=EMiniDisplayRequestNone;} - TMiniDisplayRequest AttemptRequestCompletion(); - FutabaVfdReport& InputReport() {return iInputReport;} - bool PowerOn(); - char* DeviceId(); - char* FirmwareRevision(); - -private: - enum DW - { - DW1=0xC0, - DW2=0xD0 - }; - - void SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY); - unsigned char OffScreenY() const; - void SendClearCommand(); - void OffScreenTranslation(unsigned char& aX, unsigned char& aY); - void ResetBuffers(); - void SendModifiedPixelBlocks(); - -private: - unsigned char iDisplayPositionX; - unsigned char iDisplayPositionY; - ///Off screen mode is the recommended default settings to avoid tearing. - ///Though turning it off can be useful for debugging - bool iOffScreenMode; - ///Frame differences algo is used to reduce USB bus traffic and improve frame rate in typical use case - bool iUseFrameDifferencing; - /// - //FutabaVfdReport iReport; - /// - //unsigned char iFrameBuffer[256*64]; - BitArray* iFrameNext; - BitArray* iFrameCurrent; - BitArray* iFramePrevious; - // - BitArray* iFrameAlpha; - BitArray* iFrameBeta; - BitArray* iFrameGamma; - // - int iNeedFullFrameUpdate; - //unsigned char iFrameBeta[256*64]; - //unsigned char *iFrontBuffer; - //unsigned char *iBackBuffer; - TMiniDisplayRequest iRequest; - FutabaVfdReport iInputReport; - // - char iDeviceId[KFutabaMaxHidReportSize]; - char iFirmwareRevision[KFutabaMaxHidReportSize]; - bool iPowerOn; - }; - #endif diff -r 8bac7aac665c -r 5a9dbbc40c6b MiniDisplay.cpp --- a/MiniDisplay.cpp Sat Jul 12 13:15:31 2014 +0200 +++ b/MiniDisplay.cpp Thu Aug 21 21:30:38 2014 +0200 @@ -1,13 +1,13 @@ #include "MiniDisplay.h" -#include "FutabaVfd.h" +#include "FutabaGP1212A01.h" //Open & Close functions -MiniDisplayDevice MiniDisplayOpen() +MiniDisplayDevice MiniDisplayOpen(TMiniDisplayType aType) { GP1212A01A* device=NULL; device=new GP1212A01A(); diff -r 8bac7aac665c -r 5a9dbbc40c6b MiniDisplay.h --- a/MiniDisplay.h Sat Jul 12 13:15:31 2014 +0200 +++ b/MiniDisplay.h Thu Aug 21 21:30:38 2014 +0200 @@ -27,6 +27,14 @@ typedef enum { + EMiniDisplayAutoDetect=0, /*Not yet implemented*/ + EMiniDisplayFutabaGP1212A01, + EMiniDisplayFutabaGP1212A02 + } +TMiniDisplayType; + +typedef enum + { EMiniDisplayRequestNone, EMiniDisplayRequestDeviceId, EMiniDisplayRequestFirmwareRevision, @@ -35,7 +43,7 @@ TMiniDisplayRequest; //Open & Close functions -extern "C" MDAPI MiniDisplayDevice MiniDisplayOpen(); +extern "C" MDAPI MiniDisplayDevice MiniDisplayOpen(TMiniDisplayType aType); extern "C" MDAPI void MiniDisplayClose(MiniDisplayDevice aDevice); /**