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