FutabaGP1212A02.cpp
author StephaneLenclud
Sat, 07 Feb 2015 13:50:11 +0100
changeset 32 2c844ef1ff4b
parent 26 f943cd500390
child 35 638eb0763e20
permissions -rw-r--r--
MDM166AA: Improved icon APIs.
sl@8
     1
//
sl@8
     2
//
sl@8
     3
//
sl@8
     4
sl@10
     5
#include "FutabaGP1212A02.h"
sl@10
     6
sl@17
     7
#include <stdio.h>
sl@17
     8
#include <time.h>
sl@10
     9
sl@15
    10
const unsigned short KMaxDataMemoryAddress = 0x4FFF;
sl@15
    11
const unsigned short KFrameSizeInBytes = 0x800;
sl@15
    12
sl@20
    13
StephaneLenclud@25
    14
static void sleep(unsigned int mseconds)
sl@20
    15
	{
sl@20
    16
    clock_t goal = mseconds + clock();
sl@20
    17
    while (goal > clock());
sl@20
    18
	}
sl@20
    19
sl@10
    20
//
sl@10
    21
// class GP1212A02A
sl@10
    22
//
sl@10
    23
sl@10
    24
GP1212A02A::GP1212A02A():
sl@10
    25
	iDisplayPositionX(0),iDisplayPositionY(0),
sl@10
    26
    iOffScreenMode(true),
sl@10
    27
    iUseFrameDifferencing(true),
sl@10
    28
    iFrameNext(NULL),
sl@10
    29
    iFrameCurrent(NULL),
sl@10
    30
    iFramePrevious(NULL),
sl@10
    31
    iFrameAlpha(NULL),
sl@10
    32
    iFrameBeta(NULL),
sl@10
    33
    iFrameGamma(NULL),
StephaneLenclud@29
    34
    iNeedFullFrameUpdate(0)
sl@10
    35
	{
sl@10
    36
	iDeviceId[0]=0;
sl@10
    37
	iFirmwareRevision[0]=0;
sl@10
    38
	//ResetBuffers();
sl@10
    39
	}
sl@10
    40
sl@10
    41
/**
sl@10
    42
*/
sl@10
    43
GP1212A02A::~GP1212A02A()
sl@10
    44
	{
sl@10
    45
    delete iFrameAlpha;
sl@10
    46
    iFrameAlpha=NULL;
sl@10
    47
    //
sl@10
    48
    delete iFrameBeta;
sl@10
    49
    iFrameBeta=NULL;
sl@10
    50
    //
sl@10
    51
    delete iFrameGamma;
sl@10
    52
    iFrameGamma=NULL;
sl@10
    53
    //
sl@10
    54
    iFrameNext=NULL;
sl@10
    55
    iFrameCurrent=NULL;
sl@10
    56
    iFramePrevious=NULL;
sl@10
    57
    //
sl@10
    58
    iNeedFullFrameUpdate=0;
sl@10
    59
	}
sl@10
    60
sl@10
    61
/**
sl@10
    62
*/
sl@10
    63
int GP1212A02A::Open()
sl@10
    64
	{
sl@10
    65
	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A02A,NULL);
sl@10
    66
	if (success)
sl@10
    67
		{
sl@10
    68
        //Allocate both frames
sl@10
    69
        delete iFrameAlpha;
sl@10
    70
        iFrameAlpha=NULL;
sl@13
    71
        iFrameAlpha=new BitArrayLow(KGP12xFrameBufferPixelCount);
sl@10
    72
        //
sl@10
    73
        delete iFrameBeta;
sl@10
    74
        iFrameBeta=NULL;
sl@13
    75
        iFrameBeta=new BitArrayLow(KGP12xFrameBufferPixelCount);
sl@10
    76
        //
sl@10
    77
        delete iFrameGamma;
sl@10
    78
        iFrameGamma=NULL;
sl@13
    79
        iFrameGamma=new BitArrayLow(KGP12xFrameBufferPixelCount);
sl@10
    80
        //
sl@10
    81
        iFrameNext=iFrameAlpha;
sl@10
    82
        iFrameCurrent=iFrameBeta;
sl@10
    83
        iFramePrevious=iFrameGamma;
sl@10
    84
sl@10
    85
sl@10
    86
        //To make sure it is synced properly
sl@10
    87
        iNeedFullFrameUpdate=0;
sl@10
    88
        //
sl@10
    89
		SetNonBlocking(1);
sl@13
    90
		//
sl@17
    91
		SendCommandClear();
sl@17
    92
		//
sl@17
    93
		SetClockSetting();
sl@14
    94
sl@17
    95
		//BMP box setup could be removed if we don't use it anymore
sl@14
    96
		//Setup BMP box
sl@14
    97
		BmpBoxSetting(EBmpBoxIdOne,0x0000,256,64);
sl@14
    98
		//Select current BMP box
sl@14
    99
		BmpBoxSelect(EBmpBoxIdOne);
sl@17
   100
		//
sl@17
   101
		iNextFrameAddress = 0x0000;
sl@14
   102
sl@20
   103
		//Beta font test
sl@21
   104
		/*
sl@21
   105
		SendCommandFontAction(EFontDelete);
sl@21
   106
sl@21
   107
		//SendCommandSelectFontSize(EFontLarge);		
sl@20
   108
		//SendCommandReset();
sl@20
   109
sl@21
   110
		
sl@21
   111
		
sl@20
   112
		unsigned char charPixels[]={	0xFF,0xFF,0xFF,0xFF,
sl@20
   113
										0x80,0x00,0x00,0x01,
sl@20
   114
										0x80,0x00,0x00,0x01,
sl@20
   115
										0x80,0x00,0x00,0x01,
sl@20
   116
										0x80,0x00,0x00,0x01,
sl@20
   117
										0x80,0x00,0x00,0x01,
sl@20
   118
										0x80,0x00,0x00,0x01,
sl@20
   119
										0x81,0xFF,0xFF,0xE1,
sl@20
   120
										0x80,0x00,0x00,0x01,
sl@20
   121
										0x80,0x00,0x00,0x01,
sl@20
   122
										0x80,0x00,0x00,0x01,
sl@20
   123
										0x80,0x00,0x00,0x01,
sl@20
   124
										0x80,0x00,0x00,0x01,
sl@20
   125
										0x80,0x00,0x00,0x01,
sl@20
   126
										0x80,0x00,0x00,0x01,
sl@20
   127
										0xFF,0xFF,0xFF,0xFF};
sl@20
   128
		
sl@20
   129
		
sl@21
   130
		//SendCommandFontAction(EFontStore);
sl@20
   131
		for (unsigned short i=0;i<16;i++)
sl@20
   132
		{
sl@21
   133
			//SendCommandFontAction(EFontDelete);
sl@21
   134
			
sl@20
   135
			SendCommandDefineCharacter(EFont16x32,0x0030+i,charPixels);
sl@20
   136
			//SendCommandFontAction(EFontStore);
sl@21
   137
			
sl@21
   138
			
sl@20
   139
			//sleep(100);
sl@20
   140
		}
sl@20
   141
		*/
sl@21
   142
		//SendCommandFontAction(EFontTransfer);
sl@20
   143
		
sl@20
   144
sl@20
   145
		//SendCommandDefineCharacter(EFont16x32,0x0031,charPixels);
sl@20
   146
		//SendCommandFontAction(EFontStore);
sl@20
   147
sl@20
   148
sl@20
   149
		//
sl@20
   150
sl@17
   151
sl@14
   152
sl@10
   153
		}
sl@10
   154
	return success;
sl@10
   155
	}
sl@10
   156
sl@10
   157
/**
sl@14
   158
 Setting the BMP box
sl@14
   159
[Code] 1BH,5CH,42H,Pn,aL,aH,Pw,Ph
sl@14
   160
[Function] Setting the BMP box. BMP box can be defined the 3 area to DW. The position of BMP 
sl@14
   161
box is set based on the address of DW. 
sl@14
   162
* To write data in BMP box, BMP box select is necessary. 
sl@14
   163
* Specifiable horizontal size is 256dot (100H) MAX. If horizontal size specify 256dot, Pw = 00H 
sl@14
   164
Pn = Number of a BMP box 
sl@14
   165
aL = Lower byte of address 
sl@14
   166
aH = Upper byte of address 
sl@14
   167
Pw = BMP box width 
sl@14
   168
Ph = BMP box height 
sl@14
   169
sl@14
   170
[Definable area]
sl@14
   171
Pn = 31H - BMP box 1
sl@14
   172
Pn = 32H - BMP box 2
sl@14
   173
Pn = 33H - BMP box 3
sl@14
   174
0000H <= aL + aH * 100 <= 07FFH 
sl@14
   175
01H <= Pw <= 00H (=100H) 
sl@14
   176
01H <= Ph <= 08H
sl@14
   177
*/
sl@14
   178
void GP1212A02A::BmpBoxSetting(TBmpBoxId aBoxId, unsigned short aAddress, int aWidth, int aHeight)
sl@14
   179
	{
sl@14
   180
	//TODO: check parameters validity
sl@14
   181
	//1BH,5CH,42H,Pn,aL,aH,Pw,Ph
sl@14
   182
	FutabaVfdReport report;
sl@14
   183
	report[0]=0x00; //Report ID
sl@14
   184
	report[1]=0x08; //Report length.
sl@14
   185
	report[2]=0x1B; //Command ID
sl@14
   186
	report[3]=0x5C; //Command ID
sl@14
   187
	report[4]=0x42; //Command ID
sl@14
   188
	report[5]=aBoxId; 
sl@14
   189
	report[6]=(unsigned char)aAddress; //aL = DM lower byte
sl@14
   190
	report[7]=aAddress>>8; //aH = DM upper byte
sl@14
   191
	report[8]=(aWidth==256?0x00:aWidth); //Pw = BMP box width 00==256
sl@14
   192
	report[9]=aHeight/8; //Ph = BMP box height.
sl@14
   193
	Write(report);
sl@14
   194
	}
sl@14
   195
sl@14
   196
/**
sl@14
   197
[Code]1BH,5CH,48H,Pn
sl@14
   198
[Function]Select of BMP box 
sl@14
   199
* Execution "BMP box select" is necessary before "Setting the Text box". 
sl@14
   200
* In case of writing by the specified dot writing, it is necessary to cancel this command. 
sl@14
   201
[Definable area]
sl@14
   202
Pn = 30H - Remove the BMP box 
sl@14
   203
Pn = 31H - BMP box 1
sl@14
   204
Pn = 32H - BMP box 2
sl@14
   205
Pn = 33H - BMP box 3
sl@14
   206
*/
sl@14
   207
void GP1212A02A::BmpBoxSelect(TBmpBoxId aBoxId)
sl@14
   208
	{
sl@14
   209
	//TODO: check parameters validity 
sl@14
   210
	FutabaVfdReport report;
sl@14
   211
	report[0]=0x00; //Report ID
sl@14
   212
	report[1]=0x04; //Report length.
sl@14
   213
	report[2]=0x1B; //Command ID
sl@14
   214
	report[3]=0x5C; //Command ID
sl@14
   215
	report[4]=0x48; //Command ID
sl@14
   216
	report[5]=aBoxId; //BMP box ID
sl@14
   217
	Write(report);
sl@14
   218
	}
sl@14
   219
sl@14
   220
sl@14
   221
/**
sl@10
   222
*/
sl@22
   223
void GP1212A02A::SetPixel(unsigned char aX, unsigned char aY, unsigned int aPixel)
sl@10
   224
	{
sl@10
   225
	//
sl@10
   226
	//int byteOffset=(aX*HeightInPixels()+aY)/8;
sl@10
   227
	//int bitOffset=(aX*HeightInPixels()+aY)%8;
sl@10
   228
    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
sl@10
   229
sl@22
   230
	//Pixel is on if any of the non-alpha component is not null
sl@22
   231
	bool on = (aPixel&0x00FFFFFF)!=0x00000000;
sl@22
   232
sl@10
   233
    if (iOffScreenMode)
sl@10
   234
        {
sl@22
   235
        if (on)
sl@10
   236
            {
sl@10
   237
            iFrameNext->SetBit(aX*HeightInPixels()+aY);
sl@10
   238
            }
sl@10
   239
        else
sl@10
   240
            {
sl@10
   241
            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
sl@10
   242
            }
sl@10
   243
        }
sl@10
   244
    else
sl@10
   245
        {
sl@10
   246
        //Just specify a one pixel block
sl@13
   247
        //TODO
sl@10
   248
        }
sl@10
   249
	}
sl@10
   250
sl@10
   251
/**
sl@10
   252
*/
sl@13
   253
/*
sl@10
   254
void GP1212A02A::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
sl@10
   255
	{
sl@10
   256
	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
sl@10
   257
	for (int i=0;i<aSrcWidth;i++)
sl@10
   258
		{
sl@10
   259
		for (int j=0;j<aSrcHeight;j++)
sl@10
   260
			{
sl@10
   261
            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
sl@10
   262
			}
sl@10
   263
		}
sl@10
   264
	}
sl@13
   265
*/
sl@10
   266
sl@10
   267
/**
sl@10
   268
Clear our client side back buffer.
sl@10
   269
Call to SwapBuffers must follow to actually clear the display.
sl@10
   270
*/
sl@10
   271
void GP1212A02A::Clear()
sl@10
   272
    {
sl@10
   273
    //memset(iNextFrame->Ptr(),0x00,FrameBufferSizeInBytes());
sl@10
   274
    if (iOffScreenMode)
sl@10
   275
        {
sl@10
   276
        iFrameNext->ClearAll();
sl@10
   277
        }
sl@10
   278
    else
sl@10
   279
        {
sl@17
   280
        SendCommandClear();
sl@10
   281
        }
sl@10
   282
    }
sl@10
   283
sl@10
   284
/**
sl@10
   285
Turn on all pixels.
sl@10
   286
Must be followed by a SwapBuffers call.
sl@10
   287
*/
sl@10
   288
void GP1212A02A::Fill()
sl@10
   289
	{
sl@10
   290
	SetAllPixels(0xFF);
sl@10
   291
	}
sl@10
   292
sl@10
   293
/**
sl@10
   294
Set all pixels on our screen to the desired value.
sl@10
   295
This operation is performed off screen to avoid tearing.
sl@10
   296
@param 8 pixels pattern
sl@10
   297
*/
sl@10
   298
void GP1212A02A::SetAllPixels(unsigned char aPattern)
sl@10
   299
	{
sl@10
   300
	//With a single buffer
sl@10
   301
	//unsigned char screen[2048]; //One screen worth of pixels
sl@10
   302
	//memset(screen,0xFF,sizeof(screen));
sl@10
   303
	//SetPixelBlock(0,0,63,sizeof(screen),screen);
sl@10
   304
sl@10
   305
sl@10
   306
    if (iOffScreenMode)
sl@10
   307
        {
sl@10
   308
        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
sl@10
   309
        }
sl@10
   310
    else
sl@10
   311
        {
sl@10
   312
        //Using pattern SetPixelBlock variant.
sl@13
   313
        //TODO
sl@10
   314
        }
sl@10
   315
	//
sl@10
   316
	}
sl@10
   317
sl@10
   318
sl@13
   319
sl@13
   320
sl@10
   321
/**
sl@14
   322
BMP data input 
sl@14
   323
[Code] 1BH,4AH,Pm,aL,aH,Ps,nL,nH,Pd...Pd
sl@14
   324
[Function] The BMP data is written in the DW(Display Window) or the Data memory. 
sl@14
   325
Pm= DW or Data memory 
sl@14
   326
aL = DW lower byte 
sl@14
   327
aH = DW upper byte 
sl@14
   328
Ps = Direction of writing 
sl@14
   329
nL = number of BMP data length lower byte 
sl@14
   330
nH = number of BMP data length upper byte 
sl@14
   331
Pd = BMP data 
sl@14
   332
* If X direction is selected as Ps and data is written in the last address, the data in the last address is 
sl@14
   333
overwritten with the remaining data.  
sl@14
   334
[Definable area] Pm = 30H : DW
sl@14
   335
 Pm = 31H: Data memory 
sl@14
   336
0000H <= aL + aH * 100 <= 07FFH (DW)
sl@14
   337
0000H <= aL + aH * 100 <= 4FFFH (Data memory) 
sl@14
   338
Ps = 30H: Y direction 
sl@14
   339
Ps = 31H: X direction 
sl@14
   340
0001H <= nL + nH * 100 <= 0100H(DW: X direction) 
sl@14
   341
0001H <= nL + nH * 100 <= 0800H(DW: Y direction) 
sl@14
   342
0001H <= nL + nH * 100 <= 0A00H(Data memory: X direction) 
sl@14
   343
0001H <= nL + nH * 100 <= 5000H(Data memory: Y direction) 
sl@10
   344
*/
sl@14
   345
void GP1212A02A::BmpDataInput(TTarget aTarget, unsigned short aAddress, TDirection aDirection, unsigned short aSize, unsigned char* aPixels)
sl@13
   346
{
sl@13
   347
	FutabaVfdReport report;
sl@10
   348
    report[0]=0x00; //Report ID
sl@10
   349
    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@10
   350
    report[2]=0x1B; //Command ID
sl@13
   351
    report[3]=0x4A; //Command ID
sl@14
   352
    report[4]=aTarget; //Display Window or Data Memory
sl@14
   353
    report[5]=(unsigned char)aAddress; //aL = DW lower byte
sl@14
   354
    report[6]=aAddress>>8; //aH = DW upper byte
sl@14
   355
    report[7]=aDirection; //Direction of writing: Y or X
sl@14
   356
	report[8]=(unsigned char)aSize; //Size of pixel data in bytes (LSB)
sl@13
   357
	report[9]=aSize>>8;	//Size of pixel data in bytes (MSB)
sl@10
   358
    int sizeWritten=MIN(aSize,report.Size()-10);
sl@10
   359
    memcpy(report.Buffer()+10, aPixels, sizeWritten);
sl@10
   360
    Write(report);
sl@10
   361
sl@10
   362
    int remainingSize=aSize;
sl@10
   363
    //We need to keep on sending our pixel data until we are done
sl@10
   364
    while (report[1]==64)
sl@10
   365
        {
sl@10
   366
        report.Reset();
sl@10
   367
        remainingSize-=sizeWritten;
sl@10
   368
        report[0]=0x00; //Report ID
sl@10
   369
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@10
   370
        sizeWritten=(report[1]==64?63:report[1]);
sl@10
   371
        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
sl@10
   372
        Write(report);
sl@10
   373
        }
sl@13
   374
}
sl@10
   375
sl@14
   376
sl@14
   377
/**
sl@14
   378
Data memory transfer
sl@14
   379
[Code] 1BH,5CH,44H,aL,aH
sl@14
   380
[Function] BMP data transfer from Data memory to DW. 
sl@14
   381
Although source data is updated, data in BMP box is not updated. To reflect the update, 
sl@14
   382
re-executing this command is necessary. 
sl@14
   383
aL = Lower byte of address 
sl@14
   384
aH = Upper byte of address 
sl@14
   385
[Definable area]
sl@14
   386
0000H <= aL + aH * 100 <= 4FFFH 
sl@14
   387
*/
sl@14
   388
void GP1212A02A::BmpBoxDataMemoryTransfer(unsigned short aAddress)
sl@14
   389
	{
sl@14
   390
	FutabaVfdReport report;
sl@14
   391
	report[0]=0x00; //Report ID
sl@14
   392
    report[1]=0x05; //Report length.
sl@14
   393
    report[2]=0x1B; //Command ID
sl@14
   394
    report[3]=0x5C; //Command ID
sl@14
   395
    report[4]=0x44; //Command ID
sl@14
   396
    report[5]=(unsigned char)aAddress; //aL = DM lower byte
sl@14
   397
    report[6]=aAddress>>8; //aH = DM upper byte
sl@14
   398
	Write(report);
sl@14
   399
	}
sl@14
   400
sl@14
   401
/**
sl@14
   402
Input BMP data in the BMP box 
sl@14
   403
[Code] 1BH,5CH,5DH,nL,nH,Pd...Pd
sl@14
   404
[Function] BMP data is written the BMP box 
sl@14
   405
* Number of definable data is due to BMP box size. If the data is over range, the over range data is 
sl@14
   406
rewritten the final address. 
sl@14
   407
nL = Lower byte of number of definition byte 
sl@14
   408
nH = Upper byte of number of definition byte 
sl@14
   409
Pd = BMP data 
sl@14
   410
[Definable area] Pn : BMP box size (Pw * Ph)
sl@14
   411
*/
sl@14
   412
void GP1212A02A::BmpBoxDataInput(unsigned short aSize, unsigned char* aPixels)
sl@14
   413
	{
sl@14
   414
	FutabaVfdReport report;
sl@14
   415
    report[0]=0x00; //Report ID
sl@14
   416
    report[1]=(aSize<=report.Size()-7?aSize+0x05:64); //Report length. -7 is for our header first 10 bytes. +5 is for our Futaba header size
sl@14
   417
    report[2]=0x1B; //Command ID
sl@14
   418
    report[3]=0x5C; //Command ID
sl@14
   419
    report[4]=0x5D; //Display Window or Data Memory
sl@14
   420
	report[5]=(unsigned char)aSize; //Size of pixel data in bytes (LSB)
sl@14
   421
	report[6]=aSize>>8;	//Size of pixel data in bytes (MSB)
sl@14
   422
    int sizeWritten=MIN(aSize,report.Size()-7);
sl@14
   423
    memcpy(report.Buffer()+7, aPixels, sizeWritten);
sl@14
   424
    Write(report);
sl@14
   425
sl@14
   426
    int remainingSize=aSize;
sl@14
   427
    //We need to keep on sending our pixel data until we are done
sl@14
   428
    while (report[1]==64)
sl@14
   429
        {
sl@14
   430
        report.Reset();
sl@14
   431
        remainingSize-=sizeWritten;
sl@14
   432
        report[0]=0x00; //Report ID
sl@14
   433
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@14
   434
        sizeWritten=(report[1]==64?63:report[1]);
sl@14
   435
        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
sl@14
   436
        Write(report);
sl@14
   437
        }
sl@14
   438
	}
sl@14
   439
sl@10
   440
/**
sl@10
   441
Using this function is advised against as is causes tearing.
sl@10
   442
Use Clear instead.
sl@10
   443
*/
sl@17
   444
void GP1212A02A::SendCommandClear()
sl@10
   445
	{
sl@13
   446
    //1BH,4AH,43H,44H
sl@10
   447
    //Send Clear Display Command
sl@10
   448
	FutabaVfdReport report;
sl@10
   449
	report[0]=0x00; //Report ID
sl@10
   450
	report[1]=0x04; //Report length
sl@10
   451
	report[2]=0x1B; //Command ID
sl@13
   452
	report[3]=0x4A; //Command ID
sl@13
   453
	report[4]=0x43; //Command ID
sl@13
   454
	report[5]=0x44; //Command ID
sl@10
   455
	Write(report);
sl@10
   456
	}
sl@10
   457
sl@10
   458
sl@10
   459
/**
sl@20
   460
Returns to default setting. 
sl@20
   461
* The other command is not receive until this command complete. Please don’t send the any data 
sl@20
   462
from a host during “BUSY” 
sl@20
   463
* Delete the User definable font to the RAM. 
sl@20
   464
* If the VFD Power Off, VFD Power turn ON after the RESET command.
sl@20
   465
*/
sl@20
   466
void GP1212A02A::SendCommandReset()
sl@20
   467
	{
sl@20
   468
    //1BH,4AH,43H,44H
sl@20
   469
    //Send Clear Display Command
sl@20
   470
	FutabaVfdReport report;
sl@20
   471
	report[0]=0x00; //Report ID
sl@20
   472
	report[1]=0x04; //Report length
sl@20
   473
	report[2]=0x1B; //Command ID
sl@20
   474
	report[3]=0x4A; //Command ID
sl@20
   475
	report[4]=0x52; //Command ID
sl@20
   476
	report[5]=0x53; //Command ID
sl@20
   477
	Write(report);
sl@20
   478
	//Wait until reset is done. Is that needed?
sl@20
   479
	sleep(2000);
sl@20
   480
sl@20
   481
	}
sl@20
   482
sl@20
   483
sl@20
   484
/**
sl@10
   485
Provide Y coordinate of our off screen buffer.
sl@10
   486
*/
sl@10
   487
unsigned char GP1212A02A::OffScreenY() const
sl@10
   488
	{
sl@10
   489
	//Overflowing is fine this is just what we want
sl@10
   490
	return iDisplayPositionY+HeightInPixels();
sl@10
   491
	}
sl@10
   492
sl@10
   493
/**
sl@10
   494
Put our off screen buffer on screen.
sl@10
   495
On screen buffer goes off screen.
sl@10
   496
*/
sl@10
   497
void GP1212A02A::SwapBuffers()
sl@10
   498
	{
sl@10
   499
	//Only perform buffer swapping if off screen mode is enabled
sl@10
   500
	if (OffScreenMode())
sl@10
   501
		{
sl@14
   502
		//Send pixel directly into BMP box
sl@15
   503
		//BmpBoxDataInput(FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@23
   504
		
StephaneLenclud@23
   505
		//This appears to be the fastest scheme when running on our HTPC
sl@14
   506
		//Send pixel data directly into the display window
StephaneLenclud@23
   507
		BmpDataInput(ETargetDisplayWindow,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@23
   508
		
sl@14
   509
		//Send pixel data first to Data Memory then copy into the selected BMP box	
sl@14
   510
		//BmpDataInput(ETargetDataMemory,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
sl@14
   511
		//BmpBoxDataMemoryTransfer(0x0000);
StephaneLenclud@23
   512
		
StephaneLenclud@23
   513
		//Send pixel data first to Data Memory then copy into the selected BMP box, cycling through our Data Memory frame
StephaneLenclud@23
   514
#if 0
sl@15
   515
		BmpDataInput(ETargetDataMemory,iNextFrameAddress,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
sl@15
   516
		BmpBoxDataMemoryTransfer(iNextFrameAddress);
sl@15
   517
		iNextFrameAddress+=KFrameSizeInBytes;
sl@15
   518
		if (iNextFrameAddress>KMaxDataMemoryAddress)
sl@15
   519
		{
sl@15
   520
			iNextFrameAddress=0x0000;
sl@15
   521
		}
StephaneLenclud@23
   522
#endif
sl@10
   523
sl@10
   524
        //Cycle through our frame buffers
sl@10
   525
        //We keep track of previous frame which is in fact our device back buffer.
sl@10
   526
        //We can then compare previous and next frame and send only the differences to our device.
sl@10
   527
        //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
sl@10
   528
        //Keep our previous frame pointer
sl@13
   529
        BitArrayLow* previousFrame=iFramePrevious;
sl@10
   530
        //Current frame becomes the previous one
sl@10
   531
        iFramePrevious = iFrameCurrent;
sl@10
   532
        //Next frame becomes the current one
sl@10
   533
        iFrameCurrent = iFrameNext;
sl@10
   534
        //Next frame is now our former previous
sl@10
   535
        iFrameNext = previousFrame;
sl@10
   536
		}
sl@10
   537
	}
sl@10
   538
sl@10
   539
sl@10
   540
//Define the edge of our pixel block
sl@10
   541
//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
sl@10
   542
//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
sl@10
   543
const int KPixelBlockEdge = 32;
sl@10
   544
const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
sl@10
   545
const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
sl@10
   546
sl@10
   547
sl@10
   548
/**
sl@10
   549
Translate the given pixel coordinate according to our off screen mode.
sl@10
   550
*/
sl@10
   551
void GP1212A02A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
sl@10
   552
	{
sl@10
   553
	if (OffScreenMode())
sl@10
   554
		{
sl@10
   555
		aX+=WidthInPixels()-iDisplayPositionX;
sl@10
   556
		aY+=HeightInPixels()-iDisplayPositionY;
sl@10
   557
		}
sl@10
   558
	}
sl@10
   559
sl@10
   560
sl@10
   561
/**
sl@10
   562
*/
sl@15
   563
void GP1212A02A::Request(TMiniDisplayRequest aRequest)
sl@15
   564
	{
sl@15
   565
	switch (aRequest)
sl@15
   566
		{
sl@15
   567
	case EMiniDisplayRequestDeviceId:
sl@15
   568
		RequestDeviceId();
sl@15
   569
		break;
sl@15
   570
	case EMiniDisplayRequestFirmwareRevision:
sl@15
   571
		RequestFirmwareRevision();
sl@15
   572
		break;
sl@15
   573
	case EMiniDisplayRequestPowerSupplyStatus:
sl@15
   574
		RequestPowerSupplyStatus();
sl@15
   575
		break;
sl@15
   576
	default:
sl@15
   577
		//Not supported
sl@15
   578
		break;
sl@15
   579
		};
sl@15
   580
	}
sl@15
   581
sl@15
   582
sl@15
   583
/**
sl@15
   584
*/
sl@10
   585
void GP1212A02A::ResetBuffers()
sl@10
   586
	{
sl@10
   587
    //iNextFrame->ClearAll();
sl@10
   588
    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
sl@10
   589
	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
sl@10
   590
	}
sl@10
   591
sl@10
   592
/**
sl@10
   593
*/
sl@10
   594
void GP1212A02A::RequestDeviceId()
sl@10
   595
    {
sl@11
   596
	//Not supported
sl@10
   597
    }
sl@10
   598
sl@10
   599
/**
sl@15
   600
ID code 
sl@15
   601
[Code] 1BH,6AH,49H,44H
sl@15
   602
[Function] Send the ID code to the Host system. ID code is software version.
sl@10
   603
*/
sl@10
   604
void GP1212A02A::RequestFirmwareRevision()
sl@10
   605
    {
sl@15
   606
    if (RequestPending())
sl@15
   607
        {
sl@15
   608
        //Abort silently for now
sl@15
   609
        return;
sl@15
   610
        }
sl@15
   611
sl@15
   612
    //1BH,6AH,49H,44H
sl@15
   613
    //Send Software Revision Read Command
sl@15
   614
    FutabaVfdReport report;
sl@15
   615
    report[0]=0x00; //Report ID
sl@15
   616
    report[1]=0x04; //Report length
sl@15
   617
    report[2]=0x1B; //Command ID
sl@15
   618
    report[3]=0x6A; //Command ID
sl@15
   619
    report[4]=0x49; //Command ID
sl@15
   620
    report[5]=0x44; //Command ID
sl@15
   621
    if (Write(report)==report.Size())
sl@15
   622
        {
sl@15
   623
        SetRequest(EMiniDisplayRequestFirmwareRevision);
sl@15
   624
        }
sl@15
   625
sl@10
   626
    }
sl@10
   627
sl@10
   628
/**
sl@10
   629
*/
sl@10
   630
void GP1212A02A::RequestPowerSupplyStatus()
sl@10
   631
    {
sl@11
   632
	//Not supported
sl@10
   633
    }
sl@10
   634
sl@10
   635
sl@10
   636
/**
sl@10
   637
This is for development purposes only.
sl@10
   638
Production application should stick to off-screen mode to avoid tearing.
sl@10
   639
*/
sl@10
   640
void GP1212A02A::ToggleOffScreenMode()
sl@10
   641
	{
sl@10
   642
    SetOffScreenMode(!iOffScreenMode);
sl@10
   643
	}
sl@10
   644
sl@10
   645
/**
sl@10
   646
 * @brief GP1212A02A::SetOffScreenMode
sl@10
   647
 * @param aOn
sl@10
   648
 * @return
sl@10
   649
 */
sl@10
   650
void GP1212A02A::SetOffScreenMode(bool aOn)
sl@10
   651
    {
sl@10
   652
    if (aOn==iOffScreenMode)
sl@10
   653
    {
sl@10
   654
        //Nothing to do here
sl@10
   655
        return;
sl@10
   656
    }
sl@10
   657
sl@10
   658
    iOffScreenMode=aOn;
sl@10
   659
sl@10
   660
    //Clean up our buffers upon switching modes
sl@10
   661
    Clear();
sl@10
   662
    SwapBuffers();
sl@10
   663
    Clear();
sl@10
   664
    }
sl@10
   665
sl@10
   666
/**
sl@10
   667
Tries to complete our current request if we have one pending.
sl@10
   668
 */
sl@10
   669
TMiniDisplayRequest GP1212A02A::AttemptRequestCompletion()
sl@10
   670
    {
sl@15
   671
    if (!RequestPending())
sl@15
   672
        {
sl@15
   673
        return EMiniDisplayRequestNone;
sl@15
   674
        }
sl@15
   675
sl@15
   676
    int res=Read(iInputReport);
sl@15
   677
sl@15
   678
    if (!res)
sl@15
   679
        {
sl@15
   680
        return EMiniDisplayRequestNone;
sl@15
   681
        }
sl@15
   682
sl@15
   683
    //Process our request
sl@15
   684
	if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision)
sl@15
   685
		{
sl@15
   686
			unsigned char* ptr=&iInputReport[2];
sl@15
   687
			iInputReport[7]=0x00;
sl@15
   688
			strcpy(iFirmwareRevision,(const char*)ptr);
sl@15
   689
		}
sl@15
   690
sl@15
   691
    TMiniDisplayRequest completed=CurrentRequest();
sl@15
   692
    //Our request was completed
sl@15
   693
    SetRequest(EMiniDisplayRequestNone);
sl@15
   694
sl@15
   695
    return completed;
sl@11
   696
	}
sl@10
   697
sl@10
   698
sl@10
   699
/**
sl@10
   700
Set our screen brightness.
sl@10
   701
@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
sl@10
   702
*/
sl@10
   703
void GP1212A02A::SetBrightness(int aBrightness)
sl@10
   704
    {
sl@10
   705
    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
sl@10
   706
        {
sl@10
   707
        //Brightness out of range.
sl@10
   708
        //Just ignore that request.
sl@10
   709
        return;
sl@10
   710
        }
sl@10
   711
sl@10
   712
    FutabaVfdReport report;
sl@10
   713
    report[0]=0x00; //Report ID
sl@10
   714
    report[1]=0x04; //Report size
sl@10
   715
    report[2]=0x1B; //Command ID
sl@10
   716
    report[3]=0x4A; //Command ID
sl@10
   717
    report[4]=0x44; //Command ID
sl@13
   718
    report[5]=0x30+aBrightness; //Brightness level
sl@10
   719
    Write(report);
sl@10
   720
    }
sl@10
   721
sl@10
   722
/**
sl@16
   723
VFD Power ON/OFF 
sl@16
   724
[Code]1BH,4AH,42H,Ps
sl@16
   725
[Function]Control of the power supply for VFD 
sl@16
   726
* If VFD power ON or OFF, at interval of 10s or more. 
sl@16
   727
* When the VFD power off, VFD display is turn off, but the module can receive a data and 
sl@16
   728
process.
sl@16
   729
Ps = VFD Power control 
sl@16
   730
[Definable area]
sl@16
   731
Ps = 30H : VFD Power OFF 
sl@16
   732
Ps = 31H : VFD Power ON  (Default)
sl@16
   733
*/
sl@16
   734
void GP1212A02A::SendCommandPower(TPowerStatus aPowerStatus)
sl@16
   735
	{
sl@16
   736
	FutabaVfdReport report;
sl@16
   737
    report[0]=0x00; //Report ID
sl@16
   738
    report[1]=0x04; //Report size
sl@16
   739
    report[2]=0x1B; //Command ID
sl@16
   740
    report[3]=0x4A; //Command ID
sl@16
   741
    report[4]=0x42; //Command ID
sl@16
   742
    report[5]=aPowerStatus; //ON or OFF
sl@16
   743
    Write(report);
sl@16
   744
	}
sl@16
   745
sl@16
   746
/**
sl@16
   747
*/
sl@16
   748
void GP1212A02A::TurnPowerOn()
sl@16
   749
	{
sl@16
   750
	SendCommandPower(EPowerOn);
sl@17
   751
	SetClockSetting();
sl@16
   752
	}
sl@16
   753
sl@16
   754
/**
sl@16
   755
*/
sl@16
   756
void GP1212A02A::TurnPowerOff()
sl@16
   757
	{
sl@16
   758
	SendCommandPower(EPowerOff);
sl@16
   759
	}
sl@17
   760
sl@17
   761
sl@17
   762
/**
sl@20
   763
Provide the length of our character string for the given clock format.
sl@20
   764
@param The clock format to evaluate.
sl@20
   765
@return Number of characters for the given clock format.
sl@17
   766
*/
sl@17
   767
int GP1212A02A::ClockCharCount(TClockFormat aFormat)
sl@17
   768
	{
sl@17
   769
	switch (aFormat)
sl@17
   770
		{
sl@17
   771
	case EClockDay12:
sl@19
   772
		return 13;
sl@17
   773
	case EClockDay24:
sl@17
   774
		return 10;
sl@17
   775
	case EClock12:
sl@19
   776
		return 8;
sl@17
   777
	case EClock24:
sl@17
   778
		return 5;
sl@17
   779
		}
sl@17
   780
sl@17
   781
	return 10;
sl@17
   782
	}
sl@17
   783
sl@17
   784
/**
sl@20
   785
@return Clock character width in pixels.
sl@17
   786
*/
sl@21
   787
int GP1212A02A::ClockCharWidthInPixels(TFontSizeLogical aSize)
sl@17
   788
	{
sl@17
   789
	switch (aSize)
sl@17
   790
		{
sl@21
   791
	case EFontTiny:
sl@17
   792
		return 6;
sl@21
   793
	case EFontSmall:
sl@17
   794
		return 8;
sl@21
   795
	case EFontMedium:
sl@17
   796
		return 12;
sl@21
   797
	case EFontLarge:
sl@17
   798
		return 16;
sl@17
   799
		}
sl@17
   800
sl@17
   801
	return 16;
sl@17
   802
	}
sl@17
   803
sl@17
   804
/**
sl@20
   805
@return Clock character height in pixels.
sl@17
   806
*/
sl@21
   807
int GP1212A02A::ClockCharHeightInPixels(TFontSizeLogical aSize)
sl@17
   808
	{
sl@17
   809
	switch (aSize)
sl@17
   810
		{
sl@21
   811
	case EFontTiny:
sl@17
   812
		return 8;
sl@21
   813
	case EFontSmall:
sl@17
   814
		return 16;
sl@21
   815
	case EFontMedium:
sl@17
   816
		return 24;
sl@21
   817
	case EFontLarge:
sl@17
   818
		return 32;
sl@17
   819
		}
sl@17
   820
sl@17
   821
	return 32;
sl@17
   822
	}
sl@17
   823
sl@17
   824
/**
sl@17
   825
Return the Display Window address for centering the clock corresponding to the given parameters.
sl@17
   826
*/
sl@21
   827
unsigned short GP1212A02A::ClockCenterAddress(TClockFormat aFormat, TFontSizeLogical aSize)
sl@17
   828
	{
sl@17
   829
		int charCount=ClockCharCount(aFormat);
sl@17
   830
		int halfWidth=(ClockCharWidthInPixels(aSize)*charCount)/2;
sl@17
   831
		int halfHeight=(ClockCharHeightInPixels(aSize))/2;
sl@17
   832
		int x=(WidthInPixels()/2)-halfWidth;
sl@17
   833
		int y=(HeightInPixels()/2)-halfHeight;
sl@17
   834
sl@17
   835
		int yOffset=y/8;
sl@17
   836
		int xOffset=x*8; //Not sure why...
sl@17
   837
sl@17
   838
		unsigned short address = yOffset+xOffset;
sl@17
   839
		//
sl@17
   840
		return address;
sl@17
   841
	}
sl@17
   842
sl@17
   843
/**
sl@17
   844
*/
sl@17
   845
void GP1212A02A::ShowClock()
sl@17
   846
	{
sl@21
   847
	SendCommandClockDisplay(EClock24,ClockCenterAddress(EClock24,EFontLarge),EFontLarge);
sl@17
   848
	}
sl@17
   849
sl@17
   850
/**
sl@17
   851
*/
sl@17
   852
void GP1212A02A::HideClock()
sl@17
   853
	{
sl@17
   854
	SendCommandClockCancel();
sl@17
   855
	}
sl@17
   856
sl@17
   857
sl@17
   858
/**
sl@17
   859
Clock setting 
sl@17
   860
[Code]1BH,6BH,53H,Pd,Ph,Pm 
sl@17
   861
[Function]Setting the clock data. The setting data is cleared, if the Reset command is input or power 
sl@17
   862
is turned off. 
sl@17
   863
Pd = Day of the week 
sl@17
   864
Ph = hour 
sl@17
   865
Pm = minute 
sl@17
   866
[Definable area]
sl@17
   867
Pd = 00H : Sunday 
sl@17
   868
Pd = 01H : Monday 
sl@17
   869
...
sl@17
   870
Pd = 06H : Saturday 
sl@17
   871
* Clock setting is canceled, when Pd is input value that is larger than 07H, or Ph is input value that is 
sl@17
   872
larger than 18H,or Pm is input value that is larger than 3CH. 
sl@17
   873
*/
sl@17
   874
void GP1212A02A::SendCommandClockSetting(TWeekDay aWeekDay, unsigned char aHour, unsigned char aMinute)
sl@17
   875
	{
sl@17
   876
	FutabaVfdReport report;
sl@17
   877
    report[0]=0x00; //Report ID
sl@17
   878
    report[1]=0x06; //Report size
sl@17
   879
    report[2]=0x1B; //Command ID
sl@17
   880
    report[3]=0x6B; //Command ID
sl@17
   881
    report[4]=0x53; //Command ID
sl@17
   882
    report[5]=aWeekDay; //Sunday to Saturday
sl@17
   883
	report[6]=aHour;
sl@17
   884
	report[7]=aMinute;
sl@17
   885
sl@17
   886
    Write(report);
sl@17
   887
	}
sl@17
   888
sl@17
   889
sl@17
   890
/**
sl@17
   891
Set display clock settings according to local system time.
sl@17
   892
This needs to be redone whenever we open or turn on our display.
sl@17
   893
*/
sl@17
   894
void GP1212A02A::SetClockSetting()
sl@17
   895
	{
sl@17
   896
	time_t rawtime;
sl@17
   897
	struct tm * timeinfo;
sl@17
   898
sl@17
   899
	time ( &rawtime );
sl@17
   900
	timeinfo = localtime ( &rawtime );
sl@17
   901
	//
sl@17
   902
	SendCommandClockSetting((TWeekDay)timeinfo->tm_wday,timeinfo->tm_hour,timeinfo->tm_min);
sl@17
   903
	}
sl@17
   904
sl@17
   905
sl@17
   906
/**
sl@17
   907
Clock display
sl@17
   908
[Code] 1BH,6BH,55H,Ps,aL,aH,Pf
sl@17
   909
[Function] Clock is displayed. The display position and the font size can be freely decided. 
sl@17
   910
Ps = Display type select 
sl@17
   911
aL,aH = Address 
sl@17
   912
Pf = Font size select 
sl@17
   913
[Definable area]
sl@17
   914
Ps = 00H : 24hour Ex.[12:34] 
sl@17
   915
Ps = 01H : 24hour + day of the week  Ex.[Wed._12:34] 
sl@17
   916
Ps = 10H : 12hour Ex.[PM_00:34] 
sl@17
   917
Ps = 11H : 12hour + day of the week  Ex.[Wed._PM_00:34] 
sl@17
   918
Pf = 30H : 6x8 dot 
sl@17
   919
Pf = 31H : 8x16dot
sl@17
   920
Pf = 32H : 12x24 dot 
sl@17
   921
Pf = 33H : 16x32 dot 
sl@17
   922
* When the clock data is not input, clock is not displayed. 
sl@17
   923
* The clock display is maintained until Clock display cancel "Clear display" RESET command is input 
sl@17
   924
or power is turned off. 
sl@17
   925
The clock display area
sl@17
   926
Graphic can be displayed excluding the clock display area.
sl@17
   927
The self adjustment for the position 
sl@17
   928
that cannot be displayed. 
sl@17
   929
* Excluding the clock display area can be input other display commands.
sl@17
   930
*/
sl@21
   931
void GP1212A02A::SendCommandClockDisplay(TClockFormat aClockFormat, unsigned short aAddress, TFontSizeLogical aSize)
sl@17
   932
	{
sl@17
   933
	FutabaVfdReport report;
sl@17
   934
    report[0]=0x00; //Report ID
sl@17
   935
    report[1]=0x07; //Report size
sl@17
   936
    report[2]=0x1B; //Command ID
sl@17
   937
    report[3]=0x6B; //Command ID
sl@17
   938
    report[4]=0x55; //Command ID
sl@17
   939
    report[5]=aClockFormat; //
sl@17
   940
	report[6]=(unsigned char)aAddress;	//aL
sl@17
   941
	report[7]=aAddress>>8;				//aH
sl@17
   942
	report[8]=aSize;
sl@17
   943
sl@17
   944
    Write(report);
sl@17
   945
	}
sl@17
   946
sl@17
   947
sl@17
   948
/**
sl@17
   949
 Clock display cancel 
sl@17
   950
[Code] 1BH,6BH,3DH,58H
sl@17
   951
[Function] Clock display is canceled.
sl@17
   952
*/
sl@17
   953
void GP1212A02A::SendCommandClockCancel()
sl@17
   954
	{
sl@17
   955
	FutabaVfdReport report;
sl@17
   956
    report[0]=0x00; //Report ID
sl@17
   957
    report[1]=0x04; //Report size
sl@17
   958
    report[2]=0x1B; //Command ID
sl@17
   959
    report[3]=0x6B; //Command ID
sl@17
   960
    report[4]=0x3D; //Command ID
sl@17
   961
    report[5]=0x58; //
sl@17
   962
sl@17
   963
    Write(report);
sl@17
   964
	}
sl@20
   965
sl@20
   966
sl@20
   967
/**
sl@20
   968
@return Size in bytes of a character for a given font size.
sl@20
   969
*/
sl@20
   970
int GP1212A02A::CharacterSizeInBytes(TFontSize aFontSize)
sl@20
   971
	{
sl@20
   972
	switch (aFontSize)
sl@20
   973
		{
sl@20
   974
	case EFont6x8:
sl@20
   975
		return 6;
sl@20
   976
	case EFont8x16:
sl@20
   977
		return 16;
sl@20
   978
	case EFont12x24:
sl@20
   979
		return 36;
sl@20
   980
	case EFont16x32:
sl@20
   981
		return 64;
sl@20
   982
	case EFont16x16:
sl@20
   983
		return 32;
sl@20
   984
	case EFont24x24:
sl@20
   985
		return 72;
sl@20
   986
	case EFont32x32:
sl@20
   987
		return 128;
sl@20
   988
		}
sl@20
   989
sl@20
   990
	return 0;
sl@20
   991
	}
sl@20
   992
sl@20
   993
/**
sl@20
   994
Define the User definable font (RAM) 
sl@20
   995
[Code] 1BH,6AH,47H,Pf,cL,(cH),Pd...Pd
sl@20
   996
[Function] Define the User definable font into RAM. A maximum 16 characters can be defined 
sl@20
   997
within each font size. 
sl@20
   998
The User definable fonts are displayed the defined code. It is a same process to normal fonts.  
sl@20
   999
The User definable fonts are valid until they redefined, Reset command, or the power off. 
sl@20
  1000
If define the user definable font over 16 characters, at first defined user definable font is removed    
sl@20
  1001
If the defined code is specified, existing data is re-written. 
sl@20
  1002
If the 16x16, 24x24, 32x32 size define, it must specify the “cH” 
sl@20
  1003
Pf = Font size 
sl@20
  1004
cL = Lower byte of User definable font code 
sl@20
  1005
cH = Upper byte of User definable font code 
sl@20
  1006
Pd = Definition data 
sl@20
  1007
[Definable area]
sl@20
  1008
Pf = 30H : 6x8 dot  (Pd=6 byte) 
sl@20
  1009
Pf = 31H : 8x16 dot  (Pd=16 byte) 
sl@20
  1010
Pf = 32H : 12x24 dot  (Pd=36 byte) 
sl@20
  1011
Pf = 33H : 16x32 dot  (Pd=64 byte) 
sl@20
  1012
Pf = 34H : 16x16 dot  (Pd=32 byte) 
sl@20
  1013
Pf = 35H : 24x24 dot  (Pd=72 byte) 
sl@20
  1014
Pf = 36H : 32x32 dot  (Pd=128 byte) 
sl@20
  1015
cL = ANK code (Pf=30H~33H : 1 byte code) 
sl@20
  1016
cL,cH = Shift-JIS code (Pf=34H~36H : 2 byte code)
sl@20
  1017
*/
sl@20
  1018
void GP1212A02A::SendCommandDefineCharacter(TFontSize aFontSize, unsigned short aCharacterCode, unsigned char* aPixels)
sl@20
  1019
	{
sl@20
  1020
	unsigned char reportSize=0;
sl@20
  1021
	unsigned char headerSize=0;
sl@20
  1022
	unsigned char dataSize=CharacterSizeInBytes(aFontSize);
sl@20
  1023
	FutabaVfdReport report;
sl@20
  1024
sl@20
  1025
	if (aFontSize>=EFont16x16)
sl@20
  1026
	{
sl@20
  1027
		//16 bits char code
sl@20
  1028
		headerSize=8;
sl@20
  1029
		reportSize = (dataSize<=report.Size()-headerSize?dataSize+0x06:64); //Report length. -7 is for our header first 7 bytes. +5 is for our Futaba header size
sl@20
  1030
		report[7] = aCharacterCode>>8;	
sl@20
  1031
	}
sl@20
  1032
	else
sl@20
  1033
	{
sl@20
  1034
		//8 bits char code
sl@20
  1035
		headerSize=7;
sl@20
  1036
		reportSize = (dataSize<=report.Size()-headerSize?dataSize+0x05:64); //Report length. -7 is for our header first 7 bytes. +5 is for our Futaba header size
sl@20
  1037
	}
sl@20
  1038
sl@20
  1039
	
sl@20
  1040
    report[0]=0x00; //Report ID
sl@20
  1041
    report[1]=reportSize; //Report size
sl@20
  1042
    report[2]=0x1B; //Command ID
sl@20
  1043
    report[3]=0x6A; //Command ID
sl@20
  1044
    report[4]=0x47; //Command ID
sl@20
  1045
    report[5]=aFontSize; //
sl@20
  1046
	report[6] = (unsigned char) aCharacterCode;
sl@20
  1047
	//7th byte was set above already
sl@20
  1048
	int sizeWritten=MIN(dataSize,report.Size()-headerSize);
sl@20
  1049
    memcpy(report.Buffer()+headerSize, aPixels, sizeWritten);
sl@20
  1050
    Write(report);
sl@20
  1051
sl@20
  1052
    int remainingSize=dataSize;
sl@20
  1053
    //We need to keep on sending our pixel data until we are done
sl@20
  1054
    while (report[1]==64)
sl@20
  1055
        {
sl@20
  1056
        report.Reset();
sl@20
  1057
        remainingSize-=sizeWritten;
sl@20
  1058
        report[0]=0x00; //Report ID
sl@20
  1059
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@20
  1060
        sizeWritten=(report[1]==64?63:report[1]);
sl@20
  1061
        memcpy(report.Buffer()+2, aPixels+(dataSize-remainingSize), sizeWritten);
sl@20
  1062
        Write(report);
sl@20
  1063
        }
sl@20
  1064
	}
sl@20
  1065
sl@20
  1066
sl@20
  1067
/**
sl@20
  1068
User definable font store / transfer / delete 
sl@20
  1069
[Code] 1BH,6AH,45H,Ps
sl@20
  1070
[Function] Store, transfer, or delete the User definable font to FROM.  
sl@20
  1071
* Define the user definable font, after the user definable font is stored 
sl@20
  1072
* The user definable font store is stored the all defined user definable font data. 
sl@20
  1073
* The use definable font delete is deleted the all defined to FROM and RAM user definable font data. 
sl@20
  1074
Ps = store / transfer / delete 
sl@20
  1075
[Definable area]
sl@20
  1076
Ps = 30H : Store
sl@20
  1077
Ps = 31H : Transfer
sl@20
  1078
Ps = 32H : Delete
sl@20
  1079
*/
sl@20
  1080
void GP1212A02A::SendCommandFontAction(TFontAction aFontAction)
sl@20
  1081
	{
sl@20
  1082
	FutabaVfdReport report;
sl@20
  1083
    report[0]=0x00; //Report ID
sl@20
  1084
    report[1]=0x04; //Report size
sl@20
  1085
    report[2]=0x1B; //Command ID
sl@20
  1086
    report[3]=0x6A; //Command ID
sl@20
  1087
    report[4]=0x45; //Command ID
sl@20
  1088
    report[5]=aFontAction; //Ps
sl@20
  1089
sl@20
  1090
    Write(report);
sl@20
  1091
	}
sl@21
  1092
sl@21
  1093
sl@21
  1094
/**
sl@21
  1095
[Code]1BH,4AH,46H,Pf
sl@21
  1096
[Function]Setting the font size 
sl@21
  1097
 Pf = Font size 
sl@21
  1098
[Definable area]
sl@21
  1099
Pf = 30H?6x8 dot 
sl@21
  1100
Pf = 31H?8x16dot and 16x16 dot 
sl@21
  1101
Pf = 32H?12x24 dot and 24x24 dot 
sl@21
  1102
Pf = 33H?16x32 dot and 32x32 dot
sl@21
  1103
*/
sl@21
  1104
void GP1212A02A::SendCommandSelectFontSize(TFontSizeLogical aFontSoze)
sl@21
  1105
	{
sl@21
  1106
	FutabaVfdReport report;
sl@21
  1107
    report[0]=0x00; //Report ID
sl@21
  1108
    report[1]=0x04; //Report size
sl@21
  1109
    report[2]=0x1B; //Command ID
sl@21
  1110
    report[3]=0x4A; //Command ID
sl@21
  1111
    report[4]=0x46; //Command ID
sl@21
  1112
    report[5]=aFontSoze; //Pf
sl@21
  1113
sl@21
  1114
    Write(report);
sl@21
  1115
	}