src/FutabaVfd.cpp
changeset 23 d4e164906a1b
parent 22 efa6ff02287c
child 25 233a997193b8
     1.1 --- a/src/FutabaVfd.cpp	Thu May 22 16:46:50 2014 +0200
     1.2 +++ b/src/FutabaVfd.cpp	Thu May 22 21:32:45 2014 +0200
     1.3 @@ -71,53 +71,50 @@
     1.4  // class GP1212A01A
     1.5  //
     1.6  
     1.7 +GP1212A01A::GP1212A01A():iDisplayPositionX(0),iDisplayPositionY(0),iOffScreenMode(true)
     1.8 +	{
     1.9 +	}
    1.10 +
    1.11  int GP1212A01A::Open()
    1.12  	{
    1.13  	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
    1.14  	if (success)
    1.15  		{
    1.16  		SetNonBlocking(1);
    1.17 +		//Since we can't get our display position we for it to our default
    1.18 +		//This makes sure frames are in sync from the start
    1.19 +		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
    1.20  		}
    1.21  	return success;
    1.22  	}
    1.23  
    1.24  /**
    1.25  */
    1.26 -void GP1212A01A::SetPixel(int aX, int aY, bool aOn)
    1.27 +void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
    1.28  	{
    1.29  	//Just specify a one pixel block
    1.30  	SetPixelBlock(aX,aY,0x00,0x01,aOn);
    1.31  	}
    1.32  
    1.33  /**
    1.34 +Set all pixels on our screen to the desired value.
    1.35 +This operation is performed off screen to avoid tearing.
    1.36 +@param 8 pixels pattern
    1.37  */
    1.38 -void GP1212A01A::SetAllPixels(bool aOn)
    1.39 +void GP1212A01A::SetAllPixels(unsigned char aPattern)
    1.40  	{
    1.41 -	//One pixel at a time
    1.42 -	/*
    1.43 -	for (int i=0;i<256;i++)
    1.44 -		{
    1.45 -		for (int j=0;j<64;j++)
    1.46 -			{
    1.47 -			SetPixel(i,j,0x01);
    1.48 -			}
    1.49 -		}
    1.50 -	*/
    1.51 +	//With a single buffer
    1.52 +	//unsigned char screen[2048]; //One screen worth of pixels
    1.53 +	//memset(screen,0xFF,sizeof(screen));
    1.54 +	//SetPixelBlock(0,0,63,sizeof(screen),screen);
    1.55  
    1.56 -	//16x16=256 pixels at a time goes much faster
    1.57 -	//TODO: use even larger blocks
    1.58 -	for (int i=0;i<256;i+=16)
    1.59 -		{
    1.60 -		for (int j=0;j<64;j+=16)
    1.61 -			{
    1.62 -			SetPixelBlock(i,j,15,32,(aOn?0xFF:0x00));
    1.63 -			//FXThread::sleep(1000000000);
    1.64 -			}
    1.65 -		}
    1.66 -
    1.67 +	//Using pattern SetPixelBlock variant.
    1.68 +	SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
    1.69  	}
    1.70  
    1.71  /**
    1.72 +Set our screen brightness.
    1.73 +@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
    1.74  */
    1.75  void GP1212A01A::SetBrightness(int aBrightness)
    1.76      {
    1.77 @@ -149,23 +146,36 @@
    1.78  @param The size of our pixel data. Number of pixels divided by 8.
    1.79  @param The value set to 8 pixels used as a pattern.
    1.80  */
    1.81 -void GP1212A01A::SetPixelBlock(int aX, int aY, int aHeight, int aSize, unsigned char aValue)
    1.82 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
    1.83  	{
    1.84 -	//Size must be 63 or below
    1.85 -	FutabaVfdReport report;
    1.86 -	report[0]=0x00; //Report ID
    1.87 -	report[1]=0x08+aSize; //Report length
    1.88 -	report[2]=0x1B; //
    1.89 -	report[3]=0x5B; //
    1.90 -	report[4]=0xF0; //
    1.91 -	report[5]=aX; //X
    1.92 -	report[6]=aY; //Y
    1.93 -	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.94 -	report[8]=0x00; //Size of pixel data in bytes (MSB)
    1.95 -	report[9]=aSize; //Size of pixel data in bytes (LSB)
    1.96 -	memset(report.Buffer()+10, aValue, aSize);
    1.97 -	//iOutputReportBuffer[10]=aValue; //Pixel data
    1.98 -	Write(report);
    1.99 +	OffScreenTranslation(aX,aY);
   1.100 +    FutabaVfdReport report;
   1.101 +    report[0]=0x00; //Report ID
   1.102 +    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.103 +    report[2]=0x1B; //Command ID
   1.104 +    report[3]=0x5B; //Command ID
   1.105 +    report[4]=0xF0; //Command ID
   1.106 +    report[5]=aX;   //X
   1.107 +    report[6]=aY;   //Y
   1.108 +    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.109 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   1.110 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   1.111 +    int sizeWritten=MIN(aSize,report.Size()-10);
   1.112 +    memset(report.Buffer()+10, aValue, sizeWritten);
   1.113 +    Write(report);
   1.114 +
   1.115 +    int remainingSize=aSize;
   1.116 +    //We need to keep on sending our pixel data until we are done
   1.117 +    while (report[1]==64)
   1.118 +        {
   1.119 +        report.Reset();
   1.120 +        remainingSize-=sizeWritten;
   1.121 +        report[0]=0x00; //Report ID
   1.122 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   1.123 +        sizeWritten=(report[1]==64?63:report[1]);
   1.124 +        memset(report.Buffer()+2, aValue, sizeWritten);
   1.125 +        Write(report);
   1.126 +        }
   1.127  	}
   1.128  
   1.129  /**
   1.130 @@ -176,19 +186,20 @@
   1.131  @param The size of our pixel data. Number of pixels divided by 8.
   1.132  @param Pointer to our pixel data.
   1.133  */
   1.134 -void GP1212A01A::SetPixelBlock(int aX, int aY, int aHeight, int aSize, unsigned char* aPixels)
   1.135 +void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
   1.136      {
   1.137 +	OffScreenTranslation(aX,aY);
   1.138      FutabaVfdReport report;
   1.139      report[0]=0x00; //Report ID
   1.140 -    report[1]=0x08+(aSize<=report.Size()-10?aSize:64); //Report length. -10 is for our header first 10 bytes
   1.141 +    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.142      report[2]=0x1B; //Command ID
   1.143      report[3]=0x5B; //Command ID
   1.144      report[4]=0xF0; //Command ID
   1.145      report[5]=aX;   //X
   1.146      report[6]=aY;   //Y
   1.147      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.148 -    unsigned short* sizePtr=(unsigned short*)report.Buffer()+8; //Size of pixel data in bytes (MSB)
   1.149 -    *sizePtr=aSize; //Put our size over 2 bytes
   1.150 +	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
   1.151 +	report[9]=aSize;	//Size of pixel data in bytes (LSB)
   1.152      int sizeWritten=MIN(aSize,report.Size()-10);
   1.153      memcpy(report.Buffer()+10, aPixels, sizeWritten);
   1.154      Write(report);
   1.155 @@ -200,7 +211,7 @@
   1.156          report.Reset();
   1.157          remainingSize-=sizeWritten;
   1.158          report[0]=0x00; //Report ID
   1.159 -        report[1]=(remainingSize<=report.Size()-2?aSize:64); //Report length, should be 64 or the remaining size
   1.160 +        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
   1.161          sizeWritten=(report[1]==64?63:report[1]);
   1.162          memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
   1.163          Write(report);
   1.164 @@ -210,9 +221,21 @@
   1.165  
   1.166  /**
   1.167  Clear our display's screen.
   1.168 +This operation is performed off screen to avoid tearing.
   1.169  */
   1.170  void GP1212A01A::Clear()
   1.171  	{
   1.172 +	//Using pattern SetPixelBlock variant.
   1.173 +	//First fill our off screen buffer with the desired values
   1.174 +	SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),(unsigned char)0x00);
   1.175 +	}
   1.176 +
   1.177 +/**
   1.178 +Using this function is advised against as is causes tearing.
   1.179 +Use Clear instead.
   1.180 +*/
   1.181 +void GP1212A01A::SendClearCommand()
   1.182 +	{
   1.183      //1BH,5BH,32H,4AH
   1.184      //Send Clear Display Command
   1.185  	FutabaVfdReport report;
   1.186 @@ -228,7 +251,7 @@
   1.187  /**
   1.188  Change our display position within our buffer.
   1.189  */
   1.190 -void GP1212A01A::SetDisplayPosition(DW aDw,int aX, int aY)
   1.191 +void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
   1.192      {
   1.193      //1BH,5BH,Dw,Px,Py
   1.194      //Send Display Position Settings Command
   1.195 @@ -246,12 +269,48 @@
   1.196  /**
   1.197  Change our display position within our buffer.
   1.198  */
   1.199 -void GP1212A01A::SetDisplayPosition(int aX, int aY)
   1.200 +void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
   1.201  	{
   1.202  	//Specs apparently says both DW should remain the same
   1.203  	//Just don't ask
   1.204      SetDisplayPosition(GP1212A01A::DW1,aX,aY);
   1.205      SetDisplayPosition(GP1212A01A::DW2,aX,aY);
   1.206 +	iDisplayPositionX=aX;
   1.207 +	iDisplayPositionY=aY;
   1.208 +	}
   1.209 +
   1.210 +/**
   1.211 +Provide Y coordinate of our off screen buffer.
   1.212 +*/
   1.213 +unsigned char GP1212A01A::OffScreenY() const
   1.214 +	{
   1.215 +	//Overflowing is fine this is just what we want
   1.216 +	return iDisplayPositionY+HeightInPixels();
   1.217 +	}
   1.218 +
   1.219 +/**
   1.220 +Put our off screen buffer on screen.
   1.221 +On screen buffer goes off screen.
   1.222 +*/
   1.223 +void GP1212A01A::SwapBuffers()
   1.224 +	{
   1.225 +	//Only perform buffer swapping if off screen mode is enabled
   1.226 +	if (OffScreenMode())
   1.227 +		{
   1.228 +		SetDisplayPosition(iDisplayPositionX,OffScreenY());
   1.229 +		}
   1.230 +	}
   1.231 +
   1.232 +/**
   1.233 +Translate the given pixel coordinate according to our off screen mode.
   1.234 +*/
   1.235 +void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
   1.236 +	{
   1.237 +	if (OffScreenMode())
   1.238 +		{
   1.239 +		aX+=WidthInPixels()-iDisplayPositionX;
   1.240 +		aY+=HeightInPixels()-iDisplayPositionY;
   1.241 +		}
   1.242  	}
   1.243  /**
   1.244  */
   1.245 @@ -302,4 +361,19 @@
   1.246      report[5]=0x50; //Command ID
   1.247      report[6]=0x4D; //Command ID
   1.248      Write(report);
   1.249 -    }
   1.250 \ No newline at end of file
   1.251 +    }
   1.252 +
   1.253 +
   1.254 +/**
   1.255 +This is for development purposes only.
   1.256 +Production application should stick to off-screen mode to avoid tearing.
   1.257 +*/
   1.258 +void GP1212A01A::ToggleOffScreenMode()
   1.259 +	{
   1.260 +	iOffScreenMode=!iOffScreenMode;
   1.261 +	//Clean up our buffers upon switching modes	
   1.262 +	SetDisplayPosition(0,0);
   1.263 +	Clear();
   1.264 +	SwapBuffers();
   1.265 +	Clear();
   1.266 +	}
   1.267 \ No newline at end of file