FutabaMDM166AA.cpp
author StephaneLenclud
Wed, 04 Feb 2015 21:47:17 +0100
changeset 25 3fa4007c0b19
child 27 949be5444c57
permissions -rw-r--r--
First draft implementation of Futaba MDM166AA.
Only clock and brightness working for now.
StephaneLenclud@25
     1
//
StephaneLenclud@25
     2
//
StephaneLenclud@25
     3
//
StephaneLenclud@25
     4
StephaneLenclud@25
     5
#include "FutabaMDM166AA.h"
StephaneLenclud@25
     6
StephaneLenclud@25
     7
#include <stdio.h>
StephaneLenclud@25
     8
#include <time.h>
StephaneLenclud@25
     9
StephaneLenclud@25
    10
StephaneLenclud@25
    11
StephaneLenclud@25
    12
static void sleep(unsigned int mseconds)
StephaneLenclud@25
    13
	{
StephaneLenclud@25
    14
    clock_t goal = mseconds + clock();
StephaneLenclud@25
    15
    while (goal > clock());
StephaneLenclud@25
    16
	}
StephaneLenclud@25
    17
StephaneLenclud@25
    18
//
StephaneLenclud@25
    19
// class MDM166AA
StephaneLenclud@25
    20
//
StephaneLenclud@25
    21
StephaneLenclud@25
    22
MDM166AA::MDM166AA():
StephaneLenclud@25
    23
	iDisplayPositionX(0),iDisplayPositionY(0),
StephaneLenclud@25
    24
    iOffScreenMode(true),
StephaneLenclud@25
    25
    iUseFrameDifferencing(true),
StephaneLenclud@25
    26
    iFrameNext(NULL),
StephaneLenclud@25
    27
    iFrameCurrent(NULL),
StephaneLenclud@25
    28
    iFramePrevious(NULL),
StephaneLenclud@25
    29
    iFrameAlpha(NULL),
StephaneLenclud@25
    30
    iFrameBeta(NULL),
StephaneLenclud@25
    31
    iFrameGamma(NULL),
StephaneLenclud@25
    32
    iNeedFullFrameUpdate(0),
StephaneLenclud@25
    33
    iPowerOn(false)
StephaneLenclud@25
    34
	{
StephaneLenclud@25
    35
	iDeviceId[0]=0;
StephaneLenclud@25
    36
	iFirmwareRevision[0]=0;
StephaneLenclud@25
    37
	//ResetBuffers();
StephaneLenclud@25
    38
	}
StephaneLenclud@25
    39
StephaneLenclud@25
    40
/**
StephaneLenclud@25
    41
*/
StephaneLenclud@25
    42
MDM166AA::~MDM166AA()
StephaneLenclud@25
    43
	{
StephaneLenclud@25
    44
    delete iFrameAlpha;
StephaneLenclud@25
    45
    iFrameAlpha=NULL;
StephaneLenclud@25
    46
    //
StephaneLenclud@25
    47
    delete iFrameBeta;
StephaneLenclud@25
    48
    iFrameBeta=NULL;
StephaneLenclud@25
    49
    //
StephaneLenclud@25
    50
    delete iFrameGamma;
StephaneLenclud@25
    51
    iFrameGamma=NULL;
StephaneLenclud@25
    52
    //
StephaneLenclud@25
    53
    iFrameNext=NULL;
StephaneLenclud@25
    54
    iFrameCurrent=NULL;
StephaneLenclud@25
    55
    iFramePrevious=NULL;
StephaneLenclud@25
    56
    //
StephaneLenclud@25
    57
    iNeedFullFrameUpdate=0;
StephaneLenclud@25
    58
	}
StephaneLenclud@25
    59
StephaneLenclud@25
    60
/**
StephaneLenclud@25
    61
*/
StephaneLenclud@25
    62
int MDM166AA::Open()
StephaneLenclud@25
    63
	{
StephaneLenclud@25
    64
	int success = HidDevice::Open(KTargaVendorId,KFutabaProductIdMDM166AA,NULL);
StephaneLenclud@25
    65
	if (success)
StephaneLenclud@25
    66
		{
StephaneLenclud@25
    67
        //Allocate both frames
StephaneLenclud@25
    68
        delete iFrameAlpha;
StephaneLenclud@25
    69
        iFrameAlpha=NULL;
StephaneLenclud@25
    70
        iFrameAlpha=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
StephaneLenclud@25
    71
        //
StephaneLenclud@25
    72
        delete iFrameBeta;
StephaneLenclud@25
    73
        iFrameBeta=NULL;
StephaneLenclud@25
    74
        iFrameBeta=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
StephaneLenclud@25
    75
        //
StephaneLenclud@25
    76
        delete iFrameGamma;
StephaneLenclud@25
    77
        iFrameGamma=NULL;
StephaneLenclud@25
    78
        iFrameGamma=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
StephaneLenclud@25
    79
        //
StephaneLenclud@25
    80
        iFrameNext=iFrameAlpha;
StephaneLenclud@25
    81
        iFrameCurrent=iFrameBeta;
StephaneLenclud@25
    82
        iFramePrevious=iFrameGamma;
StephaneLenclud@25
    83
StephaneLenclud@25
    84
StephaneLenclud@25
    85
        //To make sure it is synced properly
StephaneLenclud@25
    86
        iNeedFullFrameUpdate=0;
StephaneLenclud@25
    87
        //
StephaneLenclud@25
    88
		SetNonBlocking(1);
StephaneLenclud@25
    89
		//
StephaneLenclud@25
    90
		SendCommandClear();
StephaneLenclud@25
    91
		//
StephaneLenclud@25
    92
		SetClockSetting();
StephaneLenclud@25
    93
StephaneLenclud@25
    94
		}
StephaneLenclud@25
    95
	return success;
StephaneLenclud@25
    96
	}
StephaneLenclud@25
    97
StephaneLenclud@25
    98
StephaneLenclud@25
    99
/**
StephaneLenclud@25
   100
Display RAM filled with 00H.
StephaneLenclud@25
   101
Address Counter is set by 00H.
StephaneLenclud@25
   102
Dimming is set to 50%.
StephaneLenclud@25
   103
*/
StephaneLenclud@25
   104
void MDM166AA::SendCommandReset()
StephaneLenclud@25
   105
	{
StephaneLenclud@25
   106
	FutabaVfdReport report;
StephaneLenclud@25
   107
	report[0]=0x00; //Report ID
StephaneLenclud@25
   108
	report[1]=0x01; //Report length.
StephaneLenclud@25
   109
	report[2]=0x1F; //Command ID
StephaneLenclud@25
   110
	Write(report);
StephaneLenclud@25
   111
	//Wait until reset is done. Is that needed?
StephaneLenclud@25
   112
	//sleep(2000);
StephaneLenclud@25
   113
	}
StephaneLenclud@25
   114
StephaneLenclud@25
   115
StephaneLenclud@25
   116
/**
StephaneLenclud@25
   117
Set Address Counter (AC) values: 1BH + 60H + xxH
StephaneLenclud@25
   118
xxH: 00 ~ BFH
StephaneLenclud@25
   119
AC value represents the start address for graphic data.
StephaneLenclud@25
   120
There are 192 bytes as display RAM. It can be set on anywhere even if AC value is not visible area.
StephaneLenclud@25
   121
The default value is 00H.
StephaneLenclud@25
   122
Default: 00H
StephaneLenclud@25
   123
When clock is displayed, AC value is set 00H.
StephaneLenclud@25
   124
*/
StephaneLenclud@25
   125
void MDM166AA::SendCommandSetAddressCounter(unsigned char aAddressCounter)
StephaneLenclud@25
   126
	{
StephaneLenclud@25
   127
	FutabaVfdReport report;
StephaneLenclud@25
   128
	report[0]=0x00; //Report ID
StephaneLenclud@25
   129
	report[1]=0x03; //Report length.
StephaneLenclud@25
   130
	report[2]=0x1B; //Command ID
StephaneLenclud@25
   131
	report[3]=0x60; //Command ID
StephaneLenclud@25
   132
	report[4]=aAddressCounter;
StephaneLenclud@25
   133
	Write(report);
StephaneLenclud@25
   134
	}
StephaneLenclud@25
   135
StephaneLenclud@25
   136
StephaneLenclud@25
   137
/**
StephaneLenclud@25
   138
*/
StephaneLenclud@25
   139
void MDM166AA::SetPixel(unsigned char aX, unsigned char aY, unsigned int aPixel)
StephaneLenclud@25
   140
	{
StephaneLenclud@25
   141
	//
StephaneLenclud@25
   142
	//int byteOffset=(aX*HeightInPixels()+aY)/8;
StephaneLenclud@25
   143
	//int bitOffset=(aX*HeightInPixels()+aY)%8;
StephaneLenclud@25
   144
    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
StephaneLenclud@25
   145
StephaneLenclud@25
   146
	//Pixel is on if any of the non-alpha component is not null
StephaneLenclud@25
   147
	bool on = (aPixel&0x00FFFFFF)!=0x00000000;
StephaneLenclud@25
   148
StephaneLenclud@25
   149
    if (iOffScreenMode)
StephaneLenclud@25
   150
        {
StephaneLenclud@25
   151
        if (on)
StephaneLenclud@25
   152
            {
StephaneLenclud@25
   153
            iFrameNext->SetBit(aX*HeightInPixels()+aY);
StephaneLenclud@25
   154
            }
StephaneLenclud@25
   155
        else
StephaneLenclud@25
   156
            {
StephaneLenclud@25
   157
            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
StephaneLenclud@25
   158
            }
StephaneLenclud@25
   159
        }
StephaneLenclud@25
   160
    else
StephaneLenclud@25
   161
        {
StephaneLenclud@25
   162
        //Just specify a one pixel block
StephaneLenclud@25
   163
        //TODO
StephaneLenclud@25
   164
        }
StephaneLenclud@25
   165
	}
StephaneLenclud@25
   166
StephaneLenclud@25
   167
/**
StephaneLenclud@25
   168
*/
StephaneLenclud@25
   169
/*
StephaneLenclud@25
   170
void MDM166AA::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
StephaneLenclud@25
   171
	{
StephaneLenclud@25
   172
	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
StephaneLenclud@25
   173
	for (int i=0;i<aSrcWidth;i++)
StephaneLenclud@25
   174
		{
StephaneLenclud@25
   175
		for (int j=0;j<aSrcHeight;j++)
StephaneLenclud@25
   176
			{
StephaneLenclud@25
   177
            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
StephaneLenclud@25
   178
			}
StephaneLenclud@25
   179
		}
StephaneLenclud@25
   180
	}
StephaneLenclud@25
   181
*/
StephaneLenclud@25
   182
StephaneLenclud@25
   183
/**
StephaneLenclud@25
   184
Clear our client side back buffer.
StephaneLenclud@25
   185
Call to SwapBuffers must follow to actually clear the display.
StephaneLenclud@25
   186
*/
StephaneLenclud@25
   187
void MDM166AA::Clear()
StephaneLenclud@25
   188
    {
StephaneLenclud@25
   189
	//That one also clear the symbols
StephaneLenclud@25
   190
    SendCommandClear();
StephaneLenclud@25
   191
	//TODO: Consider just clearing the pixels instead
StephaneLenclud@25
   192
    }
StephaneLenclud@25
   193
StephaneLenclud@25
   194
/**
StephaneLenclud@25
   195
Turn on all pixels.
StephaneLenclud@25
   196
Must be followed by a SwapBuffers call.
StephaneLenclud@25
   197
*/
StephaneLenclud@25
   198
void MDM166AA::Fill()
StephaneLenclud@25
   199
	{
StephaneLenclud@25
   200
	SetAllPixels(0xFF);
StephaneLenclud@25
   201
	}
StephaneLenclud@25
   202
StephaneLenclud@25
   203
/**
StephaneLenclud@25
   204
Set all pixels on our screen to the desired value.
StephaneLenclud@25
   205
This operation is performed off screen to avoid tearing.
StephaneLenclud@25
   206
@param 8 pixels pattern
StephaneLenclud@25
   207
*/
StephaneLenclud@25
   208
void MDM166AA::SetAllPixels(unsigned char aPattern)
StephaneLenclud@25
   209
	{
StephaneLenclud@25
   210
	//With a single buffer
StephaneLenclud@25
   211
	//unsigned char screen[2048]; //One screen worth of pixels
StephaneLenclud@25
   212
	//memset(screen,0xFF,sizeof(screen));
StephaneLenclud@25
   213
	//SetPixelBlock(0,0,63,sizeof(screen),screen);
StephaneLenclud@25
   214
StephaneLenclud@25
   215
StephaneLenclud@25
   216
    if (iOffScreenMode)
StephaneLenclud@25
   217
        {
StephaneLenclud@25
   218
        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
StephaneLenclud@25
   219
        }
StephaneLenclud@25
   220
    else
StephaneLenclud@25
   221
        {
StephaneLenclud@25
   222
        //Using pattern SetPixelBlock variant.
StephaneLenclud@25
   223
        //TODO
StephaneLenclud@25
   224
        }
StephaneLenclud@25
   225
	//
StephaneLenclud@25
   226
	}
StephaneLenclud@25
   227
StephaneLenclud@25
   228
StephaneLenclud@25
   229
StephaneLenclud@25
   230
StephaneLenclud@25
   231
StephaneLenclud@25
   232
StephaneLenclud@25
   233
/**
StephaneLenclud@25
   234
Whole display RAM areas including invisible area are filled with 00H data.
StephaneLenclud@25
   235
(Include the symbol)
StephaneLenclud@25
   236
SL: Though there is no invisible area with that device.
StephaneLenclud@25
   237
*/
StephaneLenclud@25
   238
void MDM166AA::SendCommandClear()
StephaneLenclud@25
   239
	{
StephaneLenclud@25
   240
    //Send Clear Display Command
StephaneLenclud@25
   241
	FutabaVfdReport report;
StephaneLenclud@25
   242
	report[0]=0x00; //Report ID
StephaneLenclud@25
   243
	report[1]=0x02; //Report length
StephaneLenclud@25
   244
	report[2]=0x1B; //Command ID
StephaneLenclud@25
   245
	report[3]=0x50; //Command ID
StephaneLenclud@25
   246
	Write(report);
StephaneLenclud@25
   247
	}
StephaneLenclud@25
   248
StephaneLenclud@25
   249
StephaneLenclud@25
   250
/**
StephaneLenclud@25
   251
Provide Y coordinate of our off screen buffer.
StephaneLenclud@25
   252
*/
StephaneLenclud@25
   253
unsigned char MDM166AA::OffScreenY() const
StephaneLenclud@25
   254
	{
StephaneLenclud@25
   255
	//Overflowing is fine this is just what we want
StephaneLenclud@25
   256
	return iDisplayPositionY+HeightInPixels();
StephaneLenclud@25
   257
	}
StephaneLenclud@25
   258
StephaneLenclud@25
   259
/**
StephaneLenclud@25
   260
Put our off screen buffer on screen.
StephaneLenclud@25
   261
On screen buffer goes off screen.
StephaneLenclud@25
   262
*/
StephaneLenclud@25
   263
void MDM166AA::SwapBuffers()
StephaneLenclud@25
   264
	{
StephaneLenclud@25
   265
	//Only perform buffer swapping if off screen mode is enabled
StephaneLenclud@25
   266
	if (OffScreenMode())
StephaneLenclud@25
   267
		{
StephaneLenclud@25
   268
		//Send pixel directly into BMP box
StephaneLenclud@25
   269
		//BmpBoxDataInput(FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@25
   270
		//Send pixel data directly into the display window
StephaneLenclud@25
   271
		//BmpDataInput(ETargetDisplayWindow,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@25
   272
		//Send pixel data first to Data Memory then copy into the selected BMP box	
StephaneLenclud@25
   273
		//BmpDataInput(ETargetDataMemory,0x0000,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@25
   274
		//BmpBoxDataMemoryTransfer(0x0000);
StephaneLenclud@25
   275
		//Send pixel data first to Data Memory then copy into the selected BMP box, cycling through our Data Memory frmae
StephaneLenclud@25
   276
		//BmpDataInput(ETargetDataMemory,iNextFrameAddress,EDirectionY, FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@25
   277
		//BmpBoxDataMemoryTransfer(iNextFrameAddress);
StephaneLenclud@25
   278
StephaneLenclud@25
   279
StephaneLenclud@25
   280
        //Cycle through our frame buffers
StephaneLenclud@25
   281
        //We keep track of previous frame which is in fact our device back buffer.
StephaneLenclud@25
   282
        //We can then compare previous and next frame and send only the differences to our device.
StephaneLenclud@25
   283
        //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
StephaneLenclud@25
   284
        //Keep our previous frame pointer
StephaneLenclud@25
   285
        BitArrayLow* previousFrame=iFramePrevious;
StephaneLenclud@25
   286
        //Current frame becomes the previous one
StephaneLenclud@25
   287
        iFramePrevious = iFrameCurrent;
StephaneLenclud@25
   288
        //Next frame becomes the current one
StephaneLenclud@25
   289
        iFrameCurrent = iFrameNext;
StephaneLenclud@25
   290
        //Next frame is now our former previous
StephaneLenclud@25
   291
        iFrameNext = previousFrame;
StephaneLenclud@25
   292
		}
StephaneLenclud@25
   293
	}
StephaneLenclud@25
   294
StephaneLenclud@25
   295
StephaneLenclud@25
   296
/**
StephaneLenclud@25
   297
Set the defined pixel block to the given value.
StephaneLenclud@25
   298
@param X coordinate of our pixel block starting point.
StephaneLenclud@25
   299
@param Y coordinate of our pixel block starting point.
StephaneLenclud@25
   300
@param The height of our pixel block.
StephaneLenclud@25
   301
@param The size of our pixel data. Number of pixels divided by 8.
StephaneLenclud@25
   302
@param Pointer to our pixel data.
StephaneLenclud@25
   303
*/
StephaneLenclud@25
   304
void MDM166AA::SetPixelBlock(unsigned char aX, unsigned char aY, int aHeight, int aSize, unsigned char* aPixels)
StephaneLenclud@25
   305
    {
StephaneLenclud@25
   306
	//TODO: Assuming 0,0 for now, do the math later
StephaneLenclud@25
   307
	SendCommandSetAddressCounter(0);
StephaneLenclud@25
   308
StephaneLenclud@25
   309
	const int KMaxPixelBytes=48;
StephaneLenclud@25
   310
StephaneLenclud@25
   311
    FutabaVfdReport report;
StephaneLenclud@25
   312
    report[0]=0x00; //Report ID
StephaneLenclud@25
   313
    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
StephaneLenclud@25
   314
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   315
    report[3]=0x70; //Command ID
StephaneLenclud@25
   316
	//TODO: All rubbish
StephaneLenclud@25
   317
	report[4]=MAX(KMaxPixelBytes,aSize); //Size of pixel data in bytes
StephaneLenclud@25
   318
    int sizeWritten=MIN(aSize,report.Size()-10);
StephaneLenclud@25
   319
    memcpy(report.Buffer()+10, aPixels, sizeWritten);
StephaneLenclud@25
   320
    Write(report);
StephaneLenclud@25
   321
StephaneLenclud@25
   322
    int remainingSize=aSize;
StephaneLenclud@25
   323
    //We need to keep on sending our pixel data until we are done
StephaneLenclud@25
   324
    while (report[1]==64)
StephaneLenclud@25
   325
        {
StephaneLenclud@25
   326
        report.Reset();
StephaneLenclud@25
   327
        remainingSize-=sizeWritten;
StephaneLenclud@25
   328
        report[0]=0x00; //Report ID
StephaneLenclud@25
   329
        report[1]=(remainingSize<=report.Size()-2?remainingSize:64); //Report length, should be 64 or the remaining size
StephaneLenclud@25
   330
        sizeWritten=(report[1]==64?63:report[1]);
StephaneLenclud@25
   331
        memcpy(report.Buffer()+2, aPixels+(aSize-remainingSize), sizeWritten);
StephaneLenclud@25
   332
        Write(report);
StephaneLenclud@25
   333
        }
StephaneLenclud@25
   334
    }
StephaneLenclud@25
   335
StephaneLenclud@25
   336
StephaneLenclud@25
   337
StephaneLenclud@25
   338
//Define the edge of our pixel block
StephaneLenclud@25
   339
//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
StephaneLenclud@25
   340
//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
StephaneLenclud@25
   341
const int KPixelBlockEdge = 32;
StephaneLenclud@25
   342
const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
StephaneLenclud@25
   343
const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
StephaneLenclud@25
   344
StephaneLenclud@25
   345
StephaneLenclud@25
   346
/**
StephaneLenclud@25
   347
Translate the given pixel coordinate according to our off screen mode.
StephaneLenclud@25
   348
*/
StephaneLenclud@25
   349
void MDM166AA::OffScreenTranslation(unsigned char& aX, unsigned char& aY)
StephaneLenclud@25
   350
	{
StephaneLenclud@25
   351
	if (OffScreenMode())
StephaneLenclud@25
   352
		{
StephaneLenclud@25
   353
		aX+=WidthInPixels()-iDisplayPositionX;
StephaneLenclud@25
   354
		aY+=HeightInPixels()-iDisplayPositionY;
StephaneLenclud@25
   355
		}
StephaneLenclud@25
   356
	}
StephaneLenclud@25
   357
StephaneLenclud@25
   358
StephaneLenclud@25
   359
/**
StephaneLenclud@25
   360
*/
StephaneLenclud@25
   361
void MDM166AA::Request(TMiniDisplayRequest aRequest)
StephaneLenclud@25
   362
	{
StephaneLenclud@25
   363
	switch (aRequest)
StephaneLenclud@25
   364
		{
StephaneLenclud@25
   365
	case EMiniDisplayRequestDeviceId:
StephaneLenclud@25
   366
		RequestDeviceId();
StephaneLenclud@25
   367
		break;
StephaneLenclud@25
   368
	case EMiniDisplayRequestFirmwareRevision:
StephaneLenclud@25
   369
		RequestFirmwareRevision();
StephaneLenclud@25
   370
		break;
StephaneLenclud@25
   371
	case EMiniDisplayRequestPowerSupplyStatus:
StephaneLenclud@25
   372
		RequestPowerSupplyStatus();
StephaneLenclud@25
   373
		break;
StephaneLenclud@25
   374
	default:
StephaneLenclud@25
   375
		//Not supported
StephaneLenclud@25
   376
		break;
StephaneLenclud@25
   377
		};
StephaneLenclud@25
   378
	}
StephaneLenclud@25
   379
StephaneLenclud@25
   380
StephaneLenclud@25
   381
/**
StephaneLenclud@25
   382
*/
StephaneLenclud@25
   383
void MDM166AA::ResetBuffers()
StephaneLenclud@25
   384
	{
StephaneLenclud@25
   385
    //iNextFrame->ClearAll();
StephaneLenclud@25
   386
    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
StephaneLenclud@25
   387
	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
StephaneLenclud@25
   388
	}
StephaneLenclud@25
   389
StephaneLenclud@25
   390
/**
StephaneLenclud@25
   391
*/
StephaneLenclud@25
   392
void MDM166AA::RequestDeviceId()
StephaneLenclud@25
   393
    {
StephaneLenclud@25
   394
	//Not supported
StephaneLenclud@25
   395
    }
StephaneLenclud@25
   396
StephaneLenclud@25
   397
/**
StephaneLenclud@25
   398
ID code 
StephaneLenclud@25
   399
[Code] 1BH,6AH,49H,44H
StephaneLenclud@25
   400
[Function] Send the ID code to the Host system. ID code is software version.
StephaneLenclud@25
   401
*/
StephaneLenclud@25
   402
void MDM166AA::RequestFirmwareRevision()
StephaneLenclud@25
   403
    {
StephaneLenclud@25
   404
    if (RequestPending())
StephaneLenclud@25
   405
        {
StephaneLenclud@25
   406
        //Abort silently for now
StephaneLenclud@25
   407
        return;
StephaneLenclud@25
   408
        }
StephaneLenclud@25
   409
StephaneLenclud@25
   410
    //1BH,6AH,49H,44H
StephaneLenclud@25
   411
    //Send Software Revision Read Command
StephaneLenclud@25
   412
    FutabaVfdReport report;
StephaneLenclud@25
   413
    report[0]=0x00; //Report ID
StephaneLenclud@25
   414
    report[1]=0x04; //Report length
StephaneLenclud@25
   415
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   416
    report[3]=0x6A; //Command ID
StephaneLenclud@25
   417
    report[4]=0x49; //Command ID
StephaneLenclud@25
   418
    report[5]=0x44; //Command ID
StephaneLenclud@25
   419
    if (Write(report)==report.Size())
StephaneLenclud@25
   420
        {
StephaneLenclud@25
   421
        SetRequest(EMiniDisplayRequestFirmwareRevision);
StephaneLenclud@25
   422
        }
StephaneLenclud@25
   423
StephaneLenclud@25
   424
    }
StephaneLenclud@25
   425
StephaneLenclud@25
   426
/**
StephaneLenclud@25
   427
*/
StephaneLenclud@25
   428
void MDM166AA::RequestPowerSupplyStatus()
StephaneLenclud@25
   429
    {
StephaneLenclud@25
   430
	//Not supported
StephaneLenclud@25
   431
    }
StephaneLenclud@25
   432
StephaneLenclud@25
   433
StephaneLenclud@25
   434
/**
StephaneLenclud@25
   435
This is for development purposes only.
StephaneLenclud@25
   436
Production application should stick to off-screen mode to avoid tearing.
StephaneLenclud@25
   437
*/
StephaneLenclud@25
   438
void MDM166AA::ToggleOffScreenMode()
StephaneLenclud@25
   439
	{
StephaneLenclud@25
   440
    SetOffScreenMode(!iOffScreenMode);
StephaneLenclud@25
   441
	}
StephaneLenclud@25
   442
StephaneLenclud@25
   443
/**
StephaneLenclud@25
   444
 * @brief MDM166AA::SetOffScreenMode
StephaneLenclud@25
   445
 * @param aOn
StephaneLenclud@25
   446
 * @return
StephaneLenclud@25
   447
 */
StephaneLenclud@25
   448
void MDM166AA::SetOffScreenMode(bool aOn)
StephaneLenclud@25
   449
    {
StephaneLenclud@25
   450
    if (aOn==iOffScreenMode)
StephaneLenclud@25
   451
    {
StephaneLenclud@25
   452
        //Nothing to do here
StephaneLenclud@25
   453
        return;
StephaneLenclud@25
   454
    }
StephaneLenclud@25
   455
StephaneLenclud@25
   456
    iOffScreenMode=aOn;
StephaneLenclud@25
   457
StephaneLenclud@25
   458
    //Clean up our buffers upon switching modes
StephaneLenclud@25
   459
    Clear();
StephaneLenclud@25
   460
    SwapBuffers();
StephaneLenclud@25
   461
    Clear();
StephaneLenclud@25
   462
    }
StephaneLenclud@25
   463
StephaneLenclud@25
   464
/**
StephaneLenclud@25
   465
Tries to complete our current request if we have one pending.
StephaneLenclud@25
   466
 */
StephaneLenclud@25
   467
TMiniDisplayRequest MDM166AA::AttemptRequestCompletion()
StephaneLenclud@25
   468
    {
StephaneLenclud@25
   469
    if (!RequestPending())
StephaneLenclud@25
   470
        {
StephaneLenclud@25
   471
        return EMiniDisplayRequestNone;
StephaneLenclud@25
   472
        }
StephaneLenclud@25
   473
StephaneLenclud@25
   474
    int res=Read(iInputReport);
StephaneLenclud@25
   475
StephaneLenclud@25
   476
    if (!res)
StephaneLenclud@25
   477
        {
StephaneLenclud@25
   478
        return EMiniDisplayRequestNone;
StephaneLenclud@25
   479
        }
StephaneLenclud@25
   480
StephaneLenclud@25
   481
    //Process our request
StephaneLenclud@25
   482
	if (CurrentRequest()==EMiniDisplayRequestFirmwareRevision)
StephaneLenclud@25
   483
		{
StephaneLenclud@25
   484
			unsigned char* ptr=&iInputReport[2];
StephaneLenclud@25
   485
			iInputReport[7]=0x00;
StephaneLenclud@25
   486
			strcpy(iFirmwareRevision,(const char*)ptr);
StephaneLenclud@25
   487
		}
StephaneLenclud@25
   488
StephaneLenclud@25
   489
    TMiniDisplayRequest completed=CurrentRequest();
StephaneLenclud@25
   490
    //Our request was completed
StephaneLenclud@25
   491
    SetRequest(EMiniDisplayRequestNone);
StephaneLenclud@25
   492
StephaneLenclud@25
   493
    return completed;
StephaneLenclud@25
   494
	}
StephaneLenclud@25
   495
StephaneLenclud@25
   496
StephaneLenclud@25
   497
/**
StephaneLenclud@25
   498
Set our screen brightness.
StephaneLenclud@25
   499
@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
StephaneLenclud@25
   500
*/
StephaneLenclud@25
   501
void MDM166AA::SetBrightness(int aBrightness)
StephaneLenclud@25
   502
    {
StephaneLenclud@25
   503
    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
StephaneLenclud@25
   504
        {
StephaneLenclud@25
   505
        //Brightness out of range.
StephaneLenclud@25
   506
        //Just ignore that request.
StephaneLenclud@25
   507
        return;
StephaneLenclud@25
   508
        }
StephaneLenclud@25
   509
StephaneLenclud@25
   510
    FutabaVfdReport report;
StephaneLenclud@25
   511
    report[0]=0x00; //Report ID
StephaneLenclud@25
   512
    report[1]=0x03; //Report size
StephaneLenclud@25
   513
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   514
    report[3]=0x40; //Command ID
StephaneLenclud@25
   515
    report[4]=aBrightness; //Brightness level
StephaneLenclud@25
   516
    Write(report);
StephaneLenclud@25
   517
    }
StephaneLenclud@25
   518
StephaneLenclud@25
   519
/**
StephaneLenclud@25
   520
*/
StephaneLenclud@25
   521
bool MDM166AA::IsPowerOn()
StephaneLenclud@25
   522
	{
StephaneLenclud@25
   523
	return iPowerOn;
StephaneLenclud@25
   524
	}
StephaneLenclud@25
   525
StephaneLenclud@25
   526
/**
StephaneLenclud@25
   527
*/
StephaneLenclud@25
   528
char* MDM166AA::DeviceId()
StephaneLenclud@25
   529
	{
StephaneLenclud@25
   530
	return iDeviceId;
StephaneLenclud@25
   531
	}
StephaneLenclud@25
   532
StephaneLenclud@25
   533
/**
StephaneLenclud@25
   534
*/
StephaneLenclud@25
   535
char* MDM166AA::FirmwareRevision()
StephaneLenclud@25
   536
	{
StephaneLenclud@25
   537
	return iFirmwareRevision;
StephaneLenclud@25
   538
	}
StephaneLenclud@25
   539
StephaneLenclud@25
   540
/**
StephaneLenclud@25
   541
*/
StephaneLenclud@25
   542
void MDM166AA::ShowClock()
StephaneLenclud@25
   543
	{
StephaneLenclud@25
   544
	SendCommandClockDisplay(EClockLarge,EClock24);
StephaneLenclud@25
   545
	SetClockSetting();
StephaneLenclud@25
   546
	}
StephaneLenclud@25
   547
StephaneLenclud@25
   548
/**
StephaneLenclud@25
   549
*/
StephaneLenclud@25
   550
void MDM166AA::HideClock()
StephaneLenclud@25
   551
	{
StephaneLenclud@25
   552
	//TODO: or reset
StephaneLenclud@25
   553
	Clear();
StephaneLenclud@25
   554
	}
StephaneLenclud@25
   555
StephaneLenclud@25
   556
StephaneLenclud@25
   557
/**
StephaneLenclud@25
   558
Clock setting 
StephaneLenclud@25
   559
[Code]1BH,00H,Pm,Ph 
StephaneLenclud@25
   560
[Function]Setting the clock data. The setting data is cleared, if the Reset command is input or power is turned off.
StephaneLenclud@25
   561
Ph = hour 
StephaneLenclud@25
   562
Pm = minute 
StephaneLenclud@25
   563
*/
StephaneLenclud@25
   564
void MDM166AA::SendCommandClockSetting(unsigned char aHour, unsigned char aMinute)
StephaneLenclud@25
   565
	{
StephaneLenclud@25
   566
	FutabaVfdReport report;
StephaneLenclud@25
   567
    report[0]=0x00; //Report ID
StephaneLenclud@25
   568
    report[1]=0x04; //Report size
StephaneLenclud@25
   569
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   570
    report[3]=0x00; //Command ID
StephaneLenclud@25
   571
StephaneLenclud@25
   572
	//Minutes and Hours needs to be in hexadecimal view
StephaneLenclud@25
   573
	//To get 21:59 you need to pass in 0x21:0x59
StephaneLenclud@25
   574
	//Weirdest format ever, I know 
StephaneLenclud@25
   575
	report[4]=(aMinute/10*16)+aMinute%10;
StephaneLenclud@25
   576
	report[5]=(aHour/10*16)+aHour%10;
StephaneLenclud@25
   577
StephaneLenclud@25
   578
    Write(report);
StephaneLenclud@25
   579
	}
StephaneLenclud@25
   580
StephaneLenclud@25
   581
StephaneLenclud@25
   582
/**
StephaneLenclud@25
   583
Set display clock settings according to local system time.
StephaneLenclud@25
   584
This needs to be redone whenever we open or turn on our display.
StephaneLenclud@25
   585
*/
StephaneLenclud@25
   586
void MDM166AA::SetClockSetting()
StephaneLenclud@25
   587
	{
StephaneLenclud@25
   588
	time_t rawtime;
StephaneLenclud@25
   589
	struct tm * timeinfo;
StephaneLenclud@25
   590
StephaneLenclud@25
   591
	time ( &rawtime );
StephaneLenclud@25
   592
	timeinfo = localtime ( &rawtime );
StephaneLenclud@25
   593
	//
StephaneLenclud@25
   594
	SendCommandClockSetting(timeinfo->tm_hour,timeinfo->tm_min);
StephaneLenclud@25
   595
	}
StephaneLenclud@25
   596
StephaneLenclud@25
   597
StephaneLenclud@25
   598
/**
StephaneLenclud@25
   599
Clock display
StephaneLenclud@25
   600
[Code] 1BH,Ps,aL,aH,Pf
StephaneLenclud@25
   601
[Function] Clock is displayed small or big.
StephaneLenclud@25
   602
*/
StephaneLenclud@25
   603
void MDM166AA::SendCommandClockDisplay(TClockSize aClockSize, TClockFormat aClockFormat)
StephaneLenclud@25
   604
	{
StephaneLenclud@25
   605
	FutabaVfdReport report;
StephaneLenclud@25
   606
    report[0]=0x00; //Report ID
StephaneLenclud@25
   607
    report[1]=0x03; //Report size
StephaneLenclud@25
   608
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   609
    report[3]=aClockSize; //
StephaneLenclud@25
   610
    report[4]=aClockFormat; //
StephaneLenclud@25
   611
StephaneLenclud@25
   612
    Write(report);
StephaneLenclud@25
   613
	}
StephaneLenclud@25
   614