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 /**