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