1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/ArduinoAlphanumeric.cpp Sat Oct 01 22:31:07 2016 +0200
1.3 @@ -0,0 +1,278 @@
1.4 +/*
1.5 +Interfacing the Arduino Duemilanove to the ElecFreaks alphanumeric display
1.6 +brick.
1.7 +
1.8 +Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
1.9 +
1.10 +This program is free software; you can redistribute it and/or modify it under
1.11 +the terms of the GNU General Public License as published by the Free Software
1.12 +Foundation; either version 3 of the License, or (at your option) any later
1.13 +version.
1.14 +
1.15 +This program is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
1.17 +PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 +
1.19 +You should have received a copy of the GNU General Public License along
1.20 +with this program. If not, see <http://www.gnu.org/licenses/>.
1.21 +*/
1.22 +
1.23 +#include <Wire.h>
1.24 +#include "shapes.h"
1.25 +
1.26 +/* Multiplexer circuit definitions. */
1.27 +
1.28 +const uint8_t MUX_S = 3,
1.29 + D0 = 4, D1 = 5, D2 = 6, D3 = 7,
1.30 + D4 = 8, D5 = 9, D6 = 10, D7 = 11;
1.31 +
1.32 +const uint8_t datapins[8] = {D7, D6, D5, D4, D3, D2, D1, D0};
1.33 +
1.34 +const uint16_t digits[] = {
1.35 + OUTER_FRAME,
1.36 + RIGHT_EDGE,
1.37 + HORIZONTALS | UPPER_RIGHT_VERTICAL | LOWER_LEFT_VERTICAL,
1.38 + HORIZONTALS | RIGHT_EDGE,
1.39 + UPPER_LEFT_VERTICAL | MIDDLE_ELEMENTS | RIGHT_EDGE,
1.40 + HORIZONTALS | UPPER_LEFT_VERTICAL | LOWER_RIGHT_VERTICAL,
1.41 + HORIZONTALS | LEFT_EDGE | LOWER_RIGHT_VERTICAL,
1.42 + TOP_EDGE | UPPER_RIGHT_DIAGONAL | LOWER_LEFT_DIAGONAL,
1.43 + OUTER_FRAME | MIDDLE_ELEMENTS,
1.44 + HORIZONTALS | RIGHT_EDGE | UPPER_LEFT_VERTICAL,
1.45 + HORIZONTALS | RIGHT_EDGE | LOWER_LEFT_VERTICAL,
1.46 + LEFT_EDGE | MIDDLE_ELEMENTS | BOTTOM_EDGE | LOWER_RIGHT_VERTICAL,
1.47 + MIDDLE_ELEMENTS | BOTTOM_EDGE | LOWER_LEFT_VERTICAL,
1.48 + RIGHT_EDGE | MIDDLE_ELEMENTS | BOTTOM_EDGE | LOWER_LEFT_VERTICAL,
1.49 + HORIZONTALS | LEFT_EDGE | UPPER_RIGHT_VERTICAL,
1.50 + LEFT_EDGE | TOP_EDGE | MIDDLE_ELEMENTS
1.51 + };
1.52 +
1.53 +/* Serial communications definitions. */
1.54 +
1.55 +const int BUFSIZE = 17;
1.56 +char inbuffer[BUFSIZE];
1.57 +uint8_t nread = 0;
1.58 +
1.59 +/* Display memory buffer. */
1.60 +
1.61 +uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1.62 +
1.63 +/* Display operations. */
1.64 +
1.65 +void enable_clock()
1.66 +{
1.67 + Wire.beginTransmission(0x70);
1.68 + Wire.write(0x21);
1.69 + Wire.endTransmission();
1.70 +}
1.71 +
1.72 +void set_row_output()
1.73 +{
1.74 + Wire.beginTransmission(0x70);
1.75 + Wire.write(0xa0);
1.76 + Wire.endTransmission();
1.77 +}
1.78 +
1.79 +void set_dimming()
1.80 +{
1.81 + Wire.beginTransmission(0x70);
1.82 + Wire.write(0xe3); // pulse_width = 4/16
1.83 + Wire.endTransmission();
1.84 +}
1.85 +
1.86 +void enable_display()
1.87 +{
1.88 + Wire.beginTransmission(0x70);
1.89 + Wire.write(0x81); // no blinking
1.90 + Wire.endTransmission();
1.91 +}
1.92 +
1.93 +void disable_display()
1.94 +{
1.95 + Wire.beginTransmission(0x70);
1.96 + Wire.write(0x80);
1.97 + Wire.endTransmission();
1.98 +}
1.99 +
1.100 +void init_alphanumeric()
1.101 +{
1.102 + enable_clock();
1.103 + set_row_output();
1.104 + set_dimming();
1.105 +}
1.106 +
1.107 +void write_digits(uint8_t data[], uint8_t len)
1.108 +{
1.109 + uint8_t i;
1.110 +
1.111 + Wire.beginTransmission(0x70);
1.112 + Wire.write(0x00); // address = 0
1.113 +
1.114 + for (i = 0; i < len; i++)
1.115 + {
1.116 + Wire.write(data[i]);
1.117 + }
1.118 +
1.119 + Wire.endTransmission();
1.120 +}
1.121 +
1.122 +/* User interface functions. */
1.123 +
1.124 +uint8_t fromHex(char c)
1.125 +{
1.126 + if ((c >= 48) && (c <= 57))
1.127 + return c - 48;
1.128 + if ((c >= 65) && (c <= 70))
1.129 + return c - 65 + 10;
1.130 + if ((c >= 97) && (c <= 102))
1.131 + return c - 97 + 10;
1.132 + return 0;
1.133 +}
1.134 +
1.135 +void to_digits(char buffer[], uint8_t data[], uint8_t len)
1.136 +{
1.137 + uint8_t i, j, p, high, low;
1.138 +
1.139 + for (i = 0, j = 0; j < len; j += 2)
1.140 + {
1.141 + for (p = 2; p > 0; p--, i += 2)
1.142 + {
1.143 + high = fromHex(buffer[i]);
1.144 + if (high == 17)
1.145 + return;
1.146 + low = fromHex(buffer[i+1]);
1.147 + if (low == 17)
1.148 + return;
1.149 +
1.150 + /* Switch to little-endian. */
1.151 +
1.152 + data[j+p-1] = (high << 4) + low;
1.153 + }
1.154 + }
1.155 +}
1.156 +
1.157 +/* Data sampling functions. */
1.158 +
1.159 +uint8_t sample_value(uint8_t start, uint8_t end)
1.160 +{
1.161 + uint8_t bit, value;
1.162 +
1.163 + value = 0;
1.164 +
1.165 + for (bit = start; bit < end; bit++)
1.166 + {
1.167 + value = (value << 1) | digitalRead(datapins[bit]);
1.168 + }
1.169 +
1.170 + return value;
1.171 +}
1.172 +
1.173 +void sample_data(uint8_t data[], uint8_t start, uint8_t end)
1.174 +{
1.175 + uint8_t low, high, value;
1.176 + uint16_t digit_value;
1.177 +
1.178 + value = sample_value(start, end);
1.179 + digit_value = digits[value];
1.180 +
1.181 + /* Switch to little-endian. */
1.182 +
1.183 + data[0] = (uint8_t) (digit_value & 0xff);
1.184 + data[1] = (uint8_t) (digit_value >> 8);
1.185 +}
1.186 +
1.187 +void scan_inputs(uint8_t data[])
1.188 +{
1.189 + digitalWrite(MUX_S, 0);
1.190 + sample_data(&data[2], 4, 8); /* bits 3..0 */
1.191 + sample_data(&data[0], 0, 4); /* bits 7..4 */
1.192 +
1.193 + digitalWrite(MUX_S, 1);
1.194 + sample_data(&data[6], 4, 8);
1.195 + sample_data(&data[4], 0, 4);
1.196 +}
1.197 +
1.198 +/* Main functions. */
1.199 +
1.200 +void client_setup()
1.201 +{
1.202 + Wire.begin();
1.203 + Serial.begin(115200);
1.204 +
1.205 + init_alphanumeric();
1.206 + write_digits(data, 8);
1.207 + enable_display();
1.208 +
1.209 + // Interface loop.
1.210 +
1.211 + Serial.println("?");
1.212 +}
1.213 +
1.214 +void sample_setup()
1.215 +{
1.216 + Wire.begin();
1.217 +
1.218 + pinMode(MUX_S, OUTPUT);
1.219 + pinMode(D0, INPUT);
1.220 + pinMode(D1, INPUT);
1.221 + pinMode(D2, INPUT);
1.222 + pinMode(D3, INPUT);
1.223 + pinMode(D4, INPUT);
1.224 + pinMode(D5, INPUT);
1.225 + pinMode(D6, INPUT);
1.226 + pinMode(D7, INPUT);
1.227 +
1.228 + init_alphanumeric();
1.229 + write_digits(data, 8);
1.230 + enable_display();
1.231 +}
1.232 +
1.233 +void setup()
1.234 +{
1.235 + /* client_setup(); */
1.236 + sample_setup();
1.237 +}
1.238 +
1.239 +void sample_loop()
1.240 +{
1.241 + scan_inputs(data);
1.242 + write_digits(data, 8);
1.243 + delay(250);
1.244 +}
1.245 +
1.246 +void client_loop()
1.247 +{
1.248 + /* Read bytes, obtaining the number read excluding any newline terminator. */
1.249 +
1.250 + if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread))
1.251 + {
1.252 + /* Handle each command, waiting for the newline. */
1.253 +
1.254 + if (nread >= 16)
1.255 + {
1.256 + to_digits(inbuffer, data, 8);
1.257 + write_digits(data, 8);
1.258 + nread = 0;
1.259 + Serial.println("OK");
1.260 + }
1.261 + else
1.262 + {
1.263 + Serial.print(nread);
1.264 + Serial.println("...");
1.265 + }
1.266 +
1.267 + Serial.flush();
1.268 + }
1.269 +}
1.270 +
1.271 +void loop()
1.272 +{
1.273 + /* client_loop(); */
1.274 + sample_loop();
1.275 +}
1.276 +
1.277 +extern "C" void __cxa_pure_virtual(void) {
1.278 + while(1);
1.279 +}
1.280 +
1.281 +// tabstop=4 expandtab shiftwidth=4