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