src/FutabaVfd.cpp
author sl
Thu, 22 May 2014 22:36:43 +0200
changeset 24 c6b5c552980a
parent 22 efa6ff02287c
child 25 233a997193b8
permissions -rw-r--r--
Draft implementation of our bitmap to display format.
sl@9
     1
sl@9
     2
#include "FutabaVfd.h"
sl@9
     3
//#include <stdlib.h>
sl@9
     4
#include <string.h>
sl@9
     5
sl@10
     6
sl@10
     7
//
sl@10
     8
//
sl@10
     9
//
sl@10
    10
sl@10
    11
sl@10
    12
sl@10
    13
sl@10
    14
sl@10
    15
//
sl@10
    16
//
sl@10
    17
//
sl@10
    18
sl@9
    19
FutabaVfdCommand::FutabaVfdCommand():/*iBuffer(NULL),*/iSize(0),iMaxSize(0)
sl@9
    20
    {
sl@9
    21
    }
sl@9
    22
sl@9
    23
FutabaVfdCommand::~FutabaVfdCommand()
sl@9
    24
    {
sl@9
    25
    //Delete();
sl@9
    26
    }
sl@9
    27
sl@9
    28
sl@9
    29
/**
sl@9
    30
sl@9
    31
*/
sl@9
    32
void FutabaVfdCommand::Reset()
sl@9
    33
    {
sl@9
    34
    memset(iReports,0,sizeof(iReports));
sl@9
    35
    }
sl@9
    36
sl@9
    37
sl@9
    38
sl@9
    39
/**
sl@9
    40
sl@9
    41
*/
sl@9
    42
/*
sl@9
    43
void FutabaVfdCommand::Create(int aMaxSize)
sl@9
    44
    {
sl@9
    45
    iBuffer=new unsigned char[aMaxSize];
sl@9
    46
    if (iBuffer)
sl@9
    47
        {
sl@9
    48
        iMaxSize = aMaxSize;
sl@9
    49
        iSize = 0;
sl@9
    50
        }
sl@9
    51
    }
sl@9
    52
*/
sl@9
    53
sl@9
    54
/**
sl@9
    55
sl@9
    56
*/
sl@9
    57
/*
sl@9
    58
void FutabaVfdCommand::Delete()
sl@9
    59
{
sl@9
    60
    delete[] iBuffer;
sl@9
    61
    iBuffer = NULL;
sl@9
    62
    iMaxSize = 0;
sl@9
    63
    iSize = 0;
sl@9
    64
}
sl@9
    65
*/
sl@9
    66
sl@9
    67
sl@10
    68
sl@10
    69
sl@10
    70
//
sl@10
    71
// class GP1212A01A
sl@10
    72
//
sl@10
    73
sl@23
    74
GP1212A01A::GP1212A01A():iDisplayPositionX(0),iDisplayPositionY(0),iOffScreenMode(true)
sl@23
    75
	{
sl@23
    76
	}
sl@23
    77
sl@10
    78
int GP1212A01A::Open()
sl@10
    79
	{
sl@10
    80
	int success = HidDevice::Open(KFutabaVendorId,KFutabaProductIdGP1212A01A,NULL);
sl@10
    81
	if (success)
sl@10
    82
		{
sl@10
    83
		SetNonBlocking(1);
sl@23
    84
		//Since we can't get our display position we for it to our default
sl@23
    85
		//This makes sure frames are in sync from the start
sl@23
    86
		SetDisplayPosition(iDisplayPositionX,iDisplayPositionY);
sl@10
    87
		}
sl@10
    88
	return success;
sl@10
    89
	}
sl@10
    90
sl@10
    91
/**
sl@10
    92
*/
sl@23
    93
void GP1212A01A::SetPixel(unsigned char aX, unsigned char aY, bool aOn)
sl@10
    94
	{
sl@10
    95
	//Just specify a one pixel block
sl@10
    96
	SetPixelBlock(aX,aY,0x00,0x01,aOn);
sl@10
    97
	}
sl@10
    98
sl@10
    99
/**
sl@23
   100
Set all pixels on our screen to the desired value.
sl@23
   101
This operation is performed off screen to avoid tearing.
sl@23
   102
@param 8 pixels pattern
sl@10
   103
*/
sl@23
   104
void GP1212A01A::SetAllPixels(unsigned char aPattern)
sl@10
   105
	{
sl@23
   106
	//With a single buffer
sl@23
   107
	//unsigned char screen[2048]; //One screen worth of pixels
sl@23
   108
	//memset(screen,0xFF,sizeof(screen));
sl@23
   109
	//SetPixelBlock(0,0,63,sizeof(screen),screen);
sl@10
   110
sl@23
   111
	//Using pattern SetPixelBlock variant.
sl@23
   112
	SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),aPattern);
sl@10
   113
	}
sl@10
   114
sl@10
   115
/**
sl@23
   116
Set our screen brightness.
sl@23
   117
@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
sl@10
   118
*/
sl@10
   119
void GP1212A01A::SetBrightness(int aBrightness)
sl@18
   120
    {
sl@18
   121
	if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
sl@18
   122
        {
sl@18
   123
        //Brightness out of range.
sl@18
   124
        //Just ignore that request.
sl@18
   125
        return;
sl@18
   126
        }
sl@18
   127
sl@18
   128
    FutabaVfdReport report;
sl@18
   129
    report[0]=0x00; //Report ID
sl@18
   130
    report[1]=0x06; //Report size
sl@18
   131
    report[2]=0x1B; //Command ID
sl@18
   132
    report[3]=0x5C; //Command ID
sl@18
   133
    report[4]=0x3F; //Command ID
sl@18
   134
    report[5]=0x4C; //Command ID
sl@18
   135
    report[6]=0x44; //Command ID
sl@18
   136
    report[7]=0x30+aBrightness; //Brightness level
sl@18
   137
    Write(report);
sl@18
   138
sl@10
   139
	}
sl@10
   140
sl@10
   141
/**
sl@10
   142
Set the defined pixel block to the given value.
sl@10
   143
@param X coordinate of our pixel block starting point.
sl@10
   144
@param Y coordinate of our pixel block starting point.
sl@10
   145
@param The height of our pixel block.
sl@10
   146
@param The size of our pixel data. Number of pixels divided by 8.
sl@20
   147
@param The value set to 8 pixels used as a pattern.
sl@10
   148
*/
sl@23
   149
void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char aValue)
sl@10
   150
	{
sl@23
   151
	OffScreenTranslation(aX,aY);
sl@23
   152
    FutabaVfdReport report;
sl@23
   153
    report[0]=0x00; //Report ID
sl@23
   154
    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@23
   155
    report[2]=0x1B; //Command ID
sl@23
   156
    report[3]=0x5B; //Command ID
sl@23
   157
    report[4]=0xF0; //Command ID
sl@23
   158
    report[5]=aX;   //X
sl@23
   159
    report[6]=aY;   //Y
sl@23
   160
    report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
sl@23
   161
	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
sl@23
   162
	report[9]=aSize;	//Size of pixel data in bytes (LSB)
sl@23
   163
    int sizeWritten=MIN(aSize,report.Size()-10);
sl@23
   164
    memset(report.Buffer()+10, aValue, sizeWritten);
sl@23
   165
    Write(report);
sl@23
   166
sl@23
   167
    int remainingSize=aSize;
sl@23
   168
    //We need to keep on sending our pixel data until we are done
sl@23
   169
    while (report[1]==64)
sl@23
   170
        {
sl@23
   171
        report.Reset();
sl@23
   172
        remainingSize-=sizeWritten;
sl@23
   173
        report[0]=0x00; //Report ID
sl@23
   174
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@23
   175
        sizeWritten=(report[1]==64?63:report[1]);
sl@23
   176
        memset(report.Buffer()+2, aValue, sizeWritten);
sl@23
   177
        Write(report);
sl@23
   178
        }
sl@10
   179
	}
sl@10
   180
sl@20
   181
/**
sl@20
   182
Set the defined pixel block to the given value.
sl@20
   183
@param X coordinate of our pixel block starting point.
sl@20
   184
@param Y coordinate of our pixel block starting point.
sl@20
   185
@param The height of our pixel block.
sl@20
   186
@param The size of our pixel data. Number of pixels divided by 8.
sl@20
   187
@param Pointer to our pixel data.
sl@20
   188
*/
sl@23
   189
void GP1212A01A::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
sl@20
   190
    {
sl@23
   191
	OffScreenTranslation(aX,aY);
sl@20
   192
    FutabaVfdReport report;
sl@20
   193
    report[0]=0x00; //Report ID
sl@23
   194
    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@20
   195
    report[2]=0x1B; //Command ID
sl@20
   196
    report[3]=0x5B; //Command ID
sl@20
   197
    report[4]=0xF0; //Command ID
sl@20
   198
    report[5]=aX;   //X
sl@20
   199
    report[6]=aY;   //Y
sl@20
   200
    report[7]=aHeight; //Y length before return. Though outside the specs, setting this to zero apparently allows us to modify a single pixel without touching any other.
sl@23
   201
	report[8]=aSize>>8; //Size of pixel data in bytes (MSB)
sl@23
   202
	report[9]=aSize;	//Size of pixel data in bytes (LSB)
sl@20
   203
    int sizeWritten=MIN(aSize,report.Size()-10);
sl@20
   204
    memcpy(report.Buffer()+10, aPixels, sizeWritten);
sl@20
   205
    Write(report);
sl@20
   206
sl@20
   207
    int remainingSize=aSize;
sl@20
   208
    //We need to keep on sending our pixel data until we are done
sl@20
   209
    while (report[1]==64)
sl@20
   210
        {
sl@20
   211
        report.Reset();
sl@20
   212
        remainingSize-=sizeWritten;
sl@20
   213
        report[0]=0x00; //Report ID
sl@23
   214
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
sl@20
   215
        sizeWritten=(report[1]==64?63:report[1]);
sl@20
   216
        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
sl@20
   217
        Write(report);
sl@20
   218
        }
sl@20
   219
    }
sl@20
   220
sl@10
   221
sl@10
   222
/**
sl@19
   223
Clear our display's screen.
sl@23
   224
This operation is performed off screen to avoid tearing.
sl@10
   225
*/
sl@10
   226
void GP1212A01A::Clear()
sl@10
   227
	{
sl@23
   228
	//Using pattern SetPixelBlock variant.
sl@23
   229
	//First fill our off screen buffer with the desired values
sl@23
   230
	SetPixelBlock(0,0,63,FrameBufferSizeInBytes(),(unsigned char)0x00);
sl@23
   231
	}
sl@23
   232
sl@23
   233
/**
sl@23
   234
Using this function is advised against as is causes tearing.
sl@23
   235
Use Clear instead.
sl@23
   236
*/
sl@23
   237
void GP1212A01A::SendClearCommand()
sl@23
   238
	{
sl@21
   239
    //1BH,5BH,32H,4AH
sl@21
   240
    //Send Clear Display Command
sl@10
   241
	FutabaVfdReport report;
sl@10
   242
	report[0]=0x00; //Report ID
sl@10
   243
	report[1]=0x04; //Report length
sl@19
   244
	report[2]=0x1B; //Command ID
sl@19
   245
	report[3]=0x5B; //Command ID
sl@19
   246
	report[4]=0x32; //Command ID
sl@19
   247
	report[5]=0x4A; //Command ID
sl@10
   248
	Write(report);
sl@19
   249
	}
sl@19
   250
sl@19
   251
/**
sl@21
   252
Change our display position within our buffer.
sl@21
   253
*/
sl@23
   254
void GP1212A01A::SetDisplayPosition(DW aDw,unsigned char aX, unsigned char aY)
sl@21
   255
    {
sl@21
   256
    //1BH,5BH,Dw,Px,Py
sl@21
   257
    //Send Display Position Settings Command
sl@21
   258
    FutabaVfdReport report;
sl@21
   259
    report[0]=0x00; //Report ID
sl@21
   260
    report[1]=0x05; //Report length
sl@21
   261
    report[2]=0x1B; //Command ID
sl@21
   262
    report[3]=0x5B; //Command ID
sl@21
   263
    report[4]=aDw;  //Specify our DW
sl@21
   264
    report[5]=aX;   //X coordinate of our DW top-left corner
sl@22
   265
    report[6]=aY;   //Y coordinate of our DW top-left corner
sl@21
   266
    Write(report);
sl@21
   267
    }
sl@21
   268
sl@21
   269
/**
sl@22
   270
Change our display position within our buffer.
sl@22
   271
*/
sl@23
   272
void GP1212A01A::SetDisplayPosition(unsigned char aX, unsigned char aY)
sl@22
   273
	{
sl@22
   274
	//Specs apparently says both DW should remain the same
sl@22
   275
	//Just don't ask
sl@22
   276
    SetDisplayPosition(GP1212A01A::DW1,aX,aY);
sl@22
   277
    SetDisplayPosition(GP1212A01A::DW2,aX,aY);
sl@23
   278
	iDisplayPositionX=aX;
sl@23
   279
	iDisplayPositionY=aY;
sl@23
   280
	}
sl@23
   281
sl@23
   282
/**
sl@23
   283
Provide Y coordinate of our off screen buffer.
sl@23
   284
*/
sl@23
   285
unsigned char GP1212A01A::OffScreenY() const
sl@23
   286
	{
sl@23
   287
	//Overflowing is fine this is just what we want
sl@23
   288
	return iDisplayPositionY+HeightInPixels();
sl@23
   289
	}
sl@23
   290
sl@23
   291
/**
sl@23
   292
Put our off screen buffer on screen.
sl@23
   293
On screen buffer goes off screen.
sl@23
   294
*/
sl@23
   295
void GP1212A01A::SwapBuffers()
sl@23
   296
	{
sl@23
   297
	//Only perform buffer swapping if off screen mode is enabled
sl@23
   298
	if (OffScreenMode())
sl@23
   299
		{
sl@23
   300
		SetDisplayPosition(iDisplayPositionX,OffScreenY());
sl@23
   301
		}
sl@23
   302
	}
sl@23
   303
sl@23
   304
/**
sl@23
   305
Translate the given pixel coordinate according to our off screen mode.
sl@23
   306
*/
sl@23
   307
void GP1212A01A::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
sl@23
   308
	{
sl@23
   309
	if (OffScreenMode())
sl@23
   310
		{
sl@23
   311
		aX+=WidthInPixels()-iDisplayPositionX;
sl@23
   312
		aY+=HeightInPixels()-iDisplayPositionY;
sl@23
   313
		}
sl@22
   314
	}
sl@22
   315
/**
sl@19
   316
*/
sl@19
   317
void GP1212A01A::RequestId()
sl@19
   318
    {
sl@19
   319
    //1BH,5BH,63H,49H,44H
sl@19
   320
    //Send Read ID command
sl@19
   321
    FutabaVfdReport report;
sl@19
   322
    report[0]=0x00; //Report ID
sl@19
   323
    report[1]=0x05; //Report length
sl@19
   324
    report[2]=0x1B; //Command ID
sl@19
   325
    report[3]=0x5B; //Command ID
sl@19
   326
    report[4]=0x63; //Command ID
sl@19
   327
    report[5]=0x49; //Command ID
sl@19
   328
    report[6]=0x44; //Command ID
sl@19
   329
    Write(report);
sl@19
   330
    }
sl@19
   331
sl@19
   332
/**
sl@19
   333
*/
sl@19
   334
void GP1212A01A::RequestFirmwareRevision()
sl@19
   335
    {
sl@19
   336
    //1BH,5BH,63H,46H,52H
sl@19
   337
    //Send Software Revision Read Command
sl@19
   338
    FutabaVfdReport report;
sl@19
   339
    report[0]=0x00; //Report ID
sl@19
   340
    report[1]=0x05; //Report length
sl@19
   341
    report[2]=0x1B; //Command ID
sl@19
   342
    report[3]=0x5B; //Command ID
sl@19
   343
    report[4]=0x63; //Command ID
sl@19
   344
    report[5]=0x46; //Command ID
sl@19
   345
    report[6]=0x52; //Command ID
sl@19
   346
    Write(report);
sl@19
   347
    }
sl@19
   348
sl@19
   349
/**
sl@19
   350
*/
sl@19
   351
void GP1212A01A::RequestPowerSupplyStatus()
sl@19
   352
    {
sl@19
   353
    //1BH,5BH,63H,50H,4DH
sl@19
   354
    //Send Power Suppply Monitor Command
sl@19
   355
    FutabaVfdReport report;
sl@19
   356
    report[0]=0x00; //Report ID
sl@19
   357
    report[1]=0x05; //Report length
sl@19
   358
    report[2]=0x1B; //Command ID
sl@19
   359
    report[3]=0x5B; //Command ID
sl@19
   360
    report[4]=0x63; //Command ID
sl@19
   361
    report[5]=0x50; //Command ID
sl@19
   362
    report[6]=0x4D; //Command ID
sl@19
   363
    Write(report);
sl@23
   364
    }
sl@23
   365
sl@23
   366
sl@23
   367
/**
sl@23
   368
This is for development purposes only.
sl@23
   369
Production application should stick to off-screen mode to avoid tearing.
sl@23
   370
*/
sl@23
   371
void GP1212A01A::ToggleOffScreenMode()
sl@23
   372
	{
sl@23
   373
	iOffScreenMode=!iOffScreenMode;
sl@23
   374
	//Clean up our buffers upon switching modes	
sl@23
   375
	SetDisplayPosition(0,0);
sl@23
   376
	Clear();
sl@23
   377
	SwapBuffers();
sl@23
   378
	Clear();
sl@23
   379
	}