MiniDisplay/FutabaVfd.cpp
changeset 4 7d34342ac6e9
child 6 b1b049e28772
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/MiniDisplay/FutabaVfd.cpp	Tue May 27 19:50:28 2014 +0200
     1.3 @@ -0,0 +1,446 @@
     1.4 +
     1.5 +#include "FutabaVfd.h"
     1.6 +//#include <stdlib.h>
     1.7 +#include <string.h>
     1.8 +
     1.9 +
    1.10 +//
    1.11 +//
    1.12 +//
    1.13 +
    1.14 +
    1.15 +
    1.16 +
    1.17 +
    1.18 +//
    1.19 +//
    1.20 +//
    1.21 +
    1.22 +FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0)
    1.23 +    {
    1.24 +    }
    1.25 +
    1.26 +FutabaVfdCommand::~FutabaVfdCommand()
    1.27 +    {
    1.28 +    //Delete();
    1.29 +    }
    1.30 +
    1.31 +
    1.32 +/**
    1.33 +
    1.34 +*/
    1.35 +void FutabaVfdCommand::Reset()
    1.36 +    {
    1.37 +    memset(iReports,0,sizeof(iReports));
    1.38 +    }
    1.39 +
    1.40 +
    1.41 +
    1.42 +/**
    1.43 +
    1.44 +*/
    1.45 +/*
    1.46 +void FutabaVfdCommand::Create(int aMaxSize)
    1.47 +    {
    1.48 +    iBuffer=new unsigned char[aMaxSize];
    1.49 +    if (iBuffer)
    1.50 +        {
    1.51 +        iMaxSize = aMaxSize;
    1.52 +        iSize = 0;
    1.53 +        }
    1.54 +    }
    1.55 +*/
    1.56 +
    1.57 +/**
    1.58 +
    1.59 +*/
    1.60 +/*
    1.61 +void FutabaVfdCommand::Delete()
    1.62 +{
    1.63 +    delete[] iBuffer;
    1.64 +    iBuffer = NULL;
    1.65 +    iMaxSize = 0;
    1.66 +    iSize = 0;
    1.67 +}
    1.68 +*/
    1.69 +
    1.70 +
    1.71 +
    1.72 +
    1.73 +//
    1.74 +// class GP1212A01A
    1.75 +//
    1.76 +
    1.77 +GP1212A01A::GP1212A01A():
    1.78 +	iDisplayPositionX(0),iDisplayPositionY(0),
    1.79 +	iOffScreenMode(true),iFrameBuffer(NULL)
    1.80 +	{
    1.81 +	//ResetBuffers();
    1.82 +	}
    1.83 +
    1.84 +/**
    1.85 +*/
    1.86 +GP1212A01A::~GP1212A01A()
    1.87 +	{
    1.88 +	delete iFrameBuffer;
    1.89 +	iFrameBuffer=NULL;
    1.90 +	}
    1.91 +
    1.92 +/**
    1.93 +*/
    1.94 +int GP1212A01A::Open()
    1.95 +	{
    1.96 +	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    1.97 +	if (success)
    1.98 +		{
    1.99 +		delete iFrameBuffer;
   1.100 +		iFrameBuffer = NULL;
   1.101 +		iFrameBuffer=new BitArray(KGP12xFrameBufferPixelCount);
   1.102 +		SetNonBlocking(1);
   1.103 +		//Since we can't get our display position we for it to our default
   1.104 +		//This makes sure frames are in sync from the start
   1.105 +		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
   1.106 +		//Now clear both front and back buffer on host and device
   1.107 +		Clear();
   1.108 +		SwapBuffers();
   1.109 +		Clear();
   1.110 +		SwapBuffers();
   1.111 +		}
   1.112 +	return success;
   1.113 +	}
   1.114 +
   1.115 +/**
   1.116 +*/
   1.117 +void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
   1.118 +	{
   1.119 +	//Just specify a one pixel block
   1.120 +	//SetPixelBlock(aX,aY,0x00,0x01,aOn);
   1.121 +	//
   1.122 +	//int byteOffset=(aX*HeightInPixels()+aY)/8;
   1.123 +	//int bitOffset=(aX*HeightInPixels()+aY)%8;
   1.124 +	//iFrameBuffer[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
   1.125 +	if (aOn)
   1.126 +		{
   1.127 +		iFrameBuffer->SetBit(aX*HeightInPixels()+aY);
   1.128 +		}
   1.129 +	else
   1.130 +		{
   1.131 +		iFrameBuffer->ClearBit(aX*HeightInPixels()+aY);
   1.132 +		}
   1.133 +	}
   1.134 +
   1.135 +/**
   1.136 +*/
   1.137 +void GP1212A01A::BitBlit(BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
   1.138 +	{
   1.139 +	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
   1.140 +	for (int i=0;i<aSrcWidth;i++)
   1.141 +		{
   1.142 +		for (int j=0;j<aSrcHeight;j++)
   1.143 +			{
   1.144 +			iFrameBuffer->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
   1.145 +			}
   1.146 +		}
   1.147 +	}
   1.148 +
   1.149 +/**
   1.150 +Set all pixels on our screen to the desired value.
   1.151 +This operation is performed off screen to avoid tearing.
   1.152 +@param 8 pixels pattern
   1.153 +*/
   1.154 +void GP1212A01A::SetAllPixels(unsigned char aPattern)
   1.155 +	{
   1.156 +	//With a single buffer
   1.157 +	//unsigned char screen[2048]; //One screen worth of pixels
   1.158 +	//memset(screen,0xFF,sizeof(screen));
   1.159 +	//SetPixelBlock(0,0,63,sizeof(screen),screen);
   1.160 +
   1.161 +	//Using pattern SetPixelBlock variant.
   1.162 +	memset(iFrameBuffer->Ptr(),aPattern,FrameBufferSizeInBytes());
   1.163 +	//
   1.164 +
   1.165 +
   1.166 +	}
   1.167 +
   1.168 +/**
   1.169 +Set our screen brightness.
   1.170 +@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
   1.171 +*/
   1.172 +void GP1212A01A::SetBrightness(int aBrightness)
   1.173 +    {
   1.174 +	if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
   1.175 +        {
   1.176 +        //Brightness out of range.
   1.177 +        //Just ignore that request.
   1.178 +        return;
   1.179 +        }
   1.180 +
   1.181 +    FutabaVfdReport report;
   1.182 +    report[0]=0x00; //Report ID
   1.183 +    report[1]=0x06; //Report size
   1.184 +    report[2]=0x1B; //Command ID
   1.185 +    report[3]=0x5C; //Command ID
   1.186 +    report[4]=0x3F; //Command ID
   1.187 +    report[5]=0x4C; //Command ID
   1.188 +    report[6]=0x44; //Command ID
   1.189 +    report[7]=0x30+aBrightness; //Brightness level
   1.190 +    Write(report);
   1.191 +
   1.192 +	}
   1.193 +
   1.194 +/**
   1.195 +Set the defined pixel block to the given value.
   1.196 +@param X coordinate of our pixel block starting point.
   1.197 +@param Y coordinate of our pixel block starting point.
   1.198 +@param The height of our pixel block.
   1.199 +@param The size of our pixel data. Number of pixels divided by 8.
   1.200 +@param The value set to 8 pixels used as a pattern.
   1.201 +*/
   1.202 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
   1.203 +	{
   1.204 +	OffScreenTranslation(aX,aY);
   1.205 +    FutabaVfdReport report;
   1.206 +    report[0]=0x00; //Report ID
   1.207 +    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
   1.208 +    report[2]=0x1B; //Command ID
   1.209 +    report[3]=0x5B; //Command ID
   1.210 +    report[4]=0xF0; //Command ID
   1.211 +    report[5]=aX;   //X
   1.212 +    report[6]=aY;   //Y
   1.213 +    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.
   1.214 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   1.215 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   1.216 +    int sizeWritten=MIN(aSize,report.Size()-10);
   1.217 +    memset(report.Buffer()+10, aValue, sizeWritten);
   1.218 +    Write(report);
   1.219 +
   1.220 +    int remainingSize=aSize;
   1.221 +    //We need to keep on sending our pixel data until we are done
   1.222 +    while (report[1]==64)
   1.223 +        {
   1.224 +        report.Reset();
   1.225 +        remainingSize-=sizeWritten;
   1.226 +        report[0]=0x00; //Report ID
   1.227 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   1.228 +        sizeWritten=(report[1]==64?63:report[1]);
   1.229 +        memset(report.Buffer()+2, aValue, sizeWritten);
   1.230 +        Write(report);
   1.231 +        }
   1.232 +	}
   1.233 +
   1.234 +/**
   1.235 +Set the defined pixel block to the given value.
   1.236 +@param X coordinate of our pixel block starting point.
   1.237 +@param Y coordinate of our pixel block starting point.
   1.238 +@param The height of our pixel block.
   1.239 +@param The size of our pixel data. Number of pixels divided by 8.
   1.240 +@param Pointer to our pixel data.
   1.241 +*/
   1.242 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   1.243 +    {
   1.244 +	OffScreenTranslation(aX,aY);
   1.245 +    FutabaVfdReport report;
   1.246 +    report[0]=0x00; //Report ID
   1.247 +    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
   1.248 +    report[2]=0x1B; //Command ID
   1.249 +    report[3]=0x5B; //Command ID
   1.250 +    report[4]=0xF0; //Command ID
   1.251 +    report[5]=aX;   //X
   1.252 +    report[6]=aY;   //Y
   1.253 +    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.
   1.254 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   1.255 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   1.256 +    int sizeWritten=MIN(aSize,report.Size()-10);
   1.257 +    memcpy(report.Buffer()+10, aPixels, sizeWritten);
   1.258 +    Write(report);
   1.259 +
   1.260 +    int remainingSize=aSize;
   1.261 +    //We need to keep on sending our pixel data until we are done
   1.262 +    while (report[1]==64)
   1.263 +        {
   1.264 +        report.Reset();
   1.265 +        remainingSize-=sizeWritten;
   1.266 +        report[0]=0x00; //Report ID
   1.267 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   1.268 +        sizeWritten=(report[1]==64?63:report[1]);
   1.269 +        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   1.270 +        Write(report);
   1.271 +        }
   1.272 +    }
   1.273 +
   1.274 +
   1.275 +/**
   1.276 +Clear our client side back buffer.
   1.277 +Call to SwapBuffers must follow to actually clear the display.
   1.278 +*/
   1.279 +void GP1212A01A::Clear()
   1.280 +	{
   1.281 +	//memset(iFrameBuffer->Ptr(),0x00,FrameBufferSizeInBytes());
   1.282 +	iFrameBuffer->ClearAll();
   1.283 +	}
   1.284 +
   1.285 +/**
   1.286 +Using this function is advised against as is causes tearing.
   1.287 +Use Clear instead.
   1.288 +*/
   1.289 +void GP1212A01A::SendClearCommand()
   1.290 +	{
   1.291 +    //1BH,5BH,32H,4AH
   1.292 +    //Send Clear Display Command
   1.293 +	FutabaVfdReport report;
   1.294 +	report[0]=0x00; //Report ID
   1.295 +	report[1]=0x04; //Report length
   1.296 +	report[2]=0x1B; //Command ID
   1.297 +	report[3]=0x5B; //Command ID
   1.298 +	report[4]=0x32; //Command ID
   1.299 +	report[5]=0x4A; //Command ID
   1.300 +	Write(report);
   1.301 +	}
   1.302 +
   1.303 +/**
   1.304 +Change our display position within our buffer.
   1.305 +*/
   1.306 +void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   1.307 +    {
   1.308 +    //1BH,5BH,Dw,Px,Py
   1.309 +    //Send Display Position Settings Command
   1.310 +    FutabaVfdReport report;
   1.311 +    report[0]=0x00; //Report ID
   1.312 +    report[1]=0x05; //Report length
   1.313 +    report[2]=0x1B; //Command ID
   1.314 +    report[3]=0x5B; //Command ID
   1.315 +    report[4]=aDw;  //Specify our DW
   1.316 +    report[5]=aX;   //X coordinate of our DW top-left corner
   1.317 +    report[6]=aY;   //Y coordinate of our DW top-left corner
   1.318 +    Write(report);
   1.319 +    }
   1.320 +
   1.321 +/**
   1.322 +Change our display position within our buffer.
   1.323 +*/
   1.324 +void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   1.325 +	{
   1.326 +	//Specs apparently says both DW should remain the same
   1.327 +	//Just don't ask
   1.328 +    SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   1.329 +    SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   1.330 +	iDisplayPositionX=aX;
   1.331 +	iDisplayPositionY=aY;
   1.332 +	}
   1.333 +
   1.334 +/**
   1.335 +Provide Y coordinate of our off screen buffer.
   1.336 +*/
   1.337 +unsigned char GP1212A01A::OffScreenY() const
   1.338 +	{
   1.339 +	//Overflowing is fine this is just what we want
   1.340 +	return iDisplayPositionY+HeightInPixels();
   1.341 +	}
   1.342 +
   1.343 +/**
   1.344 +Put our off screen buffer on screen.
   1.345 +On screen buffer goes off screen.
   1.346 +*/
   1.347 +void GP1212A01A::SwapBuffers()
   1.348 +	{
   1.349 +	//Only perform buffer swapping if off screen mode is enabled
   1.350 +	if (OffScreenMode())
   1.351 +		{
   1.352 +		//Send host back buffer to device back buffer
   1.353 +		SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameBuffer->Ptr());
   1.354 +		//Swap device front and back buffer
   1.355 +		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   1.356 +		//Swap host buffers
   1.357 +		//unsigned char* backBuffer=iBackBuffer;
   1.358 +		//iBackBuffer = iFrontBuffer;
   1.359 +		//iFrontBuffer = backBuffer;
   1.360 +		}
   1.361 +	}
   1.362 +
   1.363 +/**
   1.364 +Translate the given pixel coordinate according to our off screen mode.
   1.365 +*/
   1.366 +void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   1.367 +	{
   1.368 +	if (OffScreenMode())
   1.369 +		{
   1.370 +		aX+=WidthInPixels()-iDisplayPositionX;
   1.371 +		aY+=HeightInPixels()-iDisplayPositionY;
   1.372 +		}
   1.373 +	}
   1.374 +
   1.375 +
   1.376 +/**
   1.377 +*/
   1.378 +void GP1212A01A::ResetBuffers()
   1.379 +	{
   1.380 +	//iFrameBuffer->ClearAll();
   1.381 +	//memset(iFrameBuffer,0x00,sizeof(iFrameBuffer));
   1.382 +	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
   1.383 +	}
   1.384 +
   1.385 +/**
   1.386 +*/
   1.387 +void GP1212A01A::RequestId()
   1.388 +    {
   1.389 +    //1BH,5BH,63H,49H,44H
   1.390 +    //Send Read ID command
   1.391 +    FutabaVfdReport report;
   1.392 +    report[0]=0x00; //Report ID
   1.393 +    report[1]=0x05; //Report length
   1.394 +    report[2]=0x1B; //Command ID
   1.395 +    report[3]=0x5B; //Command ID
   1.396 +    report[4]=0x63; //Command ID
   1.397 +    report[5]=0x49; //Command ID
   1.398 +    report[6]=0x44; //Command ID
   1.399 +    Write(report);
   1.400 +    }
   1.401 +
   1.402 +/**
   1.403 +*/
   1.404 +void GP1212A01A::RequestFirmwareRevision()
   1.405 +    {
   1.406 +    //1BH,5BH,63H,46H,52H
   1.407 +    //Send Software Revision Read Command
   1.408 +    FutabaVfdReport report;
   1.409 +    report[0]=0x00; //Report ID
   1.410 +    report[1]=0x05; //Report length
   1.411 +    report[2]=0x1B; //Command ID
   1.412 +    report[3]=0x5B; //Command ID
   1.413 +    report[4]=0x63; //Command ID
   1.414 +    report[5]=0x46; //Command ID
   1.415 +    report[6]=0x52; //Command ID
   1.416 +    Write(report);
   1.417 +    }
   1.418 +
   1.419 +/**
   1.420 +*/
   1.421 +void GP1212A01A::RequestPowerSupplyStatus()
   1.422 +    {
   1.423 +    //1BH,5BH,63H,50H,4DH
   1.424 +    //Send Power Suppply Monitor Command
   1.425 +    FutabaVfdReport report;
   1.426 +    report[0]=0x00; //Report ID
   1.427 +    report[1]=0x05; //Report length
   1.428 +    report[2]=0x1B; //Command ID
   1.429 +    report[3]=0x5B; //Command ID
   1.430 +    report[4]=0x63; //Command ID
   1.431 +    report[5]=0x50; //Command ID
   1.432 +    report[6]=0x4D; //Command ID
   1.433 +    Write(report);
   1.434 +    }
   1.435 +
   1.436 +
   1.437 +/**
   1.438 +This is for development purposes only.
   1.439 +Production application should stick to off-screen mode to avoid tearing.
   1.440 +*/
   1.441 +void GP1212A01A::ToggleOffScreenMode()
   1.442 +	{
   1.443 +	iOffScreenMode=!iOffScreenMode;
   1.444 +	//Clean up our buffers upon switching modes	
   1.445 +	SetDisplayPosition(0,0);
   1.446 +	Clear();
   1.447 +	SwapBuffers();
   1.448 +	Clear();
   1.449 +	}
   1.450 \ No newline at end of file