ArduinoAlphanumeric

Annotated ArduinoAlphanumeric.cpp

4:03fdf31325df
2016-10-01 Paul Boddie Renamed the program source file.
paul@0 1
/*
paul@0 2
Interfacing the Arduino Duemilanove to the ElecFreaks alphanumeric display
paul@0 3
brick.
paul@0 4
paul@0 5
Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
paul@0 6
paul@0 7
This program is free software; you can redistribute it and/or modify it under
paul@0 8
the terms of the GNU General Public License as published by the Free Software
paul@0 9
Foundation; either version 3 of the License, or (at your option) any later
paul@0 10
version.
paul@0 11
paul@0 12
This program is distributed in the hope that it will be useful, but WITHOUT ANY
paul@0 13
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
paul@0 14
PARTICULAR PURPOSE.  See the GNU General Public License for more details.
paul@0 15
paul@0 16
You should have received a copy of the GNU General Public License along
paul@0 17
with this program.  If not, see <http://www.gnu.org/licenses/>.
paul@0 18
*/
paul@0 19
paul@0 20
#include <Wire.h>
paul@1 21
#include "shapes.h"
paul@1 22
paul@1 23
/* Multiplexer circuit definitions. */
paul@1 24
paul@1 25
const uint8_t MUX_S = 3,
paul@1 26
              D0 = 4, D1 = 5, D2 = 6, D3 = 7,
paul@1 27
              D4 = 8, D5 = 9, D6 = 10, D7 = 11;
paul@1 28
paul@1 29
const uint8_t datapins[8] = {D7, D6, D5, D4, D3, D2, D1, D0};
paul@1 30
paul@1 31
const uint16_t digits[] = {
paul@1 32
    OUTER_FRAME,
paul@1 33
    RIGHT_EDGE,
paul@1 34
    HORIZONTALS | UPPER_RIGHT_VERTICAL | LOWER_LEFT_VERTICAL,
paul@1 35
    HORIZONTALS | RIGHT_EDGE,
paul@1 36
    UPPER_LEFT_VERTICAL | MIDDLE_ELEMENTS | RIGHT_EDGE,
paul@1 37
    HORIZONTALS | UPPER_LEFT_VERTICAL | LOWER_RIGHT_VERTICAL,
paul@1 38
    HORIZONTALS | LEFT_EDGE | LOWER_RIGHT_VERTICAL,
paul@1 39
    TOP_EDGE | UPPER_RIGHT_DIAGONAL | LOWER_LEFT_DIAGONAL,
paul@1 40
    OUTER_FRAME | MIDDLE_ELEMENTS,
paul@1 41
    HORIZONTALS | RIGHT_EDGE | UPPER_LEFT_VERTICAL,
paul@1 42
    HORIZONTALS | RIGHT_EDGE | LOWER_LEFT_VERTICAL,
paul@1 43
    LEFT_EDGE | MIDDLE_ELEMENTS | BOTTOM_EDGE | LOWER_RIGHT_VERTICAL,
paul@1 44
    MIDDLE_ELEMENTS | BOTTOM_EDGE | LOWER_LEFT_VERTICAL,
paul@1 45
    RIGHT_EDGE | MIDDLE_ELEMENTS | BOTTOM_EDGE | LOWER_LEFT_VERTICAL,
paul@1 46
    HORIZONTALS | LEFT_EDGE | UPPER_RIGHT_VERTICAL,
paul@1 47
    LEFT_EDGE | TOP_EDGE | MIDDLE_ELEMENTS
paul@1 48
    };
paul@1 49
paul@1 50
/* Serial communications definitions. */
paul@0 51
paul@0 52
const int BUFSIZE = 17;
paul@0 53
char inbuffer[BUFSIZE];
paul@0 54
uint8_t nread = 0;
paul@0 55
paul@1 56
/* Display memory buffer. */
paul@1 57
paul@0 58
uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0};
paul@0 59
paul@1 60
/* Display operations. */
paul@1 61
paul@0 62
void enable_clock()
paul@0 63
{
paul@0 64
    Wire.beginTransmission(0x70);
paul@0 65
    Wire.write(0x21);
paul@0 66
    Wire.endTransmission();
paul@0 67
}
paul@0 68
paul@0 69
void set_row_output()
paul@0 70
{
paul@0 71
    Wire.beginTransmission(0x70);
paul@0 72
    Wire.write(0xa0);
paul@0 73
    Wire.endTransmission();
paul@0 74
}
paul@0 75
paul@0 76
void set_dimming()
paul@0 77
{
paul@0 78
    Wire.beginTransmission(0x70);
paul@0 79
    Wire.write(0xe3); // pulse_width = 4/16
paul@0 80
    Wire.endTransmission();
paul@0 81
}
paul@0 82
paul@0 83
void enable_display()
paul@0 84
{
paul@0 85
    Wire.beginTransmission(0x70);
paul@0 86
    Wire.write(0x81); // no blinking
paul@0 87
    Wire.endTransmission();
paul@0 88
}
paul@0 89
paul@0 90
void disable_display()
paul@0 91
{
paul@0 92
    Wire.beginTransmission(0x70);
paul@0 93
    Wire.write(0x80);
paul@0 94
    Wire.endTransmission();
paul@0 95
}
paul@0 96
paul@0 97
void init_alphanumeric()
paul@0 98
{
paul@0 99
    enable_clock();
paul@0 100
    set_row_output();
paul@0 101
    set_dimming();
paul@0 102
}
paul@0 103
paul@0 104
void write_digits(uint8_t data[], uint8_t len)
paul@0 105
{
paul@0 106
    uint8_t i;
paul@0 107
paul@0 108
    Wire.beginTransmission(0x70);
paul@0 109
    Wire.write(0x00); // address = 0
paul@0 110
paul@0 111
    for (i = 0; i < len; i++)
paul@0 112
    {
paul@0 113
        Wire.write(data[i]);
paul@0 114
    }
paul@0 115
paul@0 116
    Wire.endTransmission();
paul@0 117
}
paul@0 118
paul@0 119
/* User interface functions. */
paul@0 120
paul@0 121
uint8_t fromHex(char c)
paul@0 122
{
paul@0 123
    if ((c >= 48) && (c <= 57))
paul@0 124
        return c - 48;
paul@0 125
    if ((c >= 65) && (c <= 70))
paul@0 126
        return c - 65 + 10;
paul@0 127
    if ((c >= 97) && (c <= 102))
paul@0 128
        return c - 97 + 10;
paul@0 129
    return 0;
paul@0 130
}
paul@0 131
paul@0 132
void to_digits(char buffer[], uint8_t data[], uint8_t len)
paul@0 133
{
paul@0 134
    uint8_t i, j, p, high, low;
paul@0 135
paul@0 136
    for (i = 0, j = 0; j < len; j += 2)
paul@0 137
    {
paul@0 138
        for (p = 2; p > 0; p--, i += 2)
paul@0 139
        {
paul@0 140
            high = fromHex(buffer[i]);
paul@0 141
            if (high == 17)
paul@0 142
                return;
paul@0 143
            low = fromHex(buffer[i+1]);
paul@0 144
            if (low == 17)
paul@0 145
                return;
paul@0 146
paul@0 147
            /* Switch to little-endian. */
paul@0 148
paul@0 149
            data[j+p-1] = (high << 4) + low;
paul@0 150
        }
paul@0 151
    }
paul@0 152
}
paul@0 153
paul@1 154
/* Data sampling functions. */
paul@1 155
paul@1 156
uint8_t sample_value(uint8_t start, uint8_t end)
paul@1 157
{
paul@1 158
    uint8_t bit, value;
paul@1 159
paul@1 160
    value = 0;
paul@1 161
paul@1 162
    for (bit = start; bit < end; bit++)
paul@1 163
    {
paul@1 164
        value = (value << 1) | digitalRead(datapins[bit]);
paul@1 165
    }
paul@1 166
paul@1 167
    return value;
paul@1 168
}
paul@1 169
paul@1 170
void sample_data(uint8_t data[], uint8_t start, uint8_t end)
paul@1 171
{
paul@1 172
    uint8_t low, high, value;
paul@1 173
    uint16_t digit_value;
paul@1 174
paul@1 175
    value = sample_value(start, end);
paul@1 176
    digit_value = digits[value];
paul@1 177
paul@1 178
    /* Switch to little-endian. */
paul@1 179
paul@1 180
    data[0] = (uint8_t) (digit_value & 0xff);
paul@1 181
    data[1] = (uint8_t) (digit_value >> 8);
paul@1 182
}
paul@1 183
paul@1 184
void scan_inputs(uint8_t data[])
paul@1 185
{
paul@1 186
    digitalWrite(MUX_S, 0);
paul@1 187
    sample_data(&data[2], 4, 8); /* bits 3..0 */
paul@1 188
    sample_data(&data[0], 0, 4); /* bits 7..4 */
paul@1 189
paul@1 190
    digitalWrite(MUX_S, 1);
paul@1 191
    sample_data(&data[6], 4, 8);
paul@1 192
    sample_data(&data[4], 0, 4);
paul@1 193
}
paul@1 194
paul@1 195
/* Main functions. */
paul@1 196
paul@1 197
void client_setup()
paul@0 198
{
paul@0 199
    Wire.begin();
paul@0 200
    Serial.begin(115200);
paul@0 201
paul@0 202
    init_alphanumeric();
paul@0 203
    write_digits(data, 8);
paul@0 204
    enable_display();
paul@0 205
paul@0 206
    // Interface loop.
paul@0 207
paul@0 208
    Serial.println("?");
paul@0 209
}
paul@0 210
paul@1 211
void sample_setup()
paul@1 212
{
paul@1 213
    Wire.begin();
paul@1 214
paul@1 215
    pinMode(MUX_S, OUTPUT);
paul@1 216
    pinMode(D0, INPUT);
paul@1 217
    pinMode(D1, INPUT);
paul@1 218
    pinMode(D2, INPUT);
paul@1 219
    pinMode(D3, INPUT);
paul@1 220
    pinMode(D4, INPUT);
paul@1 221
    pinMode(D5, INPUT);
paul@1 222
    pinMode(D6, INPUT);
paul@1 223
    pinMode(D7, INPUT);
paul@1 224
paul@1 225
    init_alphanumeric();
paul@1 226
    write_digits(data, 8);
paul@1 227
    enable_display();
paul@1 228
}
paul@1 229
paul@1 230
void setup()
paul@1 231
{
paul@1 232
    /* client_setup(); */
paul@1 233
    sample_setup();
paul@1 234
}
paul@1 235
paul@1 236
void sample_loop()
paul@1 237
{
paul@1 238
    scan_inputs(data);
paul@1 239
    write_digits(data, 8);
paul@1 240
    delay(250);
paul@1 241
}
paul@1 242
paul@1 243
void client_loop()
paul@0 244
{
paul@0 245
    /* Read bytes, obtaining the number read excluding any newline terminator. */
paul@0 246
paul@0 247
    if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread))
paul@0 248
    {
paul@0 249
        /* Handle each command, waiting for the newline. */
paul@0 250
paul@0 251
        if (nread >= 16)
paul@0 252
        {
paul@0 253
            to_digits(inbuffer, data, 8);
paul@0 254
            write_digits(data, 8);
paul@0 255
            nread = 0;
paul@0 256
            Serial.println("OK");
paul@0 257
        }
paul@0 258
        else
paul@0 259
        {
paul@0 260
            Serial.print(nread);
paul@0 261
            Serial.println("...");
paul@0 262
        }
paul@0 263
paul@0 264
        Serial.flush();
paul@0 265
    }
paul@0 266
}
paul@0 267
paul@1 268
void loop()
paul@1 269
{
paul@1 270
    /* client_loop(); */
paul@1 271
    sample_loop();
paul@1 272
}
paul@1 273
paul@0 274
extern "C" void __cxa_pure_virtual(void) {
paul@0 275
    while(1);
paul@0 276
}
paul@0 277
paul@0 278
// tabstop=4 expandtab shiftwidth=4