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