MiniDisplay/FutabaVfd.cpp
author sl
Fri, 30 May 2014 10:56:20 +0200
changeset 20 cd6d76b9b47e
parent 19 be04ffbb561c
child 21 434d6b8a406d
permissions -rw-r--r--
Pixel diff logic for frame rate improvment now working.
It's still working on a per pixels bases so too slow with full screen update.
Thus it's still disabled.
sl@4
     1
sl@4
     2
#include "FutabaVfd.h"
sl@4
     3
//#include <stdlib.h>
sl@4
     4
#include <string.h>
sl@4
     5
sl@4
     6
sl@4
     7
//
sl@4
     8
//
sl@4
     9
//
sl@4
    10
sl@4
    11
sl@4
    12
sl@4
    13
sl@4
    14
sl@4
    15
//
sl@4
    16
//
sl@4
    17
//
sl@4
    18
sl@4
    19
FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0)
sl@4
    20
    {
sl@4
    21
    }
sl@4
    22
sl@4
    23
FutabaVfdCommand::~FutabaVfdCommand()
sl@4
    24
    {
sl@4
    25
    //Delete();
sl@4
    26
    }
sl@4
    27
sl@4
    28
sl@4
    29
/**
sl@4
    30
sl@4
    31
*/
sl@4
    32
void FutabaVfdCommand::Reset()
sl@4
    33
    {
sl@4
    34
    memset(iReports,0,sizeof(iReports));
sl@4
    35
    }
sl@4
    36
sl@4
    37
sl@4
    38
sl@4
    39
/**
sl@4
    40
sl@4
    41
*/
sl@4
    42
/*
sl@4
    43
void FutabaVfdCommand::Create(int aMaxSize)
sl@4
    44
    {
sl@4
    45
    iBuffer=new unsigned char[aMaxSize];
sl@4
    46
    if (iBuffer)
sl@4
    47
        {
sl@4
    48
        iMaxSize = aMaxSize;
sl@4
    49
        iSize = 0;
sl@4
    50
        }
sl@4
    51
    }
sl@4
    52
*/
sl@4
    53
sl@4
    54
/**
sl@4
    55
sl@4
    56
*/
sl@4
    57
/*
sl@4
    58
void FutabaVfdCommand::Delete()
sl@4
    59
{
sl@4
    60
    delete[] iBuffer;
sl@4
    61
    iBuffer = NULL;
sl@4
    62
    iMaxSize = 0;
sl@4
    63
    iSize = 0;
sl@4
    64
}
sl@4
    65
*/
sl@4
    66
sl@4
    67
sl@4
    68
sl@4
    69
sl@4
    70
//
sl@4
    71
// class GP1212A01A
sl@4
    72
//
sl@4
    73
sl@4
    74
GP1212A01A::GP1212A01A():
sl@4
    75
	iDisplayPositionX(0),iDisplayPositionY(0),
sl@19
    76
    iOffScreenMode(true),
sl@20
    77
    iFrameNext(NULL),
sl@20
    78
    iFrameCurrent(NULL),
sl@20
    79
    iFramePrevious(NULL),
sl@19
    80
    iFrameAlpha(NULL),
sl@19
    81
    iFrameBeta(NULL),
sl@20
    82
    iFrameGamma(NULL),
sl@20
    83
    iNeedFullFrameUpdate(0),
sl@19
    84
    iRequest(ERequestNone),iPowerOn(false)
sl@4
    85
	{
sl@4
    86
	//ResetBuffers();
sl@4
    87
	}
sl@4
    88
sl@4
    89
/**
sl@4
    90
*/
sl@4
    91
GP1212A01A::~GP1212A01A()
sl@4
    92
	{
sl@19
    93
    delete iFrameAlpha;
sl@19
    94
    iFrameAlpha=NULL;
sl@19
    95
    //
sl@19
    96
    delete iFrameBeta;
sl@19
    97
    iFrameBeta=NULL;
sl@19
    98
    //
sl@20
    99
    delete iFrameGamma;
sl@20
   100
    iFrameGamma=NULL;
sl@19
   101
    //
sl@20
   102
    iFrameNext=NULL;
sl@20
   103
    iFrameCurrent=NULL;
sl@20
   104
    iFramePrevious=NULL;
sl@20
   105
    //
sl@20
   106
    iNeedFullFrameUpdate=0;
sl@4
   107
	}
sl@4
   108
sl@4
   109
/**
sl@4
   110
*/
sl@4
   111
int GP1212A01A::Open()
sl@4
   112
	{
sl@4
   113
	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
sl@4
   114
	if (success)
sl@4
   115
		{
sl@19
   116
        //Allocate both frames
sl@19
   117
        delete iFrameAlpha;
sl@19
   118
        iFrameAlpha=NULL;
sl@19
   119
        iFrameAlpha=new BitArray(KGP12xFrameBufferPixelCount);
sl@19
   120
        //
sl@19
   121
        delete iFrameBeta;
sl@19
   122
        iFrameBeta=NULL;
sl@19
   123
        iFrameBeta=new BitArray(KGP12xFrameBufferPixelCount);
sl@19
   124
        //
sl@20
   125
        delete iFrameGamma;
sl@20
   126
        iFrameGamma=NULL;
sl@20
   127
        iFrameGamma=new BitArray(KGP12xFrameBufferPixelCount);
sl@20
   128
        //
sl@20
   129
        iFrameNext=iFrameAlpha;
sl@20
   130
        iFrameCurrent=iFrameBeta;
sl@20
   131
        iFramePrevious=iFrameGamma;
sl@20
   132
sl@20
   133
sl@19
   134
        //To make sure it is synced properly
sl@20
   135
        iNeedFullFrameUpdate=0;
sl@19
   136
        //
sl@4
   137
		SetNonBlocking(1);
sl@11
   138
        //Since we can't get our display position we force it to our default
sl@4
   139
		//This makes sure frames are in sync from the start
sl@11
   140
        //Clever clients will have taken care of putting back frame (0,0) before closing
sl@4
   141
		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
sl@4
   142
		}
sl@4
   143
	return success;
sl@4
   144
	}
sl@4
   145
sl@4
   146
/**
sl@4
   147
*/
sl@4
   148
void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
sl@4
   149
	{
sl@4
   150
	//
sl@4
   151
	//int byteOffset=(aX*HeightInPixels()+aY)/8;
sl@4
   152
	//int bitOffset=(aX*HeightInPixels()+aY)%8;
sl@19
   153
    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
sl@18
   154
sl@18
   155
    if (iOffScreenMode)
sl@18
   156
        {
sl@18
   157
        if (aOn)
sl@18
   158
            {
sl@20
   159
            iFrameNext->SetBit(aX*HeightInPixels()+aY);
sl@18
   160
            }
sl@18
   161
        else
sl@18
   162
            {
sl@20
   163
            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
sl@18
   164
            }
sl@18
   165
        }
sl@18
   166
    else
sl@18
   167
        {
sl@18
   168
        //Just specify a one pixel block
sl@18
   169
        SetPixelBlock(aX,aY,0x00,0x01,aOn);
sl@18
   170
        }
sl@4
   171
	}
sl@4
   172
sl@4
   173
/**
sl@4
   174
*/
sl@6
   175
void GP1212A01A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
sl@4
   176
	{
sl@4
   177
	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
sl@4
   178
	for (int i=0;i<aSrcWidth;i++)
sl@4
   179
		{
sl@4
   180
		for (int j=0;j<aSrcHeight;j++)
sl@4
   181
			{
sl@20
   182
            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
sl@4
   183
			}
sl@4
   184
		}
sl@4
   185
	}
sl@4
   186
sl@4
   187
/**
sl@20
   188
Clear our client side back buffer.
sl@20
   189
Call to SwapBuffers must follow to actually clear the display.
sl@20
   190
*/
sl@20
   191
void GP1212A01A::Clear()
sl@20
   192
    {
sl@20
   193
    //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
sl@20
   194
    if (iOffScreenMode)
sl@20
   195
        {
sl@20
   196
        iFrameNext->ClearAll();
sl@20
   197
        }
sl@20
   198
    else
sl@20
   199
        {
sl@20
   200
        SendClearCommand();
sl@20
   201
        }
sl@20
   202
    }
sl@20
   203
sl@20
   204
/**
sl@4
   205
Set all pixels on our screen to the desired value.
sl@4
   206
This operation is performed off screen to avoid tearing.
sl@4
   207
@param 8 pixels pattern
sl@4
   208
*/
sl@4
   209
void GP1212A01A::SetAllPixels(unsigned char aPattern)
sl@4
   210
	{
sl@4
   211
	//With a single buffer
sl@4
   212
	//unsigned char screen[2048]; //One screen worth of pixels
sl@4
   213
	//memset(screen,0xFF,sizeof(screen));
sl@4
   214
	//SetPixelBlock(0,0,63,sizeof(screen),screen);
sl@4
   215
sl@18
   216
sl@18
   217
    if (iOffScreenMode)
sl@18
   218
        {
sl@20
   219
        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
sl@18
   220
        }
sl@18
   221
    else
sl@18
   222
        {
sl@18
   223
        //Using pattern SetPixelBlock variant.
sl@18
   224
        SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
sl@18
   225
        }
sl@4
   226
	//
sl@4
   227
	}
sl@4
   228
sl@4
   229
sl@4
   230
/**
sl@4
   231
Set the defined pixel block to the given value.
sl@4
   232
@param X coordinate of our pixel block starting point.
sl@4
   233
@param Y coordinate of our pixel block starting point.
sl@4
   234
@param The height of our pixel block.
sl@4
   235
@param The size of our pixel data. Number of pixels divided by 8.
sl@4
   236
@param The value set to 8 pixels used as a pattern.
sl@4
   237
*/
sl@4
   238
void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
sl@4
   239
	{
sl@4
   240
	OffScreenTranslation(aX,aY);
sl@4
   241
    FutabaVfdReport report;
sl@4
   242
    report[0]=0x00; //Report ID
sl@4
   243
    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
sl@4
   244
    report[2]=0x1B; //Command ID
sl@4
   245
    report[3]=0x5B; //Command ID
sl@4
   246
    report[4]=0xF0; //Command ID
sl@4
   247
    report[5]=aX;   //X
sl@4
   248
    report[6]=aY;   //Y
sl@4
   249
    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.
sl@4
   250
	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
sl@4
   251
	report[9]=aSize;	//Size of pixel data in bytes (LSB)
sl@4
   252
    int sizeWritten=MIN(aSize,report.Size()-10);
sl@4
   253
    memset(report.Buffer()+10, aValue, sizeWritten);
sl@4
   254
    Write(report);
sl@4
   255
sl@4
   256
    int remainingSize=aSize;
sl@4
   257
    //We need to keep on sending our pixel data until we are done
sl@4
   258
    while (report[1]==64)
sl@4
   259
        {
sl@4
   260
        report.Reset();
sl@4
   261
        remainingSize-=sizeWritten;
sl@4
   262
        report[0]=0x00; //Report ID
sl@4
   263
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@4
   264
        sizeWritten=(report[1]==64?63:report[1]);
sl@4
   265
        memset(report.Buffer()+2, aValue, sizeWritten);
sl@4
   266
        Write(report);
sl@4
   267
        }
sl@4
   268
	}
sl@4
   269
sl@4
   270
/**
sl@4
   271
Set the defined pixel block to the given value.
sl@4
   272
@param X coordinate of our pixel block starting point.
sl@4
   273
@param Y coordinate of our pixel block starting point.
sl@4
   274
@param The height of our pixel block.
sl@4
   275
@param The size of our pixel data. Number of pixels divided by 8.
sl@4
   276
@param Pointer to our pixel data.
sl@4
   277
*/
sl@4
   278
void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
sl@4
   279
    {
sl@4
   280
	OffScreenTranslation(aX,aY);
sl@4
   281
    FutabaVfdReport report;
sl@4
   282
    report[0]=0x00; //Report ID
sl@4
   283
    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
sl@4
   284
    report[2]=0x1B; //Command ID
sl@4
   285
    report[3]=0x5B; //Command ID
sl@4
   286
    report[4]=0xF0; //Command ID
sl@4
   287
    report[5]=aX;   //X
sl@4
   288
    report[6]=aY;   //Y
sl@4
   289
    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.
sl@4
   290
	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
sl@4
   291
	report[9]=aSize;	//Size of pixel data in bytes (LSB)
sl@4
   292
    int sizeWritten=MIN(aSize,report.Size()-10);
sl@4
   293
    memcpy(report.Buffer()+10, aPixels, sizeWritten);
sl@4
   294
    Write(report);
sl@4
   295
sl@4
   296
    int remainingSize=aSize;
sl@4
   297
    //We need to keep on sending our pixel data until we are done
sl@4
   298
    while (report[1]==64)
sl@4
   299
        {
sl@4
   300
        report.Reset();
sl@4
   301
        remainingSize-=sizeWritten;
sl@4
   302
        report[0]=0x00; //Report ID
sl@4
   303
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@4
   304
        sizeWritten=(report[1]==64?63:report[1]);
sl@4
   305
        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
sl@4
   306
        Write(report);
sl@4
   307
        }
sl@4
   308
    }
sl@4
   309
sl@4
   310
/**
sl@4
   311
Using this function is advised against as is causes tearing.
sl@4
   312
Use Clear instead.
sl@4
   313
*/
sl@4
   314
void GP1212A01A::SendClearCommand()
sl@4
   315
	{
sl@4
   316
    //1BH,5BH,32H,4AH
sl@4
   317
    //Send Clear Display Command
sl@4
   318
	FutabaVfdReport report;
sl@4
   319
	report[0]=0x00; //Report ID
sl@4
   320
	report[1]=0x04; //Report length
sl@4
   321
	report[2]=0x1B; //Command ID
sl@4
   322
	report[3]=0x5B; //Command ID
sl@4
   323
	report[4]=0x32; //Command ID
sl@4
   324
	report[5]=0x4A; //Command ID
sl@4
   325
	Write(report);
sl@4
   326
	}
sl@4
   327
sl@4
   328
/**
sl@4
   329
Change our display position within our buffer.
sl@4
   330
*/
sl@4
   331
void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
sl@4
   332
    {
sl@4
   333
    //1BH,5BH,Dw,Px,Py
sl@4
   334
    //Send Display Position Settings Command
sl@4
   335
    FutabaVfdReport report;
sl@4
   336
    report[0]=0x00; //Report ID
sl@4
   337
    report[1]=0x05; //Report length
sl@4
   338
    report[2]=0x1B; //Command ID
sl@4
   339
    report[3]=0x5B; //Command ID
sl@4
   340
    report[4]=aDw;  //Specify our DW
sl@4
   341
    report[5]=aX;   //X coordinate of our DW top-left corner
sl@4
   342
    report[6]=aY;   //Y coordinate of our DW top-left corner
sl@4
   343
    Write(report);
sl@4
   344
    }
sl@4
   345
sl@4
   346
/**
sl@4
   347
Change our display position within our buffer.
sl@4
   348
*/
sl@4
   349
void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
sl@4
   350
	{
sl@4
   351
	//Specs apparently says both DW should remain the same
sl@4
   352
	//Just don't ask
sl@4
   353
    SetDisplayPosition(GP1212A01A::DW1,aX,aY);
sl@4
   354
    SetDisplayPosition(GP1212A01A::DW2,aX,aY);
sl@4
   355
	iDisplayPositionX=aX;
sl@4
   356
	iDisplayPositionY=aY;
sl@4
   357
	}
sl@4
   358
sl@4
   359
/**
sl@4
   360
Provide Y coordinate of our off screen buffer.
sl@4
   361
*/
sl@4
   362
unsigned char GP1212A01A::OffScreenY() const
sl@4
   363
	{
sl@4
   364
	//Overflowing is fine this is just what we want
sl@4
   365
	return iDisplayPositionY+HeightInPixels();
sl@4
   366
	}
sl@4
   367
sl@4
   368
/**
sl@4
   369
Put our off screen buffer on screen.
sl@4
   370
On screen buffer goes off screen.
sl@4
   371
*/
sl@4
   372
void GP1212A01A::SwapBuffers()
sl@4
   373
	{
sl@4
   374
	//Only perform buffer swapping if off screen mode is enabled
sl@4
   375
	if (OffScreenMode())
sl@4
   376
		{
sl@4
   377
		//Send host back buffer to device back buffer
sl@20
   378
        if (iNeedFullFrameUpdate<3)
sl@19
   379
            {
sl@19
   380
            //TODO: enable this once SendModifiedPixelBlocks works
sl@20
   381
            //iNeedFullFrameUpdate++;
sl@20
   382
            SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),iFrameNext->Ptr());
sl@19
   383
            }
sl@19
   384
        else
sl@19
   385
            {
sl@19
   386
            SendModifiedPixelBlocks();
sl@19
   387
            }
sl@4
   388
		//Swap device front and back buffer
sl@4
   389
		SetDisplayPosition(iDisplayPositionX,OffScreenY());
sl@4
   390
		//Swap host buffers
sl@20
   391
        //BitArray* nextFrame=iFrameNext;
sl@20
   392
        //iFrameCurrent = iFramePrevious;
sl@20
   393
        //iFrameNext = iFramePrevious;
sl@20
   394
sl@20
   395
        BitArray* previousFrame=iFramePrevious;
sl@20
   396
        iFramePrevious = iFrameCurrent;
sl@20
   397
        iFrameCurrent = iFrameNext;
sl@20
   398
        iFrameNext = previousFrame;
sl@4
   399
		}
sl@4
   400
	}
sl@4
   401
sl@19
   402
sl@19
   403
/**
sl@19
   404
 * @brief GP1212A01A::SendModifiedPixelBlocks
sl@19
   405
 * Compare our back and front buffer and send to the device only the modified pixels.
sl@19
   406
 * TODO: Get this working at some point.
sl@19
   407
 */
sl@19
   408
void GP1212A01A::SendModifiedPixelBlocks()
sl@19
   409
    {
sl@19
   410
    //The largest pixel block we can sanely send with one report is 16*16
sl@19
   411
    //const int KBlocksPerRow = WidthInPixels()/16; //16
sl@19
   412
    //const int KBlocksPerColumn = HeightInPixels()/16; //4
sl@19
   413
sl@19
   414
    int w=WidthInPixels();
sl@19
   415
    int h=HeightInPixels();
sl@19
   416
sl@19
   417
    BitArray block(16*16);
sl@20
   418
sl@20
   419
sl@19
   420
    //TODO: optimize with memcmp and 16 inc
sl@20
   421
    for (int i=0;i<w;i++)
sl@20
   422
        {
sl@20
   423
        for (int j=0;j<h;j++)
sl@20
   424
            {
sl@20
   425
            //aX*HeightInPixels()+aY
sl@20
   426
            if ((*iFrameNext)[i*h+j]!=(*iFramePrevious)[i*h+j])
sl@20
   427
                {
sl@20
   428
                //We need to update that pixel
sl@20
   429
                SetPixelBlock(i,j,0,1,((*iFrameNext)[i*h+j]?0x01:0x00));
sl@20
   430
                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
sl@20
   431
                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
sl@20
   432
sl@20
   433
                //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
sl@20
   434
                }
sl@20
   435
            }
sl@20
   436
        }
sl@20
   437
sl@20
   438
    /*
sl@19
   439
    for (int i=0;i<w;i+=16)
sl@19
   440
        {
sl@19
   441
        for (int j=0;j<h;j+=16)
sl@19
   442
            {
sl@19
   443
            //aX*HeightInPixels()+aY
sl@19
   444
            int offset=(i*w/8)+(j/8);
sl@20
   445
            if (memcmp(iNextFrame->Ptr()+offset,iCurrentFrame->Ptr()+offset,32 )) //32=(16*16/8)
sl@19
   446
                {
sl@19
   447
                //We need to update that block
sl@19
   448
sl@19
   449
                for (int x=i;x<i+16;x++)
sl@19
   450
                    {
sl@19
   451
                    for (int y=i;y<j+16;y++)
sl@19
   452
                        {
sl@19
   453
                        block.SetBitValue((x-i)*h+(y-j),(*iNextFrame)[x*h+y]);
sl@19
   454
                        }
sl@19
   455
                    }
sl@19
   456
                SetPixelBlock(i,j,15,32,block.Ptr());
sl@19
   457
                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
sl@19
   458
                //SetDisplayPosition(iDisplayPositionX,OffScreenY());
sl@19
   459
sl@19
   460
                //SetPixelBlock(i,j,15,32,iNextFrame->Ptr()+offset);
sl@19
   461
                }
sl@19
   462
            }
sl@19
   463
        }
sl@20
   464
    */
sl@19
   465
sl@19
   466
    }
sl@19
   467
sl@4
   468
/**
sl@4
   469
Translate the given pixel coordinate according to our off screen mode.
sl@4
   470
*/
sl@4
   471
void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
sl@4
   472
	{
sl@4
   473
	if (OffScreenMode())
sl@4
   474
		{
sl@4
   475
		aX+=WidthInPixels()-iDisplayPositionX;
sl@4
   476
		aY+=HeightInPixels()-iDisplayPositionY;
sl@4
   477
		}
sl@4
   478
	}
sl@4
   479
sl@4
   480
sl@4
   481
/**
sl@4
   482
*/
sl@4
   483
void GP1212A01A::ResetBuffers()
sl@4
   484
	{
sl@19
   485
    //iNextFrame->ClearAll();
sl@19
   486
    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
sl@4
   487
	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
sl@4
   488
	}
sl@4
   489
sl@4
   490
/**
sl@4
   491
*/
sl@9
   492
void GP1212A01A::RequestDeviceId()
sl@4
   493
    {
sl@9
   494
    if (RequestPending())
sl@9
   495
        {
sl@9
   496
        //Abort silently for now
sl@9
   497
        return;
sl@9
   498
        }
sl@9
   499
sl@4
   500
    //1BH,5BH,63H,49H,44H
sl@4
   501
    //Send Read ID command
sl@4
   502
    FutabaVfdReport report;
sl@4
   503
    report[0]=0x00; //Report ID
sl@4
   504
    report[1]=0x05; //Report length
sl@4
   505
    report[2]=0x1B; //Command ID
sl@4
   506
    report[3]=0x5B; //Command ID
sl@4
   507
    report[4]=0x63; //Command ID
sl@4
   508
    report[5]=0x49; //Command ID
sl@4
   509
    report[6]=0x44; //Command ID
sl@9
   510
    if (Write(report)==report.Size())
sl@9
   511
        {
sl@9
   512
        iRequest=ERequestDeviceId;
sl@9
   513
        }
sl@4
   514
    }
sl@4
   515
sl@4
   516
/**
sl@4
   517
*/
sl@4
   518
void GP1212A01A::RequestFirmwareRevision()
sl@4
   519
    {
sl@9
   520
    if (RequestPending())
sl@9
   521
        {
sl@9
   522
        //Abort silently for now
sl@9
   523
        return;
sl@9
   524
        }
sl@9
   525
sl@4
   526
    //1BH,5BH,63H,46H,52H
sl@4
   527
    //Send Software Revision Read Command
sl@4
   528
    FutabaVfdReport report;
sl@4
   529
    report[0]=0x00; //Report ID
sl@4
   530
    report[1]=0x05; //Report length
sl@4
   531
    report[2]=0x1B; //Command ID
sl@4
   532
    report[3]=0x5B; //Command ID
sl@4
   533
    report[4]=0x63; //Command ID
sl@4
   534
    report[5]=0x46; //Command ID
sl@4
   535
    report[6]=0x52; //Command ID
sl@9
   536
    if (Write(report)==report.Size())
sl@9
   537
        {
sl@9
   538
        iRequest=ERequestFirmwareRevision;
sl@9
   539
        }
sl@4
   540
    }
sl@4
   541
sl@4
   542
/**
sl@4
   543
*/
sl@4
   544
void GP1212A01A::RequestPowerSupplyStatus()
sl@4
   545
    {
sl@9
   546
    if (RequestPending())
sl@9
   547
        {
sl@9
   548
        //Abort silently for now
sl@9
   549
        return;
sl@9
   550
        }
sl@4
   551
    //1BH,5BH,63H,50H,4DH
sl@4
   552
    //Send Power Suppply Monitor Command
sl@4
   553
    FutabaVfdReport report;
sl@4
   554
    report[0]=0x00; //Report ID
sl@4
   555
    report[1]=0x05; //Report length
sl@4
   556
    report[2]=0x1B; //Command ID
sl@4
   557
    report[3]=0x5B; //Command ID
sl@4
   558
    report[4]=0x63; //Command ID
sl@4
   559
    report[5]=0x50; //Command ID
sl@4
   560
    report[6]=0x4D; //Command ID
sl@9
   561
    if (Write(report)==report.Size())
sl@9
   562
        {
sl@9
   563
        iRequest=ERequestPowerSupplyStatus;
sl@9
   564
        }
sl@4
   565
    }
sl@4
   566
sl@4
   567
sl@4
   568
/**
sl@4
   569
This is for development purposes only.
sl@4
   570
Production application should stick to off-screen mode to avoid tearing.
sl@4
   571
*/
sl@4
   572
void GP1212A01A::ToggleOffScreenMode()
sl@4
   573
	{
sl@20
   574
    SetOffScreenMode(!iOffScreenMode);
sl@6
   575
	}
sl@9
   576
sl@9
   577
/**
sl@18
   578
 * @brief GP1212A01A::SetOffScreenMode
sl@18
   579
 * @param aOn
sl@18
   580
 * @return
sl@18
   581
 */
sl@18
   582
void GP1212A01A::SetOffScreenMode(bool aOn)
sl@18
   583
    {
sl@18
   584
    if (aOn==iOffScreenMode)
sl@18
   585
    {
sl@18
   586
        //Nothing to do here
sl@18
   587
        return;
sl@18
   588
    }
sl@18
   589
sl@18
   590
    iOffScreenMode=aOn;
sl@18
   591
sl@18
   592
    //Clean up our buffers upon switching modes
sl@18
   593
    SetDisplayPosition(0,0);
sl@18
   594
    Clear();
sl@18
   595
    SwapBuffers();
sl@18
   596
    Clear();
sl@18
   597
    }
sl@18
   598
sl@18
   599
/**
sl@9
   600
 */
sl@9
   601
GP1212A01A::Request GP1212A01A::AttemptRequestCompletion()
sl@9
   602
    {
sl@9
   603
    if (!RequestPending())
sl@9
   604
        {
sl@9
   605
        return ERequestNone;
sl@9
   606
        }
sl@9
   607
sl@9
   608
    int res=Read(iInputReport);
sl@9
   609
sl@9
   610
    if (!res)
sl@9
   611
        {
sl@9
   612
        return ERequestNone;
sl@9
   613
        }
sl@9
   614
sl@9
   615
    //Process our request
sl@9
   616
    if (CurrentRequest()==GP1212A01A::ERequestPowerSupplyStatus)
sl@9
   617
        {
sl@9
   618
        if (iInputReport[1]==0x4F && iInputReport[2]==0x4E)
sl@9
   619
            {
sl@9
   620
            iPowerOn = true;
sl@9
   621
            }
sl@9
   622
        else if (iInputReport[1]==0x4F && iInputReport[2]==0x46 && iInputReport[3]==0x46)
sl@9
   623
            {
sl@9
   624
            iPowerOn = false;
sl@9
   625
            }
sl@9
   626
        }
sl@9
   627
sl@9
   628
    Request completed=iRequest;
sl@9
   629
    //Our request was completed
sl@9
   630
    iRequest=ERequestNone;
sl@9
   631
sl@9
   632
    return completed;
sl@9
   633
    }
sl@18
   634
sl@18
   635
sl@18
   636
/**
sl@18
   637
Set our screen brightness.
sl@18
   638
@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
sl@18
   639
*/
sl@18
   640
void GP1212A01A::SetBrightness(int aBrightness)
sl@18
   641
    {
sl@18
   642
    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
sl@18
   643
        {
sl@18
   644
        //Brightness out of range.
sl@18
   645
        //Just ignore that request.
sl@18
   646
        return;
sl@18
   647
        }
sl@18
   648
sl@18
   649
    FutabaVfdReport report;
sl@18
   650
    report[0]=0x00; //Report ID
sl@18
   651
    report[1]=0x06; //Report size
sl@18
   652
    report[2]=0x1B; //Command ID
sl@18
   653
    report[3]=0x5C; //Command ID
sl@18
   654
    report[4]=0x3F; //Command ID
sl@18
   655
    report[5]=0x4C; //Command ID
sl@18
   656
    report[6]=0x44; //Command ID
sl@18
   657
    report[7]=0x30+aBrightness; //Brightness level
sl@18
   658
    Write(report);
sl@18
   659
    }
sl@18
   660
sl@18
   661