graphlcd-base/glcddrivers/avrctl.c
author root@rika
Wed, 06 Feb 2008 17:32:55 +0000
changeset 4 df6a40031aa5
child 10 9798f65f2f35
permissions -rw-r--r--
added graphlcd-base
root@4
     1
/*
root@4
     2
 * GraphLCD driver library
root@4
     3
 *
root@4
     4
 * avrctl.c  -  AVR controlled LCD driver class
root@4
     5
 *
root@4
     6
 * This file is released under the GNU General Public License. Refer
root@4
     7
 * to the COPYING file distributed with this package.
root@4
     8
 *
root@4
     9
 * (c) 2005 Andreas Regel <andreas.regel AT powarman.de>
root@4
    10
 */
root@4
    11
root@4
    12
#include <stdint.h>
root@4
    13
#include <syslog.h>
root@4
    14
root@4
    15
#include "common.h"
root@4
    16
#include "config.h"
root@4
    17
#include "port.h"
root@4
    18
#include "avrctl.h"
root@4
    19
root@4
    20
root@4
    21
namespace GLCD
root@4
    22
{
root@4
    23
root@4
    24
/* command header:
root@4
    25
**  8 bits  sync byte (0xAA for sent commands, 0x55 for received commands)
root@4
    26
**  8 bits  command id
root@4
    27
** 16 bits  command length (excluding header)
root@4
    28
*/
root@4
    29
const unsigned char CMD_HDR_SYNC    = 0;
root@4
    30
const unsigned char CMD_HDR_COMMAND = 1;
root@4
    31
const unsigned char CMD_HDR_LENGTH  = 2;
root@4
    32
const unsigned char CMD_DATA_START  = 4;
root@4
    33
root@4
    34
const unsigned char CMD_SYNC_SEND = 0xAA;
root@4
    35
const unsigned char CMD_SYNC_RECV = 0x55;
root@4
    36
root@4
    37
const unsigned char CMD_SYS_SYNC = 0x00;
root@4
    38
const unsigned char CMD_SYS_ACK  = 0x01;
root@4
    39
root@4
    40
const unsigned char CMD_DISP_CLEAR_SCREEN   = 0x10;
root@4
    41
const unsigned char CMD_DISP_SWITCH_SCREEN  = 0x11;
root@4
    42
const unsigned char CMD_DISP_SET_BRIGHTNESS = 0x12;
root@4
    43
const unsigned char CMD_DISP_SET_COL_DATA   = 0x13;
root@4
    44
const unsigned char CMD_DISP_SET_ROW_DATA   = 0x14;
root@4
    45
const unsigned char CMD_DISP_UPDATE         = 0x15;
root@4
    46
root@4
    47
const int kBufferWidth  = 256;
root@4
    48
const int kBufferHeight = 128;
root@4
    49
root@4
    50
root@4
    51
cDriverAvrCtl::cDriverAvrCtl(cDriverConfig * config)
root@4
    52
:   config(config)
root@4
    53
{
root@4
    54
    oldConfig = new cDriverConfig(*config);
root@4
    55
root@4
    56
    port = new cSerialPort();
root@4
    57
root@4
    58
    //width = config->width;
root@4
    59
    //height = config->height;
root@4
    60
    refreshCounter = 0;
root@4
    61
}
root@4
    62
root@4
    63
cDriverAvrCtl::~cDriverAvrCtl()
root@4
    64
{
root@4
    65
    delete port;
root@4
    66
    delete oldConfig;
root@4
    67
}
root@4
    68
root@4
    69
int cDriverAvrCtl::Init()
root@4
    70
{
root@4
    71
    int x;
root@4
    72
root@4
    73
    width = config->width;
root@4
    74
    if (width <= 0)
root@4
    75
        width = 256;
root@4
    76
    height = config->height;
root@4
    77
    if (height <= 0)
root@4
    78
        height = 128;
root@4
    79
root@4
    80
    for (unsigned int i = 0; i < config->options.size(); i++)
root@4
    81
    {
root@4
    82
        if (config->options[i].name == "")
root@4
    83
        {
root@4
    84
        }
root@4
    85
    }
root@4
    86
root@4
    87
    // setup lcd array (wanted state)
root@4
    88
    newLCD = new unsigned char*[kBufferWidth];
root@4
    89
    if (newLCD)
root@4
    90
    {
root@4
    91
        for (x = 0; x < kBufferWidth; x++)
root@4
    92
        {
root@4
    93
            newLCD[x] = new unsigned char[(kBufferHeight + 7) / 8];
root@4
    94
            memset(newLCD[x], 0, (kBufferHeight + 7) / 8);
root@4
    95
        }
root@4
    96
    }
root@4
    97
    // setup lcd array (current state)
root@4
    98
    oldLCD = new unsigned char*[kBufferWidth];
root@4
    99
    if (oldLCD)
root@4
   100
    {
root@4
   101
        for (x = 0; x < kBufferWidth; x++)
root@4
   102
        {
root@4
   103
            oldLCD[x] = new unsigned char[(kBufferHeight + 7) / 8];
root@4
   104
            memset(oldLCD[x], 0, (kBufferHeight + 7) / 8);
root@4
   105
        }
root@4
   106
    }
root@4
   107
root@4
   108
    if (config->device == "")
root@4
   109
    {
root@4
   110
        return -1;
root@4
   111
    }
root@4
   112
    if (port->Open(config->device.c_str()) != 0)
root@4
   113
        return -1;
root@4
   114
root@4
   115
    *oldConfig = *config;
root@4
   116
root@4
   117
    // clear display
root@4
   118
    Clear();
root@4
   119
root@4
   120
    syslog(LOG_INFO, "%s: AvrCtl initialized.\n", config->name.c_str());
root@4
   121
    return 0;
root@4
   122
}
root@4
   123
root@4
   124
int cDriverAvrCtl::DeInit()
root@4
   125
{
root@4
   126
    int x;
root@4
   127
    // free lcd array (wanted state)
root@4
   128
    if (newLCD)
root@4
   129
    {
root@4
   130
        for (x = 0; x < kBufferWidth; x++)
root@4
   131
        {
root@4
   132
            delete[] newLCD[x];
root@4
   133
        }
root@4
   134
        delete[] newLCD;
root@4
   135
    }
root@4
   136
    // free lcd array (current state)
root@4
   137
    if (oldLCD)
root@4
   138
    {
root@4
   139
        for (x = 0; x < kBufferWidth; x++)
root@4
   140
        {
root@4
   141
            delete[] oldLCD[x];
root@4
   142
        }
root@4
   143
        delete[] oldLCD;
root@4
   144
    }
root@4
   145
root@4
   146
    if (port->Close() != 0)
root@4
   147
        return -1;
root@4
   148
    return 0;
root@4
   149
}
root@4
   150
root@4
   151
int cDriverAvrCtl::CheckSetup()
root@4
   152
{
root@4
   153
    if (config->device != oldConfig->device ||
root@4
   154
        config->width != oldConfig->width ||
root@4
   155
        config->height != oldConfig->height)
root@4
   156
    {
root@4
   157
        DeInit();
root@4
   158
        Init();
root@4
   159
        return 0;
root@4
   160
    }
root@4
   161
root@4
   162
    if (config->upsideDown != oldConfig->upsideDown ||
root@4
   163
        config->invert != oldConfig->invert)
root@4
   164
    {
root@4
   165
        oldConfig->upsideDown = config->upsideDown;
root@4
   166
        oldConfig->invert = config->invert;
root@4
   167
        return 1;
root@4
   168
    }
root@4
   169
    return 0;
root@4
   170
}
root@4
   171
root@4
   172
void cDriverAvrCtl::Clear()
root@4
   173
{
root@4
   174
    for (int x = 0; x < kBufferWidth; x++)
root@4
   175
        memset(newLCD[x], 0, (kBufferHeight + 7) / 8);
root@4
   176
}
root@4
   177
root@4
   178
void cDriverAvrCtl::Set8Pixels(int x, int y, unsigned char data)
root@4
   179
{
root@4
   180
    if (x >= width || y >= height)
root@4
   181
        return;
root@4
   182
root@4
   183
    if (!config->upsideDown)
root@4
   184
    {
root@4
   185
        int offset = 7 - (y % 8);
root@4
   186
        for (int i = 0; i < 8; i++)
root@4
   187
        {
root@4
   188
            newLCD[x + i][y / 8] |= ((data >> (7 - i)) << offset) & (1 << offset);
root@4
   189
        }
root@4
   190
    }
root@4
   191
    else
root@4
   192
    {
root@4
   193
        x = width - 1 - x;
root@4
   194
        y = height - 1 - y;
root@4
   195
        int offset = 7 - (y % 8);
root@4
   196
        for (int i = 0; i < 8; i++)
root@4
   197
        {
root@4
   198
            newLCD[x - i][y / 8] |= ((data >> (7 - i)) << offset) & (1 << offset);
root@4
   199
        }
root@4
   200
    }
root@4
   201
}
root@4
   202
root@4
   203
void cDriverAvrCtl::Refresh(bool refreshAll)
root@4
   204
{
root@4
   205
    int x;
root@4
   206
    int y;
root@4
   207
    int i;
root@4
   208
    int num = kBufferWidth / 2;
root@4
   209
    unsigned char data[16*num];
root@4
   210
root@4
   211
    if (CheckSetup() == 1)
root@4
   212
        refreshAll = true;
root@4
   213
root@4
   214
    if (config->refreshDisplay > 0)
root@4
   215
    {
root@4
   216
        refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
root@4
   217
        if (!refreshAll && !refreshCounter)
root@4
   218
            refreshAll = true;
root@4
   219
    }
root@4
   220
root@4
   221
    refreshAll = true;
root@4
   222
    if (refreshAll)
root@4
   223
    {
root@4
   224
        for (x = 0; x < kBufferWidth; x += num)
root@4
   225
        {
root@4
   226
            for (i = 0; i < num; i++)
root@4
   227
            {
root@4
   228
                for (y = 0; y < (kBufferHeight + 7) / 8; y++)
root@4
   229
                {
root@4
   230
                    data[i * ((kBufferHeight + 7) / 8) + y] = (newLCD[x + i][y]) ^ (config->invert ? 0xff : 0x00);
root@4
   231
                }
root@4
   232
                memcpy(oldLCD[x + i], newLCD[x + i], (kBufferHeight + 7) / 8);
root@4
   233
            }
root@4
   234
            CmdDispSetColData(x, 0, 16 * num, data);
root@4
   235
        }
root@4
   236
        CmdDispUpdate();
root@4
   237
        CmdDispSwitchScreen();
root@4
   238
        // and reset RefreshCounter
root@4
   239
        refreshCounter = 0;
root@4
   240
    }
root@4
   241
    else
root@4
   242
    {
root@4
   243
        // draw only the changed bytes
root@4
   244
    }
root@4
   245
}
root@4
   246
root@4
   247
void cDriverAvrCtl::SetBrightness(unsigned int percent)
root@4
   248
{
root@4
   249
  CmdDispSetBrightness(percent);
root@4
   250
}
root@4
   251
root@4
   252
int cDriverAvrCtl::WaitForAck(void)
root@4
   253
{
root@4
   254
    uint8_t cmd[4];
root@4
   255
    int len;
root@4
   256
    int timeout = 10000;
root@4
   257
root@4
   258
    len = 0;
root@4
   259
    while (len < 4 && timeout > 0)
root@4
   260
    {
root@4
   261
        len += port->ReadData(&cmd[len]);
root@4
   262
        timeout--;
root@4
   263
    }
root@4
   264
    if (timeout == 0)
root@4
   265
        return 0;
root@4
   266
    return 1;
root@4
   267
}
root@4
   268
root@4
   269
void cDriverAvrCtl::CmdSysSync(void)
root@4
   270
{
root@4
   271
    uint8_t cmd[4];
root@4
   272
root@4
   273
    cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
root@4
   274
    cmd[CMD_HDR_COMMAND] = CMD_SYS_SYNC;
root@4
   275
    cmd[CMD_HDR_LENGTH] = 0;
root@4
   276
    cmd[CMD_HDR_LENGTH+1] = 0;
root@4
   277
root@4
   278
    port->WriteData(cmd, 4);
root@4
   279
    WaitForAck();
root@4
   280
}
root@4
   281
root@4
   282
void cDriverAvrCtl::CmdDispClearScreen(void)
root@4
   283
{
root@4
   284
    uint8_t cmd[4];
root@4
   285
root@4
   286
    cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
root@4
   287
    cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN;
root@4
   288
    cmd[CMD_HDR_LENGTH] = 0;
root@4
   289
    cmd[CMD_HDR_LENGTH+1] = 0;
root@4
   290
root@4
   291
    port->WriteData(cmd, 4);
root@4
   292
    WaitForAck();
root@4
   293
}
root@4
   294
root@4
   295
void cDriverAvrCtl::CmdDispSwitchScreen(void)
root@4
   296
{
root@4
   297
    uint8_t cmd[4];
root@4
   298
root@4
   299
    cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
root@4
   300
    cmd[CMD_HDR_COMMAND] = CMD_DISP_SWITCH_SCREEN;
root@4
   301
    cmd[CMD_HDR_LENGTH] = 0;
root@4
   302
    cmd[CMD_HDR_LENGTH+1] = 0;
root@4
   303
root@4
   304
    port->WriteData(cmd, 4);
root@4
   305
    WaitForAck();
root@4
   306
}
root@4
   307
root@4
   308
void cDriverAvrCtl::CmdDispSetBrightness(uint8_t percent)
root@4
   309
{
root@4
   310
    uint8_t cmd[5];
root@4
   311
root@4
   312
    cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
root@4
   313
    cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_BRIGHTNESS;
root@4
   314
    cmd[CMD_HDR_LENGTH] = 0;
root@4
   315
    cmd[CMD_HDR_LENGTH+1] = 1;
root@4
   316
    cmd[CMD_DATA_START] = percent;
root@4
   317
root@4
   318
    port->WriteData(cmd, 5);
root@4
   319
    WaitForAck();
root@4
   320
}
root@4
   321
root@4
   322
void cDriverAvrCtl::CmdDispSetColData(uint16_t column, uint16_t offset, uint16_t length, uint8_t * data)
root@4
   323
{
root@4
   324
    uint8_t cmd[2560];
root@4
   325
root@4
   326
    cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
root@4
   327
    cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_COL_DATA;
root@4
   328
    cmd[CMD_HDR_LENGTH] = (length + 6) >> 8;
root@4
   329
    cmd[CMD_HDR_LENGTH+1] = (length + 6);
root@4
   330
    cmd[CMD_DATA_START] = column >> 8;
root@4
   331
    cmd[CMD_DATA_START+1] = column;
root@4
   332
    cmd[CMD_DATA_START+2] = offset >> 8;
root@4
   333
    cmd[CMD_DATA_START+3] = offset;
root@4
   334
    cmd[CMD_DATA_START+4] = length >> 8;
root@4
   335
    cmd[CMD_DATA_START+5] = length;
root@4
   336
    memcpy(&cmd[CMD_DATA_START+6], data, length);
root@4
   337
root@4
   338
    port->WriteData(cmd, length+10);
root@4
   339
    WaitForAck();
root@4
   340
}
root@4
   341
root@4
   342
void cDriverAvrCtl::CmdDispUpdate(void)
root@4
   343
{
root@4
   344
    uint8_t cmd[4];
root@4
   345
root@4
   346
    cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
root@4
   347
    cmd[CMD_HDR_COMMAND] = CMD_DISP_UPDATE;
root@4
   348
    cmd[CMD_HDR_LENGTH] = 0;
root@4
   349
    cmd[CMD_HDR_LENGTH+1] = 0;
root@4
   350
root@4
   351
    port->WriteData(cmd, 4);
root@4
   352
    WaitForAck();
root@4
   353
}
root@4
   354
root@4
   355
}