FutabaMDM166AA.cpp
author StephaneLenclud
Thu, 05 Feb 2015 14:02:27 +0100
changeset 28 0d426caeaefe
parent 27 949be5444c57
child 29 9b44c6e1651c
permissions -rw-r--r--
MDM166AA: more accurate time setting and cleanup.
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
    iOffScreenMode(true),
StephaneLenclud@25
    24
    iFrameNext(NULL),
StephaneLenclud@25
    25
    iFrameCurrent(NULL),
StephaneLenclud@25
    26
    iFramePrevious(NULL),
StephaneLenclud@25
    27
    iFrameAlpha(NULL),
StephaneLenclud@25
    28
    iFrameBeta(NULL),
StephaneLenclud@28
    29
    iFrameGamma(NULL)
StephaneLenclud@25
    30
	{
StephaneLenclud@25
    31
	iDeviceId[0]=0;
StephaneLenclud@25
    32
	iFirmwareRevision[0]=0;
StephaneLenclud@25
    33
	//ResetBuffers();
StephaneLenclud@25
    34
	}
StephaneLenclud@25
    35
StephaneLenclud@25
    36
/**
StephaneLenclud@25
    37
*/
StephaneLenclud@25
    38
MDM166AA::~MDM166AA()
StephaneLenclud@25
    39
	{
StephaneLenclud@25
    40
    delete iFrameAlpha;
StephaneLenclud@25
    41
    iFrameAlpha=NULL;
StephaneLenclud@25
    42
    //
StephaneLenclud@25
    43
    delete iFrameBeta;
StephaneLenclud@25
    44
    iFrameBeta=NULL;
StephaneLenclud@25
    45
    //
StephaneLenclud@25
    46
    delete iFrameGamma;
StephaneLenclud@25
    47
    iFrameGamma=NULL;
StephaneLenclud@25
    48
    //
StephaneLenclud@25
    49
    iFrameNext=NULL;
StephaneLenclud@25
    50
    iFrameCurrent=NULL;
StephaneLenclud@25
    51
    iFramePrevious=NULL;
StephaneLenclud@25
    52
	}
StephaneLenclud@25
    53
StephaneLenclud@25
    54
/**
StephaneLenclud@25
    55
*/
StephaneLenclud@25
    56
int MDM166AA::Open()
StephaneLenclud@25
    57
	{
StephaneLenclud@25
    58
	int success = HidDevice::Open(KTargaVendorId,KFutabaProductIdMDM166AA,NULL);
StephaneLenclud@25
    59
	if (success)
StephaneLenclud@25
    60
		{
StephaneLenclud@25
    61
        //Allocate both frames
StephaneLenclud@25
    62
        delete iFrameAlpha;
StephaneLenclud@25
    63
        iFrameAlpha=NULL;
StephaneLenclud@25
    64
        iFrameAlpha=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
StephaneLenclud@25
    65
        //
StephaneLenclud@25
    66
        delete iFrameBeta;
StephaneLenclud@25
    67
        iFrameBeta=NULL;
StephaneLenclud@25
    68
        iFrameBeta=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
StephaneLenclud@25
    69
        //
StephaneLenclud@25
    70
        delete iFrameGamma;
StephaneLenclud@25
    71
        iFrameGamma=NULL;
StephaneLenclud@25
    72
        iFrameGamma=new BitArrayLow(KMDM166AAFrameBufferPixelCount);
StephaneLenclud@25
    73
        //
StephaneLenclud@25
    74
        iFrameNext=iFrameAlpha;
StephaneLenclud@25
    75
        iFrameCurrent=iFrameBeta;
StephaneLenclud@25
    76
        iFramePrevious=iFrameGamma;
StephaneLenclud@25
    77
        //
StephaneLenclud@25
    78
		SetNonBlocking(1);
StephaneLenclud@25
    79
		//
StephaneLenclud@28
    80
		SendCommandReset();
StephaneLenclud@25
    81
		//
StephaneLenclud@28
    82
		ShowClock();
StephaneLenclud@25
    83
StephaneLenclud@25
    84
		}
StephaneLenclud@25
    85
	return success;
StephaneLenclud@25
    86
	}
StephaneLenclud@25
    87
StephaneLenclud@25
    88
/**
StephaneLenclud@25
    89
*/
StephaneLenclud@25
    90
void MDM166AA::SetPixel(unsigned char aX, unsigned char aY, unsigned int aPixel)
StephaneLenclud@25
    91
	{
StephaneLenclud@25
    92
	//
StephaneLenclud@25
    93
	//int byteOffset=(aX*HeightInPixels()+aY)/8;
StephaneLenclud@25
    94
	//int bitOffset=(aX*HeightInPixels()+aY)%8;
StephaneLenclud@25
    95
    //iNextFrame[byteOffset] |= ( (aOn?0x01:0x00) << bitOffset );
StephaneLenclud@25
    96
StephaneLenclud@25
    97
	//Pixel is on if any of the non-alpha component is not null
StephaneLenclud@25
    98
	bool on = (aPixel&0x00FFFFFF)!=0x00000000;
StephaneLenclud@25
    99
StephaneLenclud@25
   100
    if (iOffScreenMode)
StephaneLenclud@25
   101
        {
StephaneLenclud@25
   102
        if (on)
StephaneLenclud@25
   103
            {
StephaneLenclud@25
   104
            iFrameNext->SetBit(aX*HeightInPixels()+aY);
StephaneLenclud@25
   105
            }
StephaneLenclud@25
   106
        else
StephaneLenclud@25
   107
            {
StephaneLenclud@25
   108
            iFrameNext->ClearBit(aX*HeightInPixels()+aY);
StephaneLenclud@25
   109
            }
StephaneLenclud@25
   110
        }
StephaneLenclud@25
   111
    else
StephaneLenclud@25
   112
        {
StephaneLenclud@25
   113
        //Just specify a one pixel block
StephaneLenclud@25
   114
        //TODO
StephaneLenclud@25
   115
        }
StephaneLenclud@25
   116
	}
StephaneLenclud@25
   117
StephaneLenclud@25
   118
/**
StephaneLenclud@25
   119
*/
StephaneLenclud@25
   120
/*
StephaneLenclud@25
   121
void MDM166AA::BitBlit(const BitArray& aBitmap, int aSrcWidth, int aSrcHeight, int aTargetX, int aTargetY) const
StephaneLenclud@25
   122
	{
StephaneLenclud@25
   123
	//TODO: amend loop values so that we don't keep on looping past our frame buffer dimensions.
StephaneLenclud@25
   124
	for (int i=0;i<aSrcWidth;i++)
StephaneLenclud@25
   125
		{
StephaneLenclud@25
   126
		for (int j=0;j<aSrcHeight;j++)
StephaneLenclud@25
   127
			{
StephaneLenclud@25
   128
            iFrameNext->SetBitValue((aTargetX+i)*HeightInPixels()+aTargetY+j,aBitmap[+i*aSrcHeight+j]);
StephaneLenclud@25
   129
			}
StephaneLenclud@25
   130
		}
StephaneLenclud@25
   131
	}
StephaneLenclud@25
   132
*/
StephaneLenclud@25
   133
StephaneLenclud@25
   134
/**
StephaneLenclud@25
   135
Clear our client side back buffer.
StephaneLenclud@25
   136
Call to SwapBuffers must follow to actually clear the display.
StephaneLenclud@25
   137
*/
StephaneLenclud@25
   138
void MDM166AA::Clear()
StephaneLenclud@25
   139
    {
StephaneLenclud@25
   140
	//That one also clear the symbols
StephaneLenclud@28
   141
    SetAllPixels(0x00);
StephaneLenclud@25
   142
    }
StephaneLenclud@25
   143
StephaneLenclud@25
   144
/**
StephaneLenclud@25
   145
Turn on all pixels.
StephaneLenclud@25
   146
Must be followed by a SwapBuffers call.
StephaneLenclud@25
   147
*/
StephaneLenclud@25
   148
void MDM166AA::Fill()
StephaneLenclud@25
   149
	{
StephaneLenclud@25
   150
	SetAllPixels(0xFF);
StephaneLenclud@25
   151
	}
StephaneLenclud@25
   152
StephaneLenclud@25
   153
/**
StephaneLenclud@25
   154
Set all pixels on our screen to the desired value.
StephaneLenclud@25
   155
This operation is performed off screen to avoid tearing.
StephaneLenclud@25
   156
@param 8 pixels pattern
StephaneLenclud@25
   157
*/
StephaneLenclud@25
   158
void MDM166AA::SetAllPixels(unsigned char aPattern)
StephaneLenclud@25
   159
	{
StephaneLenclud@25
   160
	//With a single buffer
StephaneLenclud@25
   161
	//unsigned char screen[2048]; //One screen worth of pixels
StephaneLenclud@25
   162
	//memset(screen,0xFF,sizeof(screen));
StephaneLenclud@25
   163
	//SetPixelBlock(0,0,63,sizeof(screen),screen);
StephaneLenclud@25
   164
StephaneLenclud@25
   165
StephaneLenclud@25
   166
    if (iOffScreenMode)
StephaneLenclud@25
   167
        {
StephaneLenclud@25
   168
        memset(iFrameNext->Ptr(),aPattern,FrameBufferSizeInBytes());
StephaneLenclud@25
   169
        }
StephaneLenclud@25
   170
    else
StephaneLenclud@25
   171
        {
StephaneLenclud@25
   172
        //Using pattern SetPixelBlock variant.
StephaneLenclud@25
   173
        //TODO
StephaneLenclud@25
   174
        }
StephaneLenclud@25
   175
	//
StephaneLenclud@25
   176
	}
StephaneLenclud@25
   177
StephaneLenclud@25
   178
StephaneLenclud@25
   179
StephaneLenclud@25
   180
StephaneLenclud@25
   181
StephaneLenclud@25
   182
StephaneLenclud@25
   183
/**
StephaneLenclud@25
   184
Whole display RAM areas including invisible area are filled with 00H data.
StephaneLenclud@25
   185
(Include the symbol)
StephaneLenclud@25
   186
SL: Though there is no invisible area with that device.
StephaneLenclud@25
   187
*/
StephaneLenclud@25
   188
void MDM166AA::SendCommandClear()
StephaneLenclud@25
   189
	{
StephaneLenclud@25
   190
    //Send Clear Display Command
StephaneLenclud@25
   191
	FutabaVfdReport report;
StephaneLenclud@25
   192
	report[0]=0x00; //Report ID
StephaneLenclud@25
   193
	report[1]=0x02; //Report length
StephaneLenclud@25
   194
	report[2]=0x1B; //Command ID
StephaneLenclud@25
   195
	report[3]=0x50; //Command ID
StephaneLenclud@25
   196
	Write(report);
StephaneLenclud@25
   197
	}
StephaneLenclud@25
   198
StephaneLenclud@25
   199
/**
StephaneLenclud@25
   200
Put our off screen buffer on screen.
StephaneLenclud@25
   201
On screen buffer goes off screen.
StephaneLenclud@25
   202
*/
StephaneLenclud@25
   203
void MDM166AA::SwapBuffers()
StephaneLenclud@25
   204
	{
StephaneLenclud@25
   205
	//Only perform buffer swapping if off screen mode is enabled
StephaneLenclud@25
   206
	if (OffScreenMode())
StephaneLenclud@25
   207
		{
StephaneLenclud@28
   208
		//Send next frame to our display RAM
StephaneLenclud@28
   209
		//We could attempt to implement a frame differencing algorithm much like we did for GP1212A01.
StephaneLenclud@28
   210
		//However we see little point doing that since we already run at above 20 FPS.
StephaneLenclud@27
   211
		SendCommandWriteGraphicData(FrameBufferSizeInBytes(),iFrameNext->Ptr());
StephaneLenclud@25
   212
StephaneLenclud@25
   213
        //Cycle through our frame buffers
StephaneLenclud@25
   214
        //We keep track of previous frame which is in fact our device back buffer.
StephaneLenclud@25
   215
        //We can then compare previous and next frame and send only the differences to our device.
StephaneLenclud@25
   216
        //This mechanism allows us to reduce traffic over our USB bus thus improving our frame rate from 14 FPS to 30 FPS.
StephaneLenclud@25
   217
        //Keep our previous frame pointer
StephaneLenclud@25
   218
        BitArrayLow* previousFrame=iFramePrevious;
StephaneLenclud@25
   219
        //Current frame becomes the previous one
StephaneLenclud@25
   220
        iFramePrevious = iFrameCurrent;
StephaneLenclud@25
   221
        //Next frame becomes the current one
StephaneLenclud@25
   222
        iFrameCurrent = iFrameNext;
StephaneLenclud@25
   223
        //Next frame is now our former previous
StephaneLenclud@25
   224
        iFrameNext = previousFrame;
StephaneLenclud@25
   225
		}
StephaneLenclud@25
   226
	}
StephaneLenclud@25
   227
StephaneLenclud@25
   228
StephaneLenclud@25
   229
//Define the edge of our pixel block
StephaneLenclud@25
   230
//Pixel blocks of 32x32 seems to run almost as fast as full screen update in worse case scenarii.
StephaneLenclud@25
   231
//Though I wonder if in some situations 16 could be better. Make this an attribute at some point if need be.
StephaneLenclud@25
   232
const int KPixelBlockEdge = 32;
StephaneLenclud@25
   233
const int KPixelBlockSizeInBits = KPixelBlockEdge*KPixelBlockEdge;
StephaneLenclud@25
   234
const int KPixelBlockSizeInBytes = KPixelBlockSizeInBits/8;
StephaneLenclud@25
   235
StephaneLenclud@25
   236
StephaneLenclud@25
   237
/**
StephaneLenclud@25
   238
*/
StephaneLenclud@25
   239
void MDM166AA::Request(TMiniDisplayRequest aRequest)
StephaneLenclud@25
   240
	{
StephaneLenclud@25
   241
	switch (aRequest)
StephaneLenclud@25
   242
		{
StephaneLenclud@25
   243
	case EMiniDisplayRequestDeviceId:
StephaneLenclud@25
   244
		RequestDeviceId();
StephaneLenclud@25
   245
		break;
StephaneLenclud@25
   246
	case EMiniDisplayRequestFirmwareRevision:
StephaneLenclud@25
   247
		RequestFirmwareRevision();
StephaneLenclud@25
   248
		break;
StephaneLenclud@25
   249
	case EMiniDisplayRequestPowerSupplyStatus:
StephaneLenclud@25
   250
		RequestPowerSupplyStatus();
StephaneLenclud@25
   251
		break;
StephaneLenclud@25
   252
	default:
StephaneLenclud@25
   253
		//Not supported
StephaneLenclud@25
   254
		break;
StephaneLenclud@25
   255
		};
StephaneLenclud@25
   256
	}
StephaneLenclud@25
   257
StephaneLenclud@25
   258
StephaneLenclud@25
   259
/**
StephaneLenclud@25
   260
*/
StephaneLenclud@25
   261
void MDM166AA::ResetBuffers()
StephaneLenclud@25
   262
	{
StephaneLenclud@25
   263
    //iNextFrame->ClearAll();
StephaneLenclud@25
   264
    //memset(iFrameAlpha,0x00,sizeof(iFrameAlpha));
StephaneLenclud@25
   265
	//memset(iFrameBeta,0x00,sizeof(iFrameBeta));
StephaneLenclud@25
   266
	}
StephaneLenclud@25
   267
StephaneLenclud@25
   268
/**
StephaneLenclud@25
   269
*/
StephaneLenclud@25
   270
void MDM166AA::RequestDeviceId()
StephaneLenclud@25
   271
    {
StephaneLenclud@25
   272
	//Not supported
StephaneLenclud@25
   273
    }
StephaneLenclud@25
   274
StephaneLenclud@25
   275
/**
StephaneLenclud@25
   276
*/
StephaneLenclud@25
   277
void MDM166AA::RequestFirmwareRevision()
StephaneLenclud@25
   278
    {
StephaneLenclud@28
   279
	//Not supported
StephaneLenclud@25
   280
    }
StephaneLenclud@25
   281
StephaneLenclud@25
   282
/**
StephaneLenclud@25
   283
*/
StephaneLenclud@25
   284
void MDM166AA::RequestPowerSupplyStatus()
StephaneLenclud@25
   285
    {
StephaneLenclud@25
   286
	//Not supported
StephaneLenclud@25
   287
    }
StephaneLenclud@25
   288
StephaneLenclud@25
   289
StephaneLenclud@25
   290
/**
StephaneLenclud@25
   291
This is for development purposes only.
StephaneLenclud@25
   292
Production application should stick to off-screen mode to avoid tearing.
StephaneLenclud@25
   293
*/
StephaneLenclud@25
   294
void MDM166AA::ToggleOffScreenMode()
StephaneLenclud@25
   295
	{
StephaneLenclud@25
   296
    SetOffScreenMode(!iOffScreenMode);
StephaneLenclud@25
   297
	}
StephaneLenclud@25
   298
StephaneLenclud@25
   299
/**
StephaneLenclud@25
   300
 * @brief MDM166AA::SetOffScreenMode
StephaneLenclud@25
   301
 * @param aOn
StephaneLenclud@25
   302
 * @return
StephaneLenclud@25
   303
 */
StephaneLenclud@25
   304
void MDM166AA::SetOffScreenMode(bool aOn)
StephaneLenclud@25
   305
    {
StephaneLenclud@25
   306
    if (aOn==iOffScreenMode)
StephaneLenclud@25
   307
    {
StephaneLenclud@25
   308
        //Nothing to do here
StephaneLenclud@25
   309
        return;
StephaneLenclud@25
   310
    }
StephaneLenclud@25
   311
StephaneLenclud@25
   312
    iOffScreenMode=aOn;
StephaneLenclud@25
   313
StephaneLenclud@25
   314
    //Clean up our buffers upon switching modes
StephaneLenclud@25
   315
    Clear();
StephaneLenclud@25
   316
    SwapBuffers();
StephaneLenclud@25
   317
    Clear();
StephaneLenclud@25
   318
    }
StephaneLenclud@25
   319
StephaneLenclud@25
   320
/**
StephaneLenclud@25
   321
Tries to complete our current request if we have one pending.
StephaneLenclud@25
   322
 */
StephaneLenclud@25
   323
TMiniDisplayRequest MDM166AA::AttemptRequestCompletion()
StephaneLenclud@25
   324
    {
StephaneLenclud@28
   325
	return EMiniDisplayRequestNone;
StephaneLenclud@25
   326
	}
StephaneLenclud@25
   327
StephaneLenclud@25
   328
StephaneLenclud@25
   329
/**
StephaneLenclud@25
   330
Set our screen brightness.
StephaneLenclud@25
   331
@param The desired brightness level. Must be between MinBrightness and MaxBrightness.
StephaneLenclud@25
   332
*/
StephaneLenclud@25
   333
void MDM166AA::SetBrightness(int aBrightness)
StephaneLenclud@25
   334
    {
StephaneLenclud@25
   335
    if (aBrightness<MinBrightness()||aBrightness>MaxBrightness())
StephaneLenclud@25
   336
        {
StephaneLenclud@25
   337
        //Brightness out of range.
StephaneLenclud@25
   338
        //Just ignore that request.
StephaneLenclud@25
   339
        return;
StephaneLenclud@25
   340
        }
StephaneLenclud@25
   341
StephaneLenclud@25
   342
    FutabaVfdReport report;
StephaneLenclud@25
   343
    report[0]=0x00; //Report ID
StephaneLenclud@25
   344
    report[1]=0x03; //Report size
StephaneLenclud@25
   345
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   346
    report[3]=0x40; //Command ID
StephaneLenclud@25
   347
    report[4]=aBrightness; //Brightness level
StephaneLenclud@25
   348
    Write(report);
StephaneLenclud@25
   349
    }
StephaneLenclud@25
   350
StephaneLenclud@25
   351
StephaneLenclud@25
   352
/**
StephaneLenclud@25
   353
*/
StephaneLenclud@25
   354
void MDM166AA::ShowClock()
StephaneLenclud@25
   355
	{
StephaneLenclud@28
   356
	SetClockData();
StephaneLenclud@25
   357
	SendCommandClockDisplay(EClockLarge,EClock24);
StephaneLenclud@25
   358
	}
StephaneLenclud@25
   359
StephaneLenclud@25
   360
/**
StephaneLenclud@25
   361
*/
StephaneLenclud@25
   362
void MDM166AA::HideClock()
StephaneLenclud@25
   363
	{
StephaneLenclud@25
   364
	//TODO: or reset
StephaneLenclud@25
   365
	Clear();
StephaneLenclud@25
   366
	}
StephaneLenclud@25
   367
StephaneLenclud@25
   368
StephaneLenclud@25
   369
/**
StephaneLenclud@25
   370
Clock setting 
StephaneLenclud@25
   371
[Code]1BH,00H,Pm,Ph 
StephaneLenclud@25
   372
[Function]Setting the clock data. The setting data is cleared, if the Reset command is input or power is turned off.
StephaneLenclud@25
   373
Ph = hour 
StephaneLenclud@25
   374
Pm = minute 
StephaneLenclud@25
   375
*/
StephaneLenclud@28
   376
void MDM166AA::SendCommandSetClockData(unsigned char aHour, unsigned char aMinute)
StephaneLenclud@25
   377
	{
StephaneLenclud@25
   378
	FutabaVfdReport report;
StephaneLenclud@25
   379
    report[0]=0x00; //Report ID
StephaneLenclud@25
   380
    report[1]=0x04; //Report size
StephaneLenclud@25
   381
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   382
    report[3]=0x00; //Command ID
StephaneLenclud@25
   383
StephaneLenclud@25
   384
	//Minutes and Hours needs to be in hexadecimal view
StephaneLenclud@25
   385
	//To get 21:59 you need to pass in 0x21:0x59
StephaneLenclud@25
   386
	//Weirdest format ever, I know 
StephaneLenclud@25
   387
	report[4]=(aMinute/10*16)+aMinute%10;
StephaneLenclud@25
   388
	report[5]=(aHour/10*16)+aHour%10;
StephaneLenclud@25
   389
StephaneLenclud@25
   390
    Write(report);
StephaneLenclud@25
   391
	}
StephaneLenclud@25
   392
StephaneLenclud@25
   393
StephaneLenclud@25
   394
/**
StephaneLenclud@28
   395
Set display clock data according to local system time.
StephaneLenclud@25
   396
This needs to be redone whenever we open or turn on our display.
StephaneLenclud@25
   397
*/
StephaneLenclud@28
   398
void MDM166AA::SetClockData()
StephaneLenclud@25
   399
	{
StephaneLenclud@25
   400
	time_t rawtime;
StephaneLenclud@25
   401
	struct tm * timeinfo;
StephaneLenclud@25
   402
StephaneLenclud@25
   403
	time ( &rawtime );
StephaneLenclud@25
   404
	timeinfo = localtime ( &rawtime );
StephaneLenclud@28
   405
	//Adjust minute as best as we can so that we have a 30 seconds offset at most rather a than a full minute.
StephaneLenclud@28
   406
	if (timeinfo->tm_sec>30)
StephaneLenclud@28
   407
		{
StephaneLenclud@28
   408
		//Use the next minute then
StephaneLenclud@28
   409
		timeinfo->tm_min++;
StephaneLenclud@28
   410
		if (timeinfo->tm_min==60)
StephaneLenclud@28
   411
			{
StephaneLenclud@28
   412
			//Use the next hour then
StephaneLenclud@28
   413
			timeinfo->tm_hour++;
StephaneLenclud@28
   414
			timeinfo->tm_min=0;
StephaneLenclud@28
   415
			if (timeinfo->tm_hour==24)
StephaneLenclud@28
   416
				{
StephaneLenclud@28
   417
				//Move to the next day then
StephaneLenclud@28
   418
				timeinfo->tm_hour=0;
StephaneLenclud@28
   419
				}
StephaneLenclud@28
   420
			}
StephaneLenclud@28
   421
		}
StephaneLenclud@28
   422
StephaneLenclud@28
   423
	//Send hours and minutes to our display
StephaneLenclud@28
   424
	SendCommandSetClockData(timeinfo->tm_hour,timeinfo->tm_min);
StephaneLenclud@25
   425
	}
StephaneLenclud@25
   426
StephaneLenclud@25
   427
StephaneLenclud@25
   428
/**
StephaneLenclud@25
   429
Clock display
StephaneLenclud@25
   430
[Code] 1BH,Ps,aL,aH,Pf
StephaneLenclud@25
   431
[Function] Clock is displayed small or big.
StephaneLenclud@25
   432
*/
StephaneLenclud@25
   433
void MDM166AA::SendCommandClockDisplay(TClockSize aClockSize, TClockFormat aClockFormat)
StephaneLenclud@25
   434
	{
StephaneLenclud@25
   435
	FutabaVfdReport report;
StephaneLenclud@25
   436
    report[0]=0x00; //Report ID
StephaneLenclud@25
   437
    report[1]=0x03; //Report size
StephaneLenclud@25
   438
    report[2]=0x1B; //Command ID
StephaneLenclud@25
   439
    report[3]=aClockSize; //
StephaneLenclud@25
   440
    report[4]=aClockFormat; //
StephaneLenclud@25
   441
StephaneLenclud@25
   442
    Write(report);
StephaneLenclud@25
   443
	}
StephaneLenclud@25
   444
StephaneLenclud@27
   445
StephaneLenclud@27
   446
/**
StephaneLenclud@27
   447
Display RAM filled with 00H.
StephaneLenclud@27
   448
Address Counter is set by 00H.
StephaneLenclud@27
   449
Dimming is set to 50%.
StephaneLenclud@27
   450
*/
StephaneLenclud@27
   451
void MDM166AA::SendCommandReset()
StephaneLenclud@27
   452
	{
StephaneLenclud@27
   453
	FutabaVfdReport report;
StephaneLenclud@27
   454
	report[0]=0x00; //Report ID
StephaneLenclud@27
   455
	report[1]=0x01; //Report length.
StephaneLenclud@27
   456
	report[2]=0x1F; //Command ID
StephaneLenclud@27
   457
	Write(report);
StephaneLenclud@27
   458
	//Wait until reset is done. Is that needed?
StephaneLenclud@27
   459
	//sleep(2000);
StephaneLenclud@27
   460
	}
StephaneLenclud@27
   461
StephaneLenclud@27
   462
StephaneLenclud@27
   463
/**
StephaneLenclud@27
   464
Set Address Counter (AC) values: 1BH + 60H + xxH
StephaneLenclud@27
   465
xxH: 00 ~ BFH
StephaneLenclud@27
   466
AC value represents the start address for graphic data.
StephaneLenclud@27
   467
There are 192 bytes as display RAM. It can be set on anywhere even if AC value is not visible area.
StephaneLenclud@27
   468
The default value is 00H.
StephaneLenclud@27
   469
Default: 00H
StephaneLenclud@27
   470
When clock is displayed, AC value is set 00H.
StephaneLenclud@27
   471
*/
StephaneLenclud@27
   472
void MDM166AA::SendCommandSetAddressCounter(unsigned char aAddressCounter)
StephaneLenclud@27
   473
	{
StephaneLenclud@27
   474
	FutabaVfdReport report;
StephaneLenclud@27
   475
	report[0]=0x00; //Report ID
StephaneLenclud@27
   476
	report[1]=0x03; //Report length.
StephaneLenclud@27
   477
	report[2]=0x1B; //Command ID
StephaneLenclud@27
   478
	report[3]=0x60; //Command ID
StephaneLenclud@27
   479
	report[4]=aAddressCounter;
StephaneLenclud@27
   480
	Write(report);
StephaneLenclud@27
   481
	}
StephaneLenclud@27
   482
StephaneLenclud@27
   483
StephaneLenclud@27
   484
/**
StephaneLenclud@27
   485
Set the defined pixel block to the given value.
StephaneLenclud@27
   486
StephaneLenclud@27
   487
@param The size of our pixel data. Number of pixels divided by 8.
StephaneLenclud@27
   488
@param Pointer to our pixel data.
StephaneLenclud@27
   489
*/
StephaneLenclud@27
   490
void MDM166AA::SendCommandWriteGraphicData(int aSize, unsigned char* aPixels)
StephaneLenclud@27
   491
    {
StephaneLenclud@27
   492
	//TODO: Remove that at some point
StephaneLenclud@27
   493
	SendCommandSetAddressCounter(0);
StephaneLenclud@27
   494
StephaneLenclud@27
   495
	const int KMaxPixelBytes=48;
StephaneLenclud@27
   496
	const int KHeaderSize=3;
StephaneLenclud@27
   497
	
StephaneLenclud@27
   498
	int remainingSize=aSize;
StephaneLenclud@27
   499
	int sizeWritten=0;
StephaneLenclud@27
   500
StephaneLenclud@27
   501
	while (remainingSize>0)
StephaneLenclud@27
   502
		{
StephaneLenclud@27
   503
		//Only send a maximum of 48 bytes worth of pixels per report
StephaneLenclud@27
   504
		const int KPixelDataSize=(remainingSize<=KMaxPixelBytes?remainingSize:KMaxPixelBytes);
StephaneLenclud@27
   505
StephaneLenclud@27
   506
		FutabaVfdReport report;
StephaneLenclud@27
   507
		report[0]=0x00; //Report ID
StephaneLenclud@27
   508
		report[1]=KPixelDataSize+KHeaderSize; //Report length. +3 is for our header first 3 bytes.
StephaneLenclud@27
   509
		report[2]=0x1B; //Command ID
StephaneLenclud@27
   510
		report[3]=0x70; //Command ID
StephaneLenclud@27
   511
		report[4]=KPixelDataSize; //Size of pixel data in bytes		
StephaneLenclud@27
   512
		memcpy(report.Buffer()+5, aPixels+sizeWritten, KPixelDataSize);
StephaneLenclud@27
   513
		Write(report);
StephaneLenclud@27
   514
		//Advance
StephaneLenclud@27
   515
		sizeWritten+=KPixelDataSize;
StephaneLenclud@27
   516
		remainingSize-=KPixelDataSize;
StephaneLenclud@27
   517
		}
StephaneLenclud@27
   518
    }