MiniDisplay/FutabaVfd.cpp
changeset 19 be04ffbb561c
parent 18 79801cc3bc94
child 20 cd6d76b9b47e
     1.1 --- a/MiniDisplay/FutabaVfd.cpp	Thu May 29 19:46:57 2014 +0200
     1.2 +++ b/MiniDisplay/FutabaVfd.cpp	Thu May 29 21:42:07 2014 +0200
     1.3 @@ -73,7 +73,13 @@
     1.4  
     1.5  GP1212A01A::GP1212A01A():
     1.6  	iDisplayPositionX(0),iDisplayPositionY(0),
     1.7 -    iOffScreenMode(true),iFrameBuffer(NULL),iRequest(ERequestNone),iPowerOn(false)
     1.8 +    iOffScreenMode(true),
     1.9 +    iFrameAlpha(NULL),
    1.10 +    iFrameBeta(NULL),
    1.11 +    iCurrentFrame(NULL),
    1.12 +    iNextFrame(NULL),
    1.13 +    iNeedFullFrameUpdate(true),
    1.14 +    iRequest(ERequestNone),iPowerOn(false)
    1.15  	{
    1.16  	//ResetBuffers();
    1.17  	}
    1.18 @@ -82,8 +88,16 @@
    1.19  */
    1.20  GP1212A01A::~GP1212A01A()
    1.21  	{
    1.22 -	delete iFrameBuffer;
    1.23 -	iFrameBuffer=NULL;
    1.24 +    delete iFrameAlpha;
    1.25 +    iFrameAlpha=NULL;
    1.26 +    //
    1.27 +    delete iFrameBeta;
    1.28 +    iFrameBeta=NULL;
    1.29 +    //
    1.30 +    iNextFrame=NULL;
    1.31 +    iCurrentFrame=NULL;
    1.32 +    //
    1.33 +    iNeedFullFrameUpdate=true;
    1.34  	}
    1.35  
    1.36  /**
    1.37 @@ -93,9 +107,20 @@
    1.38  	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    1.39  	if (success)
    1.40  		{
    1.41 -		delete iFrameBuffer;
    1.42 -		iFrameBuffer = NULL;
    1.43 -		iFrameBuffer=new BitArray(KGP12xFrameBufferPixelCount);
    1.44 +        //Allocate both frames
    1.45 +        delete iFrameAlpha;
    1.46 +        iFrameAlpha=NULL;
    1.47 +        iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
    1.48 +        //
    1.49 +        delete iFrameBeta;
    1.50 +        iFrameBeta=NULL;
    1.51 +        iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
    1.52 +        //
    1.53 +        iCurrentFrame=iFrameAlpha;
    1.54 +        iNextFrame=iFrameBeta;
    1.55 +        //To make sure it is synced properly
    1.56 +        iNeedFullFrameUpdate=true;
    1.57 +        //
    1.58  		SetNonBlocking(1);
    1.59          //Since we can't get our display position we force it to our default
    1.60  		//This makes sure frames are in sync from the start
    1.61 @@ -112,17 +137,17 @@
    1.62  	//
    1.63  	//int byteOffset=(aX*HeightInPixels()+aY)/8;
    1.64  	//int bitOffset=(aX*HeightInPixels()+aY)%8;
    1.65 -	//iFrameBuffer[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
    1.66 +    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
    1.67  
    1.68      if (iOffScreenMode)
    1.69          {
    1.70          if (aOn)
    1.71              {
    1.72 -            iFrameBuffer->SetBit(aX*HeightInPixels()+aY);
    1.73 +            iNextFrame->SetBit(aX*HeightInPixels()+aY);
    1.74              }
    1.75          else
    1.76              {
    1.77 -            iFrameBuffer->ClearBit(aX*HeightInPixels()+aY);
    1.78 +            iNextFrame->ClearBit(aX*HeightInPixels()+aY);
    1.79              }
    1.80          }
    1.81      else
    1.82 @@ -141,7 +166,7 @@
    1.83  		{
    1.84  		for (int j=0;j<aSrcHeight;j++)
    1.85  			{
    1.86 -			iFrameBuffer->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
    1.87 +            iNextFrame->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
    1.88  			}
    1.89  		}
    1.90  	}
    1.91 @@ -161,7 +186,7 @@
    1.92  
    1.93      if (iOffScreenMode)
    1.94          {
    1.95 -        memset(iFrameBuffer->Ptr(),aPattern,FrameBufferSizeInBytes());
    1.96 +        memset(iNextFrame->Ptr(),aPattern,FrameBufferSizeInBytes());
    1.97          }
    1.98      else
    1.99          {
   1.100 @@ -259,10 +284,10 @@
   1.101  */
   1.102  void GP1212A01A::Clear()
   1.103  	{
   1.104 -	//memset(iFrameBuffer->Ptr(),0x00,FrameBufferSizeInBytes());
   1.105 +    //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
   1.106      if (iOffScreenMode)
   1.107          {
   1.108 -        iFrameBuffer->ClearAll();
   1.109 +        iNextFrame->ClearAll();
   1.110          }
   1.111      else
   1.112          {
   1.113 @@ -338,16 +363,70 @@
   1.114  	if (OffScreenMode())
   1.115  		{
   1.116  		//Send host back buffer to device back buffer
   1.117 -		SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameBuffer->Ptr());
   1.118 +        if (iNeedFullFrameUpdate)
   1.119 +            {
   1.120 +            //TODO: enable this once SendModifiedPixelBlocks works
   1.121 +            //iNeedFullFrameUpdate=false;
   1.122 +            SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iNextFrame->Ptr());
   1.123 +            }
   1.124 +        else
   1.125 +            {
   1.126 +            SendModifiedPixelBlocks();
   1.127 +            }
   1.128  		//Swap device front and back buffer
   1.129  		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   1.130  		//Swap host buffers
   1.131 -		//unsigned char* backBuffer=iBackBuffer;
   1.132 -		//iBackBuffer = iFrontBuffer;
   1.133 -		//iFrontBuffer = backBuffer;
   1.134 +        BitArray* nextFrame=iCurrentFrame;
   1.135 +        iCurrentFrame = iNextFrame;
   1.136 +        iNextFrame = nextFrame;
   1.137  		}
   1.138  	}
   1.139  
   1.140 +
   1.141 +/**
   1.142 + * @brief GP1212A01A::SendModifiedPixelBlocks
   1.143 + * Compare our back and front buffer and send to the device only the modified pixels.
   1.144 + * TODO: Get this working at some point.
   1.145 + */
   1.146 +void GP1212A01A::SendModifiedPixelBlocks()
   1.147 +    {
   1.148 +    //The largest pixel block we can sanely send with one report is 16*16
   1.149 +    //const int KBlocksPerRow = WidthInPixels()/16; //16
   1.150 +    //const int KBlocksPerColumn = HeightInPixels()/16; //4
   1.151 +
   1.152 +    int w=WidthInPixels();
   1.153 +    int h=HeightInPixels();
   1.154 +
   1.155 +    BitArray block(16*16);
   1.156 +    //TODO: optimize with memcmp and 16 inc
   1.157 +    for (int i=0;i<w;i+=16)
   1.158 +        {
   1.159 +        for (int j=0;j<h;j+=16)
   1.160 +            {
   1.161 +            //aX*HeightInPixels()+aY
   1.162 +            int offset=(i*w/8)+(j/8);
   1.163 +            if (memcmp(iNextFrame->Ptr()+offset,iCurrentFrame->Ptr()+offset,32 /*(16*16/8)*/))
   1.164 +                {
   1.165 +                //We need to update that block
   1.166 +
   1.167 +                for (int x=i;x<i+16;x++)
   1.168 +                    {
   1.169 +                    for (int y=i;y<j+16;y++)
   1.170 +                        {
   1.171 +                        block.SetBitValue((x-i)*h+(y-j),(*iNextFrame)[x*h+y]);
   1.172 +                        }
   1.173 +                    }
   1.174 +                SetPixelBlock(i,j,15,32,block.Ptr());
   1.175 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   1.176 +                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
   1.177 +
   1.178 +                //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
   1.179 +                }
   1.180 +            }
   1.181 +        }
   1.182 +
   1.183 +    }
   1.184 +
   1.185  /**
   1.186  Translate the given pixel coordinate according to our off screen mode.
   1.187  */
   1.188 @@ -365,8 +444,8 @@
   1.189  */
   1.190  void GP1212A01A::ResetBuffers()
   1.191  	{
   1.192 -	//iFrameBuffer->ClearAll();
   1.193 -	//memset(iFrameBuffer,0x00,sizeof(iFrameBuffer));
   1.194 +    //iNextFrame->ClearAll();
   1.195 +    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
   1.196  	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
   1.197  	}
   1.198