Ground work to support multiple type of display, notably GP1212A02
authorsl
Thu, 21 Aug 2014 21:30:38 +0200
changeset 85a9dbbc40c6b
parent 7 8bac7aac665c
child 9 6b08e3e81cf3
Ground work to support multiple type of display, notably GP1212A02
CMakeLists.txt
Display.h
FutabaGP1212.cpp
FutabaGP1212.h
FutabaGP1212A01.cpp
FutabaGP1212A01.h
FutabaGP1212A02.cpp
FutabaGP1212A02.h
FutabaVfd.cpp
FutabaVfd.h
MiniDisplay.cpp
MiniDisplay.h
     1.1 --- a/CMakeLists.txt	Sat Jul 12 13:15:31 2014 +0200
     1.2 +++ b/CMakeLists.txt	Thu Aug 21 21:30:38 2014 +0200
     1.3 @@ -10,10 +10,26 @@
     1.4    set (LIB_TYPE SHARED)
     1.5  endif (MD_SHARED_LIB)
     1.6  
     1.7 -set(SOURCES BitArray.cpp FutabaVfd.cpp HidDevice.cpp MiniDisplay.cpp ../../GitHub/hidapi/windows/hid.c)
     1.8 +set(SOURCES		BitArray.cpp
     1.9 +				FutabaVfd.cpp
    1.10 +				FutabaGP1212.cpp
    1.11 +				FutabaGP1212A01.cpp
    1.12 +				FutabaGP1212A02.cpp
    1.13 +				HidDevice.cpp
    1.14 +				MiniDisplay.cpp
    1.15 +				../../GitHub/hidapi/windows/hid.c)
    1.16 +
    1.17  source_group(Souces FILES ${SOURCES})
    1.18  
    1.19 -set(INCLUDES BitArray.h FutabaVfd.h HidDevice.h HidReport.h MiniDisplay.h)
    1.20 +set(INCLUDES	BitArray.h
    1.21 +				FutabaVfd.h
    1.22 +				FutabaGP1212.h
    1.23 +				FutabaGP1212A01.h
    1.24 +				FutabaGP1212A02.h
    1.25 +				HidDevice.h
    1.26 +				HidReport.h
    1.27 +				MiniDisplay.h)
    1.28 +
    1.29  source_group(Includes FILES ${INCLUDES})
    1.30  
    1.31  include_directories(../../GitHub/hidapi/hidapi)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Display.h	Thu Aug 21 21:30:38 2014 +0200
     2.3 @@ -0,0 +1,39 @@
     2.4 +//
     2.5 +//
     2.6 +//
     2.7 +
     2.8 +#ifndef DISPLAY_H
     2.9 +#define DISPLAY_H
    2.10 +
    2.11 +#include "HidDevice.h"
    2.12 +
    2.13 +/**
    2.14 +Define an interface to some basic display functionality
    2.15 +*/
    2.16 +class DisplayBase : public HidDevice
    2.17 +	{
    2.18 +public:
    2.19 +	virtual int MinBrightness() const=0;
    2.20 +	virtual int MaxBrightness() const=0;
    2.21 +	virtual void SetBrightness(int aBrightness)=0;
    2.22 +	virtual void Clear()=0;
    2.23 +	};
    2.24 +
    2.25 +
    2.26 +/**
    2.27 +*/
    2.28 +class GraphicDisplay : public DisplayBase
    2.29 +	{
    2.30 +public:
    2.31 +	virtual int WidthInPixels() const=0;
    2.32 +	virtual int HeightInPixels() const=0;
    2.33 +	virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn)=0;
    2.34 +	virtual void SetAllPixels(unsigned char aOn)=0;
    2.35 +	virtual int FrameBufferSizeInBytes() const=0;
    2.36 +	//virtual int BitBlit(unsigned char* aSrc, unsigned char aSrcWidth, unsigned char aSrcHeight, unsigned char aTargetX, unsigned char aTargetY) const=0;
    2.37 +
    2.38 +	};
    2.39 +
    2.40 +
    2.41 +
    2.42 +#endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/FutabaGP1212.cpp	Thu Aug 21 21:30:38 2014 +0200
     3.3 @@ -0,0 +1,5 @@
     3.4 +//
     3.5 +//
     3.6 +//
     3.7 +
     3.8 +#include "FutabaGP1212.h"
     3.9 \ No newline at end of file
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/FutabaGP1212.h	Thu Aug 21 21:30:38 2014 +0200
     4.3 @@ -0,0 +1,24 @@
     4.4 +//
     4.5 +//
     4.6 +//
     4.7 +
     4.8 +#ifndef FUTABA_GP1212_H
     4.9 +#define FUTABA_GP1212_H
    4.10 +
    4.11 +#include "Display.h"
    4.12 +
    4.13 +
    4.14 +/**
    4.15 +Common functionality between GP1212A01A and GP1212A02A
    4.16 +*/
    4.17 +class GP1212XXXX : public GraphicDisplay
    4.18 +	{
    4.19 +public:
    4.20 +	//From FutabaVfd
    4.21 +    virtual int MinBrightness() const {return 0;}
    4.22 +    virtual int MaxBrightness() const {return 5;}
    4.23 +	};
    4.24 +
    4.25 +
    4.26 +
    4.27 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/FutabaGP1212A01.cpp	Thu Aug 21 21:30:38 2014 +0200
     5.3 @@ -0,0 +1,670 @@
     5.4 +//
     5.5 +//
     5.6 +//
     5.7 +
     5.8 +#include "FutabaGP1212A01.h"
     5.9 +
    5.10 +const int KNumberOfFrameBeforeDiffAlgo = 3;
    5.11 +
    5.12 +//
    5.13 +// class GP1212A01A
    5.14 +//
    5.15 +
    5.16 +GP1212A01A::GP1212A01A():
    5.17 +	iDisplayPositionX(0),iDisplayPositionY(0),
    5.18 +    iOffScreenMode(true),
    5.19 +    iUseFrameDifferencing(true),
    5.20 +    iFrameNext(NULL),
    5.21 +    iFrameCurrent(NULL),
    5.22 +    iFramePrevious(NULL),
    5.23 +    iFrameAlpha(NULL),
    5.24 +    iFrameBeta(NULL),
    5.25 +    iFrameGamma(NULL),
    5.26 +    iNeedFullFrameUpdate(0),
    5.27 +    iRequest(EMiniDisplayRequestNone),iPowerOn(false)
    5.28 +	{
    5.29 +	iDeviceId[0]=0;
    5.30 +	iFirmwareRevision[0]=0;
    5.31 +	//ResetBuffers();
    5.32 +	}
    5.33 +
    5.34 +/**
    5.35 +*/
    5.36 +GP1212A01A::~GP1212A01A()
    5.37 +	{
    5.38 +    delete iFrameAlpha;
    5.39 +    iFrameAlpha=NULL;
    5.40 +    //
    5.41 +    delete iFrameBeta;
    5.42 +    iFrameBeta=NULL;
    5.43 +    //
    5.44 +    delete iFrameGamma;
    5.45 +    iFrameGamma=NULL;
    5.46 +    //
    5.47 +    iFrameNext=NULL;
    5.48 +    iFrameCurrent=NULL;
    5.49 +    iFramePrevious=NULL;
    5.50 +    //
    5.51 +    iNeedFullFrameUpdate=0;
    5.52 +	}
    5.53 +
    5.54 +/**
    5.55 +*/
    5.56 +int GP1212A01A::Open()
    5.57 +	{
    5.58 +	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    5.59 +	if (success)
    5.60 +		{
    5.61 +        //Allocate both frames
    5.62 +        delete iFrameAlpha;
    5.63 +        iFrameAlpha=NULL;
    5.64 +        iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
    5.65 +        //
    5.66 +        delete iFrameBeta;
    5.67 +        iFrameBeta=NULL;
    5.68 +        iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
    5.69 +        //
    5.70 +        delete iFrameGamma;
    5.71 +        iFrameGamma=NULL;
    5.72 +        iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount);
    5.73 +        //
    5.74 +        iFrameNext=iFrameAlpha;
    5.75 +        iFrameCurrent=iFrameBeta;
    5.76 +        iFramePrevious=iFrameGamma;
    5.77 +
    5.78 +
    5.79 +        //To make sure it is synced properly
    5.80 +        iNeedFullFrameUpdate=0;
    5.81 +        //
    5.82 +		SetNonBlocking(1);
    5.83 +        //Since we can't get our display position we force it to our default
    5.84 +		//This makes sure frames are in sync from the start
    5.85 +        //Clever clients will have taken care of putting back frame (0,0) before closing
    5.86 +		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
    5.87 +		}
    5.88 +	return success;
    5.89 +	}
    5.90 +
    5.91 +/**
    5.92 +*/
    5.93 +void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
    5.94 +	{
    5.95 +	//
    5.96 +	//int byteOffset=(aX*HeightInPixels()+aY)/8;
    5.97 +	//int bitOffset=(aX*HeightInPixels()+aY)%8;
    5.98 +    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
    5.99 +
   5.100 +    if (iOffScreenMode)
   5.101 +        {
   5.102 +        if (aOn)
   5.103 +            {
   5.104 +            iFrameNext->SetBit(aX*HeightInPixels()+aY);
   5.105 +            }
   5.106 +        else
   5.107 +            {
   5.108 +            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
   5.109 +            }
   5.110 +        }
   5.111 +    else
   5.112 +        {
   5.113 +        //Just specify a one pixel block
   5.114 +        SetPixelBlock(aX,aY,0x00,0x01,aOn);
   5.115 +        }
   5.116 +	}
   5.117 +
   5.118 +/**
   5.119 +*/
   5.120 +void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
   5.121 +	{
   5.122 +	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
   5.123 +	for (int i=0;i<aSrcWidth;i++)
   5.124 +		{
   5.125 +		for (int j=0;j<aSrcHeight;j++)
   5.126 +			{
   5.127 +            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
   5.128 +			}
   5.129 +		}
   5.130 +	}
   5.131 +
   5.132 +/**
   5.133 +Clear our client side back buffer.
   5.134 +Call to SwapBuffers must follow to actually clear the display.
   5.135 +*/
   5.136 +void GP1212A01A::Clear()
   5.137 +    {
   5.138 +    //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
   5.139 +    if (iOffScreenMode)
   5.140 +        {
   5.141 +        iFrameNext->ClearAll();
   5.142 +        }
   5.143 +    else
   5.144 +        {
   5.145 +        SendClearCommand();
   5.146 +        }
   5.147 +    }
   5.148 +
   5.149 +/**
   5.150 +Set all pixels on our screen to the desired value.
   5.151 +This operation is performed off screen to avoid tearing.
   5.152 +@param 8 pixels pattern
   5.153 +*/
   5.154 +void GP1212A01A::SetAllPixels(unsigned char aPattern)
   5.155 +	{
   5.156 +	//With a single buffer
   5.157 +	//unsigned char screen[2048]; //One screen worth of pixels
   5.158 +	//memset(screen,0xFF,sizeof(screen));
   5.159 +	//SetPixelBlock(0,0,63,sizeof(screen),screen);
   5.160 +
   5.161 +
   5.162 +    if (iOffScreenMode)
   5.163 +        {
   5.164 +        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
   5.165 +        }
   5.166 +    else
   5.167 +        {
   5.168 +        //Using pattern SetPixelBlock variant.
   5.169 +        SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
   5.170 +        }
   5.171 +	//
   5.172 +	}
   5.173 +
   5.174 +
   5.175 +/**
   5.176 +Set the defined pixel block to the given value.
   5.177 +@param X coordinate of our pixel block starting point.
   5.178 +@param Y coordinate of our pixel block starting point.
   5.179 +@param The height of our pixel block.
   5.180 +@param The size of our pixel data. Number of pixels divided by 8.
   5.181 +@param The value set to 8 pixels used as a pattern.
   5.182 +*/
   5.183 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
   5.184 +	{
   5.185 +	OffScreenTranslation(aX,aY);
   5.186 +    FutabaVfdReport report;
   5.187 +    report[0]=0x00; //Report ID
   5.188 +    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
   5.189 +    report[2]=0x1B; //Command ID
   5.190 +    report[3]=0x5B; //Command ID
   5.191 +    report[4]=0xF0; //Command ID
   5.192 +    report[5]=aX;   //X
   5.193 +    report[6]=aY;   //Y
   5.194 +    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.
   5.195 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   5.196 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   5.197 +    int sizeWritten=MIN(aSize,report.Size()-10);
   5.198 +    memset(report.Buffer()+10, aValue, sizeWritten);
   5.199 +    Write(report);
   5.200 +
   5.201 +    int remainingSize=aSize;
   5.202 +    //We need to keep on sending our pixel data until we are done
   5.203 +    while (report[1]==64)
   5.204 +        {
   5.205 +        report.Reset();
   5.206 +        remainingSize-=sizeWritten;
   5.207 +        report[0]=0x00; //Report ID
   5.208 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   5.209 +        sizeWritten=(report[1]==64?63:report[1]);
   5.210 +        memset(report.Buffer()+2, aValue, sizeWritten);
   5.211 +        Write(report);
   5.212 +        }
   5.213 +	}
   5.214 +
   5.215 +/**
   5.216 +Set the defined pixel block to the given value.
   5.217 +@param X coordinate of our pixel block starting point.
   5.218 +@param Y coordinate of our pixel block starting point.
   5.219 +@param The height of our pixel block.
   5.220 +@param The size of our pixel data. Number of pixels divided by 8.
   5.221 +@param Pointer to our pixel data.
   5.222 +*/
   5.223 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   5.224 +    {
   5.225 +	OffScreenTranslation(aX,aY);
   5.226 +    FutabaVfdReport report;
   5.227 +    report[0]=0x00; //Report ID
   5.228 +    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
   5.229 +    report[2]=0x1B; //Command ID
   5.230 +    report[3]=0x5B; //Command ID
   5.231 +    report[4]=0xF0; //Command ID
   5.232 +    report[5]=aX;   //X
   5.233 +    report[6]=aY;   //Y
   5.234 +    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.
   5.235 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   5.236 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   5.237 +    int sizeWritten=MIN(aSize,report.Size()-10);
   5.238 +    memcpy(report.Buffer()+10, aPixels, sizeWritten);
   5.239 +    Write(report);
   5.240 +
   5.241 +    int remainingSize=aSize;
   5.242 +    //We need to keep on sending our pixel data until we are done
   5.243 +    while (report[1]==64)
   5.244 +        {
   5.245 +        report.Reset();
   5.246 +        remainingSize-=sizeWritten;
   5.247 +        report[0]=0x00; //Report ID
   5.248 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   5.249 +        sizeWritten=(report[1]==64?63:report[1]);
   5.250 +        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   5.251 +        Write(report);
   5.252 +        }
   5.253 +    }
   5.254 +
   5.255 +/**
   5.256 +Using this function is advised against as is causes tearing.
   5.257 +Use Clear instead.
   5.258 +*/
   5.259 +void GP1212A01A::SendClearCommand()
   5.260 +	{
   5.261 +    //1BH,5BH,32H,4AH
   5.262 +    //Send Clear Display Command
   5.263 +	FutabaVfdReport report;
   5.264 +	report[0]=0x00; //Report ID
   5.265 +	report[1]=0x04; //Report length
   5.266 +	report[2]=0x1B; //Command ID
   5.267 +	report[3]=0x5B; //Command ID
   5.268 +	report[4]=0x32; //Command ID
   5.269 +	report[5]=0x4A; //Command ID
   5.270 +	Write(report);
   5.271 +	}
   5.272 +
   5.273 +/**
   5.274 +Change our display position within our buffer.
   5.275 +*/
   5.276 +void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   5.277 +    {
   5.278 +    //1BH,5BH,Dw,Px,Py
   5.279 +    //Send Display Position Settings Command
   5.280 +    FutabaVfdReport report;
   5.281 +    report[0]=0x00; //Report ID
   5.282 +    report[1]=0x05; //Report length
   5.283 +    report[2]=0x1B; //Command ID
   5.284 +    report[3]=0x5B; //Command ID
   5.285 +    report[4]=aDw;  //Specify our DW
   5.286 +    report[5]=aX;   //X coordinate of our DW top-left corner
   5.287 +    report[6]=aY;   //Y coordinate of our DW top-left corner
   5.288 +    Write(report);
   5.289 +    }
   5.290 +
   5.291 +/**
   5.292 +Change our display position within our buffer.
   5.293 +*/
   5.294 +void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   5.295 +	{
   5.296 +	//Specs apparently says both DW should remain the same
   5.297 +	//Just don't ask
   5.298 +    SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   5.299 +    SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   5.300 +	iDisplayPositionX=aX;
   5.301 +	iDisplayPositionY=aY;
   5.302 +	}
   5.303 +
   5.304 +/**
   5.305 +Provide Y coordinate of our off screen buffer.
   5.306 +*/
   5.307 +unsigned char GP1212A01A::OffScreenY() const
   5.308 +	{
   5.309 +	//Overflowing is fine this is just what we want
   5.310 +	return iDisplayPositionY+HeightInPixels();
   5.311 +	}
   5.312 +
   5.313 +/**
   5.314 +Put our off screen buffer on screen.
   5.315 +On screen buffer goes off screen.
   5.316 +*/
   5.317 +void GP1212A01A::SwapBuffers()
   5.318 +	{
   5.319 +	//Only perform buffer swapping if off screen mode is enabled
   5.320 +	if (OffScreenMode())
   5.321 +		{
   5.322 +		//Send host back buffer to device back buffer
   5.323 +        if (!iUseFrameDifferencing || iNeedFullFrameUpdate<KNumberOfFrameBeforeDiffAlgo)
   5.324 +            {
   5.325 +            iNeedFullFrameUpdate++;
   5.326 +            SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameNext->Ptr());
   5.327 +            }
   5.328 +        else
   5.329 +            {
   5.330 +            //Frame diff algo is enabled
   5.331 +            //We are going to send to our device only the differences between next frame and previous frame
   5.332 +            SendModifiedPixelBlocks();
   5.333 +            }
   5.334 +		//Swap device front and back buffer
   5.335 +		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   5.336 +
   5.337 +        //Cycle through our frame buffers
   5.338 +        //We keep track of previous frame which is in fact our device back buffer.
   5.339 +        //We can then compare previous and next frame and send only the differences to our device.
   5.340 +        //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
   5.341 +        //Keep our previous frame pointer
   5.342 +        BitArray* previousFrame=iFramePrevious;
   5.343 +        //Current frame becomes the previous one
   5.344 +        iFramePrevious = iFrameCurrent;
   5.345 +        //Next frame becomes the current one
   5.346 +        iFrameCurrent = iFrameNext;
   5.347 +        //Next frame is now our former previous
   5.348 +        iFrameNext = previousFrame;
   5.349 +		}
   5.350 +	}
   5.351 +
   5.352 +
   5.353 +//Define the edge of our pixel block
   5.354 +//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
   5.355 +//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
   5.356 +const int KPixelBlockEdge = 32;
   5.357 +const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
   5.358 +const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
   5.359 +
   5.360 +
   5.361 +/**
   5.362 + * @brief GP1212A01A::SendModifiedPixelBlocks
   5.363 + * Compare our back and front buffer and send to the device only the modified pixels.
   5.364 + */
   5.365 +void GP1212A01A::SendModifiedPixelBlocks()
   5.366 +    {
   5.367 +    int w=WidthInPixels();
   5.368 +    int h=HeightInPixels();
   5.369 +
   5.370 +
   5.371 +    //TODO: optimize with memcmp and 16 inc
   5.372 +    /*
   5.373 +
   5.374 +    for (int i=0;i<w;i++)
   5.375 +        {
   5.376 +        for (int j=0;j<h;j++)
   5.377 +            {
   5.378 +            //aX*HeightInPixels()+aY
   5.379 +            if ((*iFrameNext)[i*h+j]!=(*iFramePrevious)[i*h+j])
   5.380 +                {
   5.381 +                //We need to update that pixel
   5.382 +                SetPixelBlock(i,j,0,1,((*iFrameNext)[i*h+j]?0x01:0x00));
   5.383 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   5.384 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   5.385 +
   5.386 +                //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
   5.387 +                }
   5.388 +            }
   5.389 +        }
   5.390 +    */
   5.391 +
   5.392 +    BitArray nextBlock(KPixelBlockSizeInBits);
   5.393 +    BitArray previousBlock(KPixelBlockSizeInBits);
   5.394 +
   5.395 +    for (int i=0;i<w;i+=KPixelBlockEdge)
   5.396 +        {
   5.397 +        for (int j=0;j<h;j+=KPixelBlockEdge)
   5.398 +            {
   5.399 +            //aX*HeightInPixels()+aY
   5.400 +            //int offset=(i*w/8)+(j/8);
   5.401 +
   5.402 +#ifdef DEBUG_FRAME_DIFF
   5.403 +            QImage imagePrevious(KPixelBlockEdge,KPixelBlockEdge,QImage::Format_RGB32);
   5.404 +            QImage imageNext(KPixelBlockEdge,KPixelBlockEdge,QImage::Format_RGB32);
   5.405 +#endif
   5.406 +
   5.407 +            //Get both our blocks from our buffers
   5.408 +            for (int x=i;x<i+KPixelBlockEdge;x++)
   5.409 +                {
   5.410 +                for (int y=j;y<j+KPixelBlockEdge;y++)
   5.411 +                    {
   5.412 +                    int blockOffset=(x-i)*KPixelBlockEdge+(y-j);
   5.413 +                    int frameOffset=x*h+y;
   5.414 +                    nextBlock.SetBitValue(blockOffset,(*iFrameNext)[frameOffset]);
   5.415 +                    previousBlock.SetBitValue(blockOffset,(*iFramePrevious)[frameOffset]);
   5.416 +
   5.417 +#ifdef DEBUG_FRAME_DIFF
   5.418 +                    imageNext.setPixel(x-i,y-j,(nextBlock[blockOffset]?0xFFFFFFFF:0x00000000));
   5.419 +                    imagePrevious.setPixel(x-i,y-j,(previousBlock[blockOffset]?0xFFFFFFFF:0x00000000));
   5.420 +#endif
   5.421 +                    }
   5.422 +                }
   5.423 +
   5.424 +#ifdef DEBUG_FRAME_DIFF
   5.425 +            QString previousName;
   5.426 +            QString nextName;
   5.427 +            QTextStream(&previousName) << "p" << i << "x" << j << ".png";
   5.428 +            QTextStream(&nextName) << "n" << i << "x" << j << ".png";
   5.429 +            imagePrevious.save(previousName);
   5.430 +            imageNext.save(nextName);
   5.431 +#endif
   5.432 +
   5.433 +
   5.434 +            //if (memcmp(iFrameNext->Ptr()+offset,iFramePrevious->Ptr()+offset,32 )) //32=(16*16/8)
   5.435 +            if (memcmp(nextBlock.Ptr(),previousBlock.Ptr(),KPixelBlockSizeInBytes)!=0)
   5.436 +                {
   5.437 +                //We need to update that block
   5.438 +                SetPixelBlock(i,j,KPixelBlockEdge-1,KPixelBlockSizeInBytes,nextBlock.Ptr());
   5.439 +                //SetPixelBlock(i,j,15,32,0xFF/*nextBlock.Ptr()*/);
   5.440 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   5.441 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   5.442 +
   5.443 +                //SetPixelBlock(i,j,15,32,iFrameNext->Ptr()+offset);
   5.444 +                }
   5.445 +            }
   5.446 +        }
   5.447 +
   5.448 +    }
   5.449 +
   5.450 +/**
   5.451 +Translate the given pixel coordinate according to our off screen mode.
   5.452 +*/
   5.453 +void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   5.454 +	{
   5.455 +	if (OffScreenMode())
   5.456 +		{
   5.457 +		aX+=WidthInPixels()-iDisplayPositionX;
   5.458 +		aY+=HeightInPixels()-iDisplayPositionY;
   5.459 +		}
   5.460 +	}
   5.461 +
   5.462 +
   5.463 +/**
   5.464 +*/
   5.465 +void GP1212A01A::ResetBuffers()
   5.466 +	{
   5.467 +    //iNextFrame->ClearAll();
   5.468 +    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
   5.469 +	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
   5.470 +	}
   5.471 +
   5.472 +/**
   5.473 +*/
   5.474 +void GP1212A01A::RequestDeviceId()
   5.475 +    {
   5.476 +    if (RequestPending())
   5.477 +        {
   5.478 +        //Abort silently for now
   5.479 +        return;
   5.480 +        }
   5.481 +
   5.482 +    //1BH,5BH,63H,49H,44H
   5.483 +    //Send Read ID command
   5.484 +    FutabaVfdReport report;
   5.485 +    report[0]=0x00; //Report ID
   5.486 +    report[1]=0x05; //Report length
   5.487 +    report[2]=0x1B; //Command ID
   5.488 +    report[3]=0x5B; //Command ID
   5.489 +    report[4]=0x63; //Command ID
   5.490 +    report[5]=0x49; //Command ID
   5.491 +    report[6]=0x44; //Command ID
   5.492 +    if (Write(report)==report.Size())
   5.493 +        {
   5.494 +        iRequest=EMiniDisplayRequestDeviceId;
   5.495 +        }
   5.496 +    }
   5.497 +
   5.498 +/**
   5.499 +*/
   5.500 +void GP1212A01A::RequestFirmwareRevision()
   5.501 +    {
   5.502 +    if (RequestPending())
   5.503 +        {
   5.504 +        //Abort silently for now
   5.505 +        return;
   5.506 +        }
   5.507 +
   5.508 +    //1BH,5BH,63H,46H,52H
   5.509 +    //Send Software Revision Read Command
   5.510 +    FutabaVfdReport report;
   5.511 +    report[0]=0x00; //Report ID
   5.512 +    report[1]=0x05; //Report length
   5.513 +    report[2]=0x1B; //Command ID
   5.514 +    report[3]=0x5B; //Command ID
   5.515 +    report[4]=0x63; //Command ID
   5.516 +    report[5]=0x46; //Command ID
   5.517 +    report[6]=0x52; //Command ID
   5.518 +    if (Write(report)==report.Size())
   5.519 +        {
   5.520 +        iRequest=EMiniDisplayRequestFirmwareRevision;
   5.521 +        }
   5.522 +    }
   5.523 +
   5.524 +/**
   5.525 +*/
   5.526 +void GP1212A01A::RequestPowerSupplyStatus()
   5.527 +    {
   5.528 +    if (RequestPending())
   5.529 +        {
   5.530 +        //Abort silently for now
   5.531 +        return;
   5.532 +        }
   5.533 +    //1BH,5BH,63H,50H,4DH
   5.534 +    //Send Power Suppply Monitor Command
   5.535 +    FutabaVfdReport report;
   5.536 +    report[0]=0x00; //Report ID
   5.537 +    report[1]=0x05; //Report length
   5.538 +    report[2]=0x1B; //Command ID
   5.539 +    report[3]=0x5B; //Command ID
   5.540 +    report[4]=0x63; //Command ID
   5.541 +    report[5]=0x50; //Command ID
   5.542 +    report[6]=0x4D; //Command ID
   5.543 +    if (Write(report)==report.Size())
   5.544 +        {
   5.545 +        iRequest=EMiniDisplayRequestPowerSupplyStatus;
   5.546 +        }
   5.547 +    }
   5.548 +
   5.549 +
   5.550 +/**
   5.551 +This is for development purposes only.
   5.552 +Production application should stick to off-screen mode to avoid tearing.
   5.553 +*/
   5.554 +void GP1212A01A::ToggleOffScreenMode()
   5.555 +	{
   5.556 +    SetOffScreenMode(!iOffScreenMode);
   5.557 +	}
   5.558 +
   5.559 +/**
   5.560 + * @brief GP1212A01A::SetOffScreenMode
   5.561 + * @param aOn
   5.562 + * @return
   5.563 + */
   5.564 +void GP1212A01A::SetOffScreenMode(bool aOn)
   5.565 +    {
   5.566 +    if (aOn==iOffScreenMode)
   5.567 +    {
   5.568 +        //Nothing to do here
   5.569 +        return;
   5.570 +    }
   5.571 +
   5.572 +    iOffScreenMode=aOn;
   5.573 +
   5.574 +    //Clean up our buffers upon switching modes
   5.575 +    SetDisplayPosition(0,0);
   5.576 +    Clear();
   5.577 +    SwapBuffers();
   5.578 +    Clear();
   5.579 +    }
   5.580 +
   5.581 +/**
   5.582 +Tries to complete our current request if we have one pending.
   5.583 + */
   5.584 +TMiniDisplayRequest GP1212A01A::AttemptRequestCompletion()
   5.585 +    {
   5.586 +    if (!RequestPending())
   5.587 +        {
   5.588 +        return EMiniDisplayRequestNone;
   5.589 +        }
   5.590 +
   5.591 +    int res=Read(iInputReport);
   5.592 +
   5.593 +    if (!res)
   5.594 +        {
   5.595 +        return EMiniDisplayRequestNone;
   5.596 +        }
   5.597 +
   5.598 +    //Process our request
   5.599 +    if (CurrentRequest()==EMiniDisplayRequestPowerSupplyStatus)
   5.600 +        {
   5.601 +        if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
   5.602 +            {
   5.603 +            iPowerOn = true;
   5.604 +            }
   5.605 +        else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
   5.606 +            {
   5.607 +            iPowerOn = false;
   5.608 +            }
   5.609 +        }
   5.610 +	else if (CurrentRequest()==EMiniDisplayRequestDeviceId)
   5.611 +		{
   5.612 +			unsigned char* ptr=&iInputReport[1];
   5.613 +			strcpy(iDeviceId,(const char*)ptr);
   5.614 +		}
   5.615 +	else if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision)
   5.616 +		{
   5.617 +			unsigned char* ptr=&iInputReport[1];
   5.618 +			strcpy(iFirmwareRevision,(const char*)ptr);
   5.619 +		}
   5.620 +
   5.621 +    TMiniDisplayRequest completed=iRequest;
   5.622 +    //Our request was completed
   5.623 +    iRequest=EMiniDisplayRequestNone;
   5.624 +
   5.625 +    return completed;
   5.626 +    }
   5.627 +
   5.628 +
   5.629 +/**
   5.630 +Set our screen brightness.
   5.631 +@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
   5.632 +*/
   5.633 +void GP1212A01A::SetBrightness(int aBrightness)
   5.634 +    {
   5.635 +    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
   5.636 +        {
   5.637 +        //Brightness out of range.
   5.638 +        //Just ignore that request.
   5.639 +        return;
   5.640 +        }
   5.641 +
   5.642 +    FutabaVfdReport report;
   5.643 +    report[0]=0x00; //Report ID
   5.644 +    report[1]=0x06; //Report size
   5.645 +    report[2]=0x1B; //Command ID
   5.646 +    report[3]=0x5C; //Command ID
   5.647 +    report[4]=0x3F; //Command ID
   5.648 +    report[5]=0x4C; //Command ID
   5.649 +    report[6]=0x44; //Command ID
   5.650 +    report[7]=0x30+aBrightness; //Brightness level
   5.651 +    Write(report);
   5.652 +    }
   5.653 +
   5.654 +/**
   5.655 +*/
   5.656 +bool GP1212A01A::PowerOn()
   5.657 +	{
   5.658 +	return iPowerOn;
   5.659 +	}
   5.660 +
   5.661 +/**
   5.662 +*/
   5.663 +char* GP1212A01A::DeviceId()
   5.664 +	{
   5.665 +	return iDeviceId;
   5.666 +	}
   5.667 +
   5.668 +/**
   5.669 +*/
   5.670 +char* GP1212A01A::FirmwareRevision()
   5.671 +	{
   5.672 +	return iFirmwareRevision;
   5.673 +	}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/FutabaGP1212A01.h	Thu Aug 21 21:30:38 2014 +0200
     6.3 @@ -0,0 +1,115 @@
     6.4 +//
     6.5 +//
     6.6 +//
     6.7 +
     6.8 +#ifndef FUTABA_GP1212A01_H
     6.9 +#define FUTABA_GP1212A01_H
    6.10 +
    6.11 +#include "FutabaGP1212.h"
    6.12 +#include "FutabaVfd.h"
    6.13 +
    6.14 +/**
    6.15 +GP1212A01A is a graphic display module using a FUTABA 256x64dots VFD.
    6.16 +The module do not include character ROM, the customer will compile the character
    6.17 +by themselves (from main system).
    6.18 +*/
    6.19 +class GP1212A01A : public GP1212XXXX
    6.20 +	{
    6.21 +public:
    6.22 +
    6.23 +
    6.24 +public:
    6.25 +    GP1212A01A();
    6.26 +    ~GP1212A01A();
    6.27 +
    6.28 +	//
    6.29 +	int Open();
    6.30 +	//From FutabaGraphicVfd
    6.31 +    virtual int WidthInPixels() const {return KGP12xWidthInPixels;}
    6.32 +    virtual int HeightInPixels() const {return KGP12xHeightInPixels;}
    6.33 +	virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn);
    6.34 +	virtual void SetAllPixels(unsigned char aPattern);
    6.35 +    virtual int FrameBufferSizeInBytes() const {return KGP12xFrameBufferSizeInBytes;}
    6.36 +    virtual void BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const;
    6.37 +	//From FutabaVfd
    6.38 +	virtual void SetBrightness(int aBrightness);
    6.39 +	virtual void Clear();
    6.40 +
    6.41 +	//Specific to GP1212A01A
    6.42 +	void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue);
    6.43 +    void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels);
    6.44 +    //Define display position within our display RAM
    6.45 +	void SetDisplayPosition(unsigned char aX, unsigned char aY);
    6.46 +    unsigned char DisplayPositionX() const {return iDisplayPositionX;}
    6.47 +    unsigned char DisplayPositionY() const {return iDisplayPositionY;}
    6.48 +    //
    6.49 +	void SwapBuffers();
    6.50 +    //
    6.51 +    void RequestDeviceId();
    6.52 +    void RequestFirmwareRevision();
    6.53 +    void RequestPowerSupplyStatus();
    6.54 +	//
    6.55 +	void ToggleOffScreenMode();
    6.56 +    void SetOffScreenMode(bool aOn);
    6.57 +    bool OffScreenMode() const {return iOffScreenMode;}
    6.58 +    //
    6.59 +    void SetFrameDifferencing(bool aOn){iUseFrameDifferencing=aOn;}
    6.60 +    bool FrameDifferencing() const {return iUseFrameDifferencing;}
    6.61 +    //
    6.62 +    bool RequestPending(){return iRequest!=EMiniDisplayRequestNone;}
    6.63 +    TMiniDisplayRequest CurrentRequest(){return iRequest;}
    6.64 +    void CancelRequest(){iRequest=EMiniDisplayRequestNone;}
    6.65 +    TMiniDisplayRequest AttemptRequestCompletion();
    6.66 +    FutabaVfdReport& InputReport() {return iInputReport;}
    6.67 +    bool PowerOn();
    6.68 +	char* DeviceId();
    6.69 +	char* FirmwareRevision();
    6.70 +
    6.71 +private:
    6.72 +	enum DW
    6.73 +		{
    6.74 +        DW1=0xC0,
    6.75 +        DW2=0xD0
    6.76 +		};
    6.77 +
    6.78 +	void SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY);
    6.79 +	unsigned char OffScreenY() const;
    6.80 +	void SendClearCommand();
    6.81 +	void OffScreenTranslation(unsigned char& aX, unsigned char& aY);
    6.82 +	void ResetBuffers();
    6.83 +    void SendModifiedPixelBlocks();
    6.84 +
    6.85 +private:
    6.86 +	unsigned char iDisplayPositionX;
    6.87 +	unsigned char iDisplayPositionY;
    6.88 +	///Off screen mode is the recommended default settings to avoid tearing.
    6.89 +	///Though turning it off can be useful for debugging
    6.90 +	bool iOffScreenMode;
    6.91 +    ///Frame differences algo is used to reduce USB bus traffic and improve frame rate in typical use case
    6.92 +    bool iUseFrameDifferencing;
    6.93 +	///
    6.94 +	//FutabaVfdReport iReport;
    6.95 +	///
    6.96 +	//unsigned char iFrameBuffer[256*64];
    6.97 +    BitArray* iFrameNext;
    6.98 +    BitArray* iFrameCurrent;
    6.99 +    BitArray* iFramePrevious;
   6.100 +    //
   6.101 +    BitArray* iFrameAlpha;
   6.102 +    BitArray* iFrameBeta;
   6.103 +    BitArray* iFrameGamma;
   6.104 +    //
   6.105 +    int iNeedFullFrameUpdate;
   6.106 +	//unsigned char iFrameBeta[256*64];
   6.107 +	//unsigned char *iFrontBuffer;
   6.108 +	//unsigned char *iBackBuffer;
   6.109 +    TMiniDisplayRequest iRequest;
   6.110 +    FutabaVfdReport iInputReport;
   6.111 +	//
   6.112 +	char iDeviceId[KFutabaMaxHidReportSize];
   6.113 +	char iFirmwareRevision[KFutabaMaxHidReportSize];
   6.114 +    bool iPowerOn;
   6.115 +	};
   6.116 +
   6.117 +
   6.118 +#endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/FutabaGP1212A02.cpp	Thu Aug 21 21:30:38 2014 +0200
     7.3 @@ -0,0 +1,5 @@
     7.4 +//
     7.5 +//
     7.6 +//
     7.7 +
     7.8 +#include "FutabaGP1212A02.h"
     7.9 \ No newline at end of file
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/FutabaGP1212A02.h	Thu Aug 21 21:30:38 2014 +0200
     8.3 @@ -0,0 +1,12 @@
     8.4 +//
     8.5 +//
     8.6 +//
     8.7 +
     8.8 +#ifndef FUTABA_GP1212A02_H
     8.9 +#define FUTABA_GP1212A02_H
    8.10 +
    8.11 +#include "FutabaGP1212.h"
    8.12 +
    8.13 +
    8.14 +
    8.15 +#endif
     9.1 --- a/FutabaVfd.cpp	Sat Jul 12 13:15:31 2014 +0200
     9.2 +++ b/FutabaVfd.cpp	Thu Aug 21 21:30:38 2014 +0200
     9.3 @@ -10,7 +10,7 @@
     9.4  #endif
     9.5  
     9.6  
     9.7 -const int KNumberOfFrameBeforeDiffAlgo = 3;
     9.8 +
     9.9  
    9.10  //
    9.11  //
    9.12 @@ -67,668 +67,6 @@
    9.13  
    9.14  
    9.15  
    9.16 -//
    9.17 -// class GP1212A01A
    9.18 -//
    9.19  
    9.20 -GP1212A01A::GP1212A01A():
    9.21 -	iDisplayPositionX(0),iDisplayPositionY(0),
    9.22 -    iOffScreenMode(true),
    9.23 -    iUseFrameDifferencing(true),
    9.24 -    iFrameNext(NULL),
    9.25 -    iFrameCurrent(NULL),
    9.26 -    iFramePrevious(NULL),
    9.27 -    iFrameAlpha(NULL),
    9.28 -    iFrameBeta(NULL),
    9.29 -    iFrameGamma(NULL),
    9.30 -    iNeedFullFrameUpdate(0),
    9.31 -    iRequest(EMiniDisplayRequestNone),iPowerOn(false)
    9.32 -	{
    9.33 -	iDeviceId[0]=0;
    9.34 -	iFirmwareRevision[0]=0;
    9.35 -	//ResetBuffers();
    9.36 -	}
    9.37  
    9.38 -/**
    9.39 -*/
    9.40 -GP1212A01A::~GP1212A01A()
    9.41 -	{
    9.42 -    delete iFrameAlpha;
    9.43 -    iFrameAlpha=NULL;
    9.44 -    //
    9.45 -    delete iFrameBeta;
    9.46 -    iFrameBeta=NULL;
    9.47 -    //
    9.48 -    delete iFrameGamma;
    9.49 -    iFrameGamma=NULL;
    9.50 -    //
    9.51 -    iFrameNext=NULL;
    9.52 -    iFrameCurrent=NULL;
    9.53 -    iFramePrevious=NULL;
    9.54 -    //
    9.55 -    iNeedFullFrameUpdate=0;
    9.56 -	}
    9.57  
    9.58 -/**
    9.59 -*/
    9.60 -int GP1212A01A::Open()
    9.61 -	{
    9.62 -	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    9.63 -	if (success)
    9.64 -		{
    9.65 -        //Allocate both frames
    9.66 -        delete iFrameAlpha;
    9.67 -        iFrameAlpha=NULL;
    9.68 -        iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
    9.69 -        //
    9.70 -        delete iFrameBeta;
    9.71 -        iFrameBeta=NULL;
    9.72 -        iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
    9.73 -        //
    9.74 -        delete iFrameGamma;
    9.75 -        iFrameGamma=NULL;
    9.76 -        iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount);
    9.77 -        //
    9.78 -        iFrameNext=iFrameAlpha;
    9.79 -        iFrameCurrent=iFrameBeta;
    9.80 -        iFramePrevious=iFrameGamma;
    9.81 -
    9.82 -
    9.83 -        //To make sure it is synced properly
    9.84 -        iNeedFullFrameUpdate=0;
    9.85 -        //
    9.86 -		SetNonBlocking(1);
    9.87 -        //Since we can't get our display position we force it to our default
    9.88 -		//This makes sure frames are in sync from the start
    9.89 -        //Clever clients will have taken care of putting back frame (0,0) before closing
    9.90 -		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
    9.91 -		}
    9.92 -	return success;
    9.93 -	}
    9.94 -
    9.95 -/**
    9.96 -*/
    9.97 -void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
    9.98 -	{
    9.99 -	//
   9.100 -	//int byteOffset=(aX*HeightInPixels()+aY)/8;
   9.101 -	//int bitOffset=(aX*HeightInPixels()+aY)%8;
   9.102 -    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
   9.103 -
   9.104 -    if (iOffScreenMode)
   9.105 -        {
   9.106 -        if (aOn)
   9.107 -            {
   9.108 -            iFrameNext->SetBit(aX*HeightInPixels()+aY);
   9.109 -            }
   9.110 -        else
   9.111 -            {
   9.112 -            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
   9.113 -            }
   9.114 -        }
   9.115 -    else
   9.116 -        {
   9.117 -        //Just specify a one pixel block
   9.118 -        SetPixelBlock(aX,aY,0x00,0x01,aOn);
   9.119 -        }
   9.120 -	}
   9.121 -
   9.122 -/**
   9.123 -*/
   9.124 -void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
   9.125 -	{
   9.126 -	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
   9.127 -	for (int i=0;i<aSrcWidth;i++)
   9.128 -		{
   9.129 -		for (int j=0;j<aSrcHeight;j++)
   9.130 -			{
   9.131 -            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
   9.132 -			}
   9.133 -		}
   9.134 -	}
   9.135 -
   9.136 -/**
   9.137 -Clear our client side back buffer.
   9.138 -Call to SwapBuffers must follow to actually clear the display.
   9.139 -*/
   9.140 -void GP1212A01A::Clear()
   9.141 -    {
   9.142 -    //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
   9.143 -    if (iOffScreenMode)
   9.144 -        {
   9.145 -        iFrameNext->ClearAll();
   9.146 -        }
   9.147 -    else
   9.148 -        {
   9.149 -        SendClearCommand();
   9.150 -        }
   9.151 -    }
   9.152 -
   9.153 -/**
   9.154 -Set all pixels on our screen to the desired value.
   9.155 -This operation is performed off screen to avoid tearing.
   9.156 -@param 8 pixels pattern
   9.157 -*/
   9.158 -void GP1212A01A::SetAllPixels(unsigned char aPattern)
   9.159 -	{
   9.160 -	//With a single buffer
   9.161 -	//unsigned char screen[2048]; //One screen worth of pixels
   9.162 -	//memset(screen,0xFF,sizeof(screen));
   9.163 -	//SetPixelBlock(0,0,63,sizeof(screen),screen);
   9.164 -
   9.165 -
   9.166 -    if (iOffScreenMode)
   9.167 -        {
   9.168 -        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
   9.169 -        }
   9.170 -    else
   9.171 -        {
   9.172 -        //Using pattern SetPixelBlock variant.
   9.173 -        SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
   9.174 -        }
   9.175 -	//
   9.176 -	}
   9.177 -
   9.178 -
   9.179 -/**
   9.180 -Set the defined pixel block to the given value.
   9.181 -@param X coordinate of our pixel block starting point.
   9.182 -@param Y coordinate of our pixel block starting point.
   9.183 -@param The height of our pixel block.
   9.184 -@param The size of our pixel data. Number of pixels divided by 8.
   9.185 -@param The value set to 8 pixels used as a pattern.
   9.186 -*/
   9.187 -void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
   9.188 -	{
   9.189 -	OffScreenTranslation(aX,aY);
   9.190 -    FutabaVfdReport report;
   9.191 -    report[0]=0x00; //Report ID
   9.192 -    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
   9.193 -    report[2]=0x1B; //Command ID
   9.194 -    report[3]=0x5B; //Command ID
   9.195 -    report[4]=0xF0; //Command ID
   9.196 -    report[5]=aX;   //X
   9.197 -    report[6]=aY;   //Y
   9.198 -    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.
   9.199 -	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   9.200 -	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   9.201 -    int sizeWritten=MIN(aSize,report.Size()-10);
   9.202 -    memset(report.Buffer()+10, aValue, sizeWritten);
   9.203 -    Write(report);
   9.204 -
   9.205 -    int remainingSize=aSize;
   9.206 -    //We need to keep on sending our pixel data until we are done
   9.207 -    while (report[1]==64)
   9.208 -        {
   9.209 -        report.Reset();
   9.210 -        remainingSize-=sizeWritten;
   9.211 -        report[0]=0x00; //Report ID
   9.212 -        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   9.213 -        sizeWritten=(report[1]==64?63:report[1]);
   9.214 -        memset(report.Buffer()+2, aValue, sizeWritten);
   9.215 -        Write(report);
   9.216 -        }
   9.217 -	}
   9.218 -
   9.219 -/**
   9.220 -Set the defined pixel block to the given value.
   9.221 -@param X coordinate of our pixel block starting point.
   9.222 -@param Y coordinate of our pixel block starting point.
   9.223 -@param The height of our pixel block.
   9.224 -@param The size of our pixel data. Number of pixels divided by 8.
   9.225 -@param Pointer to our pixel data.
   9.226 -*/
   9.227 -void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   9.228 -    {
   9.229 -	OffScreenTranslation(aX,aY);
   9.230 -    FutabaVfdReport report;
   9.231 -    report[0]=0x00; //Report ID
   9.232 -    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
   9.233 -    report[2]=0x1B; //Command ID
   9.234 -    report[3]=0x5B; //Command ID
   9.235 -    report[4]=0xF0; //Command ID
   9.236 -    report[5]=aX;   //X
   9.237 -    report[6]=aY;   //Y
   9.238 -    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.
   9.239 -	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   9.240 -	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   9.241 -    int sizeWritten=MIN(aSize,report.Size()-10);
   9.242 -    memcpy(report.Buffer()+10, aPixels, sizeWritten);
   9.243 -    Write(report);
   9.244 -
   9.245 -    int remainingSize=aSize;
   9.246 -    //We need to keep on sending our pixel data until we are done
   9.247 -    while (report[1]==64)
   9.248 -        {
   9.249 -        report.Reset();
   9.250 -        remainingSize-=sizeWritten;
   9.251 -        report[0]=0x00; //Report ID
   9.252 -        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   9.253 -        sizeWritten=(report[1]==64?63:report[1]);
   9.254 -        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   9.255 -        Write(report);
   9.256 -        }
   9.257 -    }
   9.258 -
   9.259 -/**
   9.260 -Using this function is advised against as is causes tearing.
   9.261 -Use Clear instead.
   9.262 -*/
   9.263 -void GP1212A01A::SendClearCommand()
   9.264 -	{
   9.265 -    //1BH,5BH,32H,4AH
   9.266 -    //Send Clear Display Command
   9.267 -	FutabaVfdReport report;
   9.268 -	report[0]=0x00; //Report ID
   9.269 -	report[1]=0x04; //Report length
   9.270 -	report[2]=0x1B; //Command ID
   9.271 -	report[3]=0x5B; //Command ID
   9.272 -	report[4]=0x32; //Command ID
   9.273 -	report[5]=0x4A; //Command ID
   9.274 -	Write(report);
   9.275 -	}
   9.276 -
   9.277 -/**
   9.278 -Change our display position within our buffer.
   9.279 -*/
   9.280 -void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   9.281 -    {
   9.282 -    //1BH,5BH,Dw,Px,Py
   9.283 -    //Send Display Position Settings Command
   9.284 -    FutabaVfdReport report;
   9.285 -    report[0]=0x00; //Report ID
   9.286 -    report[1]=0x05; //Report length
   9.287 -    report[2]=0x1B; //Command ID
   9.288 -    report[3]=0x5B; //Command ID
   9.289 -    report[4]=aDw;  //Specify our DW
   9.290 -    report[5]=aX;   //X coordinate of our DW top-left corner
   9.291 -    report[6]=aY;   //Y coordinate of our DW top-left corner
   9.292 -    Write(report);
   9.293 -    }
   9.294 -
   9.295 -/**
   9.296 -Change our display position within our buffer.
   9.297 -*/
   9.298 -void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   9.299 -	{
   9.300 -	//Specs apparently says both DW should remain the same
   9.301 -	//Just don't ask
   9.302 -    SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   9.303 -    SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   9.304 -	iDisplayPositionX=aX;
   9.305 -	iDisplayPositionY=aY;
   9.306 -	}
   9.307 -
   9.308 -/**
   9.309 -Provide Y coordinate of our off screen buffer.
   9.310 -*/
   9.311 -unsigned char GP1212A01A::OffScreenY() const
   9.312 -	{
   9.313 -	//Overflowing is fine this is just what we want
   9.314 -	return iDisplayPositionY+HeightInPixels();
   9.315 -	}
   9.316 -
   9.317 -/**
   9.318 -Put our off screen buffer on screen.
   9.319 -On screen buffer goes off screen.
   9.320 -*/
   9.321 -void GP1212A01A::SwapBuffers()
   9.322 -	{
   9.323 -	//Only perform buffer swapping if off screen mode is enabled
   9.324 -	if (OffScreenMode())
   9.325 -		{
   9.326 -		//Send host back buffer to device back buffer
   9.327 -        if (!iUseFrameDifferencing || iNeedFullFrameUpdate<KNumberOfFrameBeforeDiffAlgo)
   9.328 -            {
   9.329 -            iNeedFullFrameUpdate++;
   9.330 -            SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameNext->Ptr());
   9.331 -            }
   9.332 -        else
   9.333 -            {
   9.334 -            //Frame diff algo is enabled
   9.335 -            //We are going to send to our device only the differences between next frame and previous frame
   9.336 -            SendModifiedPixelBlocks();
   9.337 -            }
   9.338 -		//Swap device front and back buffer
   9.339 -		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   9.340 -
   9.341 -        //Cycle through our frame buffers
   9.342 -        //We keep track of previous frame which is in fact our device back buffer.
   9.343 -        //We can then compare previous and next frame and send only the differences to our device.
   9.344 -        //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
   9.345 -        //Keep our previous frame pointer
   9.346 -        BitArray* previousFrame=iFramePrevious;
   9.347 -        //Current frame becomes the previous one
   9.348 -        iFramePrevious = iFrameCurrent;
   9.349 -        //Next frame becomes the current one
   9.350 -        iFrameCurrent = iFrameNext;
   9.351 -        //Next frame is now our former previous
   9.352 -        iFrameNext = previousFrame;
   9.353 -		}
   9.354 -	}
   9.355 -
   9.356 -
   9.357 -//Define the edge of our pixel block
   9.358 -//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
   9.359 -//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
   9.360 -const int KPixelBlockEdge = 32;
   9.361 -const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
   9.362 -const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
   9.363 -
   9.364 -
   9.365 -/**
   9.366 - * @brief GP1212A01A::SendModifiedPixelBlocks
   9.367 - * Compare our back and front buffer and send to the device only the modified pixels.
   9.368 - */
   9.369 -void GP1212A01A::SendModifiedPixelBlocks()
   9.370 -    {
   9.371 -    int w=WidthInPixels();
   9.372 -    int h=HeightInPixels();
   9.373 -
   9.374 -
   9.375 -    //TODO: optimize with memcmp and 16 inc
   9.376 -    /*
   9.377 -
   9.378 -    for (int i=0;i<w;i++)
   9.379 -        {
   9.380 -        for (int j=0;j<h;j++)
   9.381 -            {
   9.382 -            //aX*HeightInPixels()+aY
   9.383 -            if ((*iFrameNext)[i*h+j]!=(*iFramePrevious)[i*h+j])
   9.384 -                {
   9.385 -                //We need to update that pixel
   9.386 -                SetPixelBlock(i,j,0,1,((*iFrameNext)[i*h+j]?0x01:0x00));
   9.387 -                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   9.388 -                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   9.389 -
   9.390 -                //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
   9.391 -                }
   9.392 -            }
   9.393 -        }
   9.394 -    */
   9.395 -
   9.396 -    BitArray nextBlock(KPixelBlockSizeInBits);
   9.397 -    BitArray previousBlock(KPixelBlockSizeInBits);
   9.398 -
   9.399 -    for (int i=0;i<w;i+=KPixelBlockEdge)
   9.400 -        {
   9.401 -        for (int j=0;j<h;j+=KPixelBlockEdge)
   9.402 -            {
   9.403 -            //aX*HeightInPixels()+aY
   9.404 -            //int offset=(i*w/8)+(j/8);
   9.405 -
   9.406 -#ifdef DEBUG_FRAME_DIFF
   9.407 -            QImage imagePrevious(KPixelBlockEdge,KPixelBlockEdge,QImage::Format_RGB32);
   9.408 -            QImage imageNext(KPixelBlockEdge,KPixelBlockEdge,QImage::Format_RGB32);
   9.409 -#endif
   9.410 -
   9.411 -            //Get both our blocks from our buffers
   9.412 -            for (int x=i;x<i+KPixelBlockEdge;x++)
   9.413 -                {
   9.414 -                for (int y=j;y<j+KPixelBlockEdge;y++)
   9.415 -                    {
   9.416 -                    int blockOffset=(x-i)*KPixelBlockEdge+(y-j);
   9.417 -                    int frameOffset=x*h+y;
   9.418 -                    nextBlock.SetBitValue(blockOffset,(*iFrameNext)[frameOffset]);
   9.419 -                    previousBlock.SetBitValue(blockOffset,(*iFramePrevious)[frameOffset]);
   9.420 -
   9.421 -#ifdef DEBUG_FRAME_DIFF
   9.422 -                    imageNext.setPixel(x-i,y-j,(nextBlock[blockOffset]?0xFFFFFFFF:0x00000000));
   9.423 -                    imagePrevious.setPixel(x-i,y-j,(previousBlock[blockOffset]?0xFFFFFFFF:0x00000000));
   9.424 -#endif
   9.425 -                    }
   9.426 -                }
   9.427 -
   9.428 -#ifdef DEBUG_FRAME_DIFF
   9.429 -            QString previousName;
   9.430 -            QString nextName;
   9.431 -            QTextStream(&previousName) << "p" << i << "x" << j << ".png";
   9.432 -            QTextStream(&nextName) << "n" << i << "x" << j << ".png";
   9.433 -            imagePrevious.save(previousName);
   9.434 -            imageNext.save(nextName);
   9.435 -#endif
   9.436 -
   9.437 -
   9.438 -            //if (memcmp(iFrameNext->Ptr()+offset,iFramePrevious->Ptr()+offset,32 )) //32=(16*16/8)
   9.439 -            if (memcmp(nextBlock.Ptr(),previousBlock.Ptr(),KPixelBlockSizeInBytes)!=0)
   9.440 -                {
   9.441 -                //We need to update that block
   9.442 -                SetPixelBlock(i,j,KPixelBlockEdge-1,KPixelBlockSizeInBytes,nextBlock.Ptr());
   9.443 -                //SetPixelBlock(i,j,15,32,0xFF/*nextBlock.Ptr()*/);
   9.444 -                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   9.445 -                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   9.446 -
   9.447 -                //SetPixelBlock(i,j,15,32,iFrameNext->Ptr()+offset);
   9.448 -                }
   9.449 -            }
   9.450 -        }
   9.451 -
   9.452 -    }
   9.453 -
   9.454 -/**
   9.455 -Translate the given pixel coordinate according to our off screen mode.
   9.456 -*/
   9.457 -void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   9.458 -	{
   9.459 -	if (OffScreenMode())
   9.460 -		{
   9.461 -		aX+=WidthInPixels()-iDisplayPositionX;
   9.462 -		aY+=HeightInPixels()-iDisplayPositionY;
   9.463 -		}
   9.464 -	}
   9.465 -
   9.466 -
   9.467 -/**
   9.468 -*/
   9.469 -void GP1212A01A::ResetBuffers()
   9.470 -	{
   9.471 -    //iNextFrame->ClearAll();
   9.472 -    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
   9.473 -	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
   9.474 -	}
   9.475 -
   9.476 -/**
   9.477 -*/
   9.478 -void GP1212A01A::RequestDeviceId()
   9.479 -    {
   9.480 -    if (RequestPending())
   9.481 -        {
   9.482 -        //Abort silently for now
   9.483 -        return;
   9.484 -        }
   9.485 -
   9.486 -    //1BH,5BH,63H,49H,44H
   9.487 -    //Send Read ID command
   9.488 -    FutabaVfdReport report;
   9.489 -    report[0]=0x00; //Report ID
   9.490 -    report[1]=0x05; //Report length
   9.491 -    report[2]=0x1B; //Command ID
   9.492 -    report[3]=0x5B; //Command ID
   9.493 -    report[4]=0x63; //Command ID
   9.494 -    report[5]=0x49; //Command ID
   9.495 -    report[6]=0x44; //Command ID
   9.496 -    if (Write(report)==report.Size())
   9.497 -        {
   9.498 -        iRequest=EMiniDisplayRequestDeviceId;
   9.499 -        }
   9.500 -    }
   9.501 -
   9.502 -/**
   9.503 -*/
   9.504 -void GP1212A01A::RequestFirmwareRevision()
   9.505 -    {
   9.506 -    if (RequestPending())
   9.507 -        {
   9.508 -        //Abort silently for now
   9.509 -        return;
   9.510 -        }
   9.511 -
   9.512 -    //1BH,5BH,63H,46H,52H
   9.513 -    //Send Software Revision Read Command
   9.514 -    FutabaVfdReport report;
   9.515 -    report[0]=0x00; //Report ID
   9.516 -    report[1]=0x05; //Report length
   9.517 -    report[2]=0x1B; //Command ID
   9.518 -    report[3]=0x5B; //Command ID
   9.519 -    report[4]=0x63; //Command ID
   9.520 -    report[5]=0x46; //Command ID
   9.521 -    report[6]=0x52; //Command ID
   9.522 -    if (Write(report)==report.Size())
   9.523 -        {
   9.524 -        iRequest=EMiniDisplayRequestFirmwareRevision;
   9.525 -        }
   9.526 -    }
   9.527 -
   9.528 -/**
   9.529 -*/
   9.530 -void GP1212A01A::RequestPowerSupplyStatus()
   9.531 -    {
   9.532 -    if (RequestPending())
   9.533 -        {
   9.534 -        //Abort silently for now
   9.535 -        return;
   9.536 -        }
   9.537 -    //1BH,5BH,63H,50H,4DH
   9.538 -    //Send Power Suppply Monitor Command
   9.539 -    FutabaVfdReport report;
   9.540 -    report[0]=0x00; //Report ID
   9.541 -    report[1]=0x05; //Report length
   9.542 -    report[2]=0x1B; //Command ID
   9.543 -    report[3]=0x5B; //Command ID
   9.544 -    report[4]=0x63; //Command ID
   9.545 -    report[5]=0x50; //Command ID
   9.546 -    report[6]=0x4D; //Command ID
   9.547 -    if (Write(report)==report.Size())
   9.548 -        {
   9.549 -        iRequest=EMiniDisplayRequestPowerSupplyStatus;
   9.550 -        }
   9.551 -    }
   9.552 -
   9.553 -
   9.554 -/**
   9.555 -This is for development purposes only.
   9.556 -Production application should stick to off-screen mode to avoid tearing.
   9.557 -*/
   9.558 -void GP1212A01A::ToggleOffScreenMode()
   9.559 -	{
   9.560 -    SetOffScreenMode(!iOffScreenMode);
   9.561 -	}
   9.562 -
   9.563 -/**
   9.564 - * @brief GP1212A01A::SetOffScreenMode
   9.565 - * @param aOn
   9.566 - * @return
   9.567 - */
   9.568 -void GP1212A01A::SetOffScreenMode(bool aOn)
   9.569 -    {
   9.570 -    if (aOn==iOffScreenMode)
   9.571 -    {
   9.572 -        //Nothing to do here
   9.573 -        return;
   9.574 -    }
   9.575 -
   9.576 -    iOffScreenMode=aOn;
   9.577 -
   9.578 -    //Clean up our buffers upon switching modes
   9.579 -    SetDisplayPosition(0,0);
   9.580 -    Clear();
   9.581 -    SwapBuffers();
   9.582 -    Clear();
   9.583 -    }
   9.584 -
   9.585 -/**
   9.586 -Tries to complete our current request if we have one pending.
   9.587 - */
   9.588 -TMiniDisplayRequest GP1212A01A::AttemptRequestCompletion()
   9.589 -    {
   9.590 -    if (!RequestPending())
   9.591 -        {
   9.592 -        return EMiniDisplayRequestNone;
   9.593 -        }
   9.594 -
   9.595 -    int res=Read(iInputReport);
   9.596 -
   9.597 -    if (!res)
   9.598 -        {
   9.599 -        return EMiniDisplayRequestNone;
   9.600 -        }
   9.601 -
   9.602 -    //Process our request
   9.603 -    if (CurrentRequest()==EMiniDisplayRequestPowerSupplyStatus)
   9.604 -        {
   9.605 -        if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
   9.606 -            {
   9.607 -            iPowerOn = true;
   9.608 -            }
   9.609 -        else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
   9.610 -            {
   9.611 -            iPowerOn = false;
   9.612 -            }
   9.613 -        }
   9.614 -	else if (CurrentRequest()==EMiniDisplayRequestDeviceId)
   9.615 -		{
   9.616 -			unsigned char* ptr=&iInputReport[1];
   9.617 -			strcpy(iDeviceId,(const char*)ptr);
   9.618 -		}
   9.619 -	else if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision)
   9.620 -		{
   9.621 -			unsigned char* ptr=&iInputReport[1];
   9.622 -			strcpy(iFirmwareRevision,(const char*)ptr);
   9.623 -		}
   9.624 -
   9.625 -    TMiniDisplayRequest completed=iRequest;
   9.626 -    //Our request was completed
   9.627 -    iRequest=EMiniDisplayRequestNone;
   9.628 -
   9.629 -    return completed;
   9.630 -    }
   9.631 -
   9.632 -
   9.633 -/**
   9.634 -Set our screen brightness.
   9.635 -@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
   9.636 -*/
   9.637 -void GP1212A01A::SetBrightness(int aBrightness)
   9.638 -    {
   9.639 -    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
   9.640 -        {
   9.641 -        //Brightness out of range.
   9.642 -        //Just ignore that request.
   9.643 -        return;
   9.644 -        }
   9.645 -
   9.646 -    FutabaVfdReport report;
   9.647 -    report[0]=0x00; //Report ID
   9.648 -    report[1]=0x06; //Report size
   9.649 -    report[2]=0x1B; //Command ID
   9.650 -    report[3]=0x5C; //Command ID
   9.651 -    report[4]=0x3F; //Command ID
   9.652 -    report[5]=0x4C; //Command ID
   9.653 -    report[6]=0x44; //Command ID
   9.654 -    report[7]=0x30+aBrightness; //Brightness level
   9.655 -    Write(report);
   9.656 -    }
   9.657 -
   9.658 -/**
   9.659 -*/
   9.660 -bool GP1212A01A::PowerOn()
   9.661 -	{
   9.662 -	return iPowerOn;
   9.663 -	}
   9.664 -
   9.665 -/**
   9.666 -*/
   9.667 -char* GP1212A01A::DeviceId()
   9.668 -	{
   9.669 -	return iDeviceId;
   9.670 -	}
   9.671 -
   9.672 -/**
   9.673 -*/
   9.674 -char* GP1212A01A::FirmwareRevision()
   9.675 -	{
   9.676 -	return iFirmwareRevision;
   9.677 -	}
   9.678 -
   9.679 -
   9.680 -
    10.1 --- a/FutabaVfd.h	Sat Jul 12 13:15:31 2014 +0200
    10.2 +++ b/FutabaVfd.h	Thu Aug 21 21:30:38 2014 +0200
    10.3 @@ -73,145 +73,5 @@
    10.4      int iMaxSize;
    10.5      };
    10.6  
    10.7 -/**
    10.8 -*/
    10.9 -class FutabaVfd : public HidDevice
   10.10 -	{
   10.11 -public:
   10.12 -	virtual int MinBrightness() const=0;
   10.13 -	virtual int MaxBrightness() const=0;
   10.14 -	virtual void SetBrightness(int aBrightness)=0;
   10.15 -	virtual void Clear()=0;
   10.16 -	};
   10.17 -
   10.18 -
   10.19 -/**
   10.20 -*/
   10.21 -class FutabaGraphicVfd : public FutabaVfd
   10.22 -	{
   10.23 -public:
   10.24 -	virtual int WidthInPixels() const=0;
   10.25 -	virtual int HeightInPixels() const=0;
   10.26 -	virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn)=0;
   10.27 -	virtual void SetAllPixels(unsigned char aOn)=0;
   10.28 -	virtual int FrameBufferSizeInBytes() const=0;
   10.29 -	//virtual int BitBlit(unsigned char* aSrc, unsigned char aSrcWidth, unsigned char aSrcHeight, unsigned char aTargetX, unsigned char aTargetY) const=0;
   10.30 -
   10.31 -	};
   10.32 -
   10.33 -/**
   10.34 -Common functionality between GP1212A01A and GP1212A02A
   10.35 -*/
   10.36 -class GP1212XXXX : public FutabaGraphicVfd
   10.37 -	{
   10.38 -public:
   10.39 -	//From FutabaVfd
   10.40 -    virtual int MinBrightness() const {return 0;}
   10.41 -    virtual int MaxBrightness() const {return 5;}
   10.42 -	};
   10.43 -
   10.44 -/**
   10.45 -GP1212A01A is a graphic display module using a FUTABA 256x64dots VFD.
   10.46 -The module do not include character ROM, the customer will compile the character
   10.47 -by themselves (from main system).
   10.48 -*/
   10.49 -class GP1212A01A : public GP1212XXXX
   10.50 -	{
   10.51 -public:
   10.52 -
   10.53 -
   10.54 -public:
   10.55 -    GP1212A01A();
   10.56 -    ~GP1212A01A();
   10.57 -
   10.58 -	//
   10.59 -	int Open();
   10.60 -	//From FutabaGraphicVfd
   10.61 -    virtual int WidthInPixels() const {return KGP12xWidthInPixels;}
   10.62 -    virtual int HeightInPixels() const {return KGP12xHeightInPixels;}
   10.63 -	virtual void SetPixel(unsigned char aX, unsigned char aY, bool aOn);
   10.64 -	virtual void SetAllPixels(unsigned char aPattern);
   10.65 -    virtual int FrameBufferSizeInBytes() const {return KGP12xFrameBufferSizeInBytes;}
   10.66 -    virtual void BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const;
   10.67 -	//From FutabaVfd
   10.68 -	virtual void SetBrightness(int aBrightness);
   10.69 -	virtual void Clear();
   10.70 -
   10.71 -	//Specific to GP1212A01A
   10.72 -	void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue);
   10.73 -    void SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels);
   10.74 -    //Define display position within our display RAM
   10.75 -	void SetDisplayPosition(unsigned char aX, unsigned char aY);
   10.76 -    unsigned char DisplayPositionX() const {return iDisplayPositionX;}
   10.77 -    unsigned char DisplayPositionY() const {return iDisplayPositionY;}
   10.78 -    //
   10.79 -	void SwapBuffers();
   10.80 -    //
   10.81 -    void RequestDeviceId();
   10.82 -    void RequestFirmwareRevision();
   10.83 -    void RequestPowerSupplyStatus();
   10.84 -	//
   10.85 -	void ToggleOffScreenMode();
   10.86 -    void SetOffScreenMode(bool aOn);
   10.87 -    bool OffScreenMode() const {return iOffScreenMode;}
   10.88 -    //
   10.89 -    void SetFrameDifferencing(bool aOn){iUseFrameDifferencing=aOn;}
   10.90 -    bool FrameDifferencing() const {return iUseFrameDifferencing;}
   10.91 -    //
   10.92 -    bool RequestPending(){return iRequest!=EMiniDisplayRequestNone;}
   10.93 -    TMiniDisplayRequest CurrentRequest(){return iRequest;}
   10.94 -    void CancelRequest(){iRequest=EMiniDisplayRequestNone;}
   10.95 -    TMiniDisplayRequest AttemptRequestCompletion();
   10.96 -    FutabaVfdReport& InputReport() {return iInputReport;}
   10.97 -    bool PowerOn();
   10.98 -	char* DeviceId();
   10.99 -	char* FirmwareRevision();
  10.100 -
  10.101 -private:
  10.102 -	enum DW
  10.103 -		{
  10.104 -        DW1=0xC0,
  10.105 -        DW2=0xD0
  10.106 -		};
  10.107 -
  10.108 -	void SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY);
  10.109 -	unsigned char OffScreenY() const;
  10.110 -	void SendClearCommand();
  10.111 -	void OffScreenTranslation(unsigned char& aX, unsigned char& aY);
  10.112 -	void ResetBuffers();
  10.113 -    void SendModifiedPixelBlocks();
  10.114 -
  10.115 -private:
  10.116 -	unsigned char iDisplayPositionX;
  10.117 -	unsigned char iDisplayPositionY;
  10.118 -	///Off screen mode is the recommended default settings to avoid tearing.
  10.119 -	///Though turning it off can be useful for debugging
  10.120 -	bool iOffScreenMode;
  10.121 -    ///Frame differences algo is used to reduce USB bus traffic and improve frame rate in typical use case
  10.122 -    bool iUseFrameDifferencing;
  10.123 -	///
  10.124 -	//FutabaVfdReport iReport;
  10.125 -	///
  10.126 -	//unsigned char iFrameBuffer[256*64];
  10.127 -    BitArray* iFrameNext;
  10.128 -    BitArray* iFrameCurrent;
  10.129 -    BitArray* iFramePrevious;
  10.130 -    //
  10.131 -    BitArray* iFrameAlpha;
  10.132 -    BitArray* iFrameBeta;
  10.133 -    BitArray* iFrameGamma;
  10.134 -    //
  10.135 -    int iNeedFullFrameUpdate;
  10.136 -	//unsigned char iFrameBeta[256*64];
  10.137 -	//unsigned char *iFrontBuffer;
  10.138 -	//unsigned char *iBackBuffer;
  10.139 -    TMiniDisplayRequest iRequest;
  10.140 -    FutabaVfdReport iInputReport;
  10.141 -	//
  10.142 -	char iDeviceId[KFutabaMaxHidReportSize];
  10.143 -	char iFirmwareRevision[KFutabaMaxHidReportSize];
  10.144 -    bool iPowerOn;
  10.145 -	};
  10.146 -
  10.147  
  10.148  #endif
    11.1 --- a/MiniDisplay.cpp	Sat Jul 12 13:15:31 2014 +0200
    11.2 +++ b/MiniDisplay.cpp	Thu Aug 21 21:30:38 2014 +0200
    11.3 @@ -1,13 +1,13 @@
    11.4  
    11.5  #include "MiniDisplay.h"
    11.6 -#include "FutabaVfd.h"
    11.7 +#include "FutabaGP1212A01.h"
    11.8  
    11.9  
   11.10  
   11.11  
   11.12  
   11.13  //Open & Close functions
   11.14 -MiniDisplayDevice MiniDisplayOpen()
   11.15 +MiniDisplayDevice MiniDisplayOpen(TMiniDisplayType aType)
   11.16  	{
   11.17  	GP1212A01A* device=NULL;
   11.18  	device=new GP1212A01A();
    12.1 --- a/MiniDisplay.h	Sat Jul 12 13:15:31 2014 +0200
    12.2 +++ b/MiniDisplay.h	Thu Aug 21 21:30:38 2014 +0200
    12.3 @@ -27,6 +27,14 @@
    12.4  
    12.5  typedef enum
    12.6      {
    12.7 +	EMiniDisplayAutoDetect=0, /*Not yet implemented*/
    12.8 +    EMiniDisplayFutabaGP1212A01,
    12.9 +    EMiniDisplayFutabaGP1212A02
   12.10 +    }
   12.11 +TMiniDisplayType;
   12.12 +
   12.13 +typedef enum
   12.14 +    {
   12.15      EMiniDisplayRequestNone,
   12.16      EMiniDisplayRequestDeviceId,
   12.17      EMiniDisplayRequestFirmwareRevision,
   12.18 @@ -35,7 +43,7 @@
   12.19  TMiniDisplayRequest;
   12.20  
   12.21  //Open & Close functions
   12.22 -extern "C" MDAPI MiniDisplayDevice MiniDisplayOpen();
   12.23 +extern "C" MDAPI MiniDisplayDevice MiniDisplayOpen(TMiniDisplayType aType);
   12.24  extern "C" MDAPI void MiniDisplayClose(MiniDisplayDevice aDevice);
   12.25  
   12.26  /**