sketch.ino (6240B)
1#include <LCD_I2C.h> 2 3#define ARRSIZE(x) (sizeof(x)/sizeof((x)[0])) 4#define BITAT(x) (1 << (x)) 5 6#define BTN_COUNT 18 7#define FEEL_DELAY 5 8#define BLINK_LED 17 9 10enum { DISABLED, KEY, FUNC }; 11 12enum { 13 FUNC_NONE, 14 FUNC_BS, 15 FUNC_ENTER, 16 FUNC_LEFT, 17 FUNC_RIGHT, 18 FUNC_HOME, 19 FUNC_DEL 20}; 21 22enum { 23 R1C1, R1C2, R1C3, R1C4, 24 R2C1, R2C2, R2C3, R2C4, 25 R3C1, R3C2, R3C3, R3C4, 26 R4C1, R4C2, R4C3, 27 R5C12, R5C3, R45C4 28}; 29 30enum { 31 NUMLOCK = 1 << 0, 32}; 33 34struct keycfg { 35 uint8_t type; 36 char c; 37}; 38 39const char *bnames[BTN_COUNT] = { 40 "R1C1", "R1C2", "R1C3", "R1C4", 41 "R2C1", "R2C2", "R2C3", "R2C4", 42 "R3C1", "R3C2", "R3C3", "R3C4", 43 "R4C1", "R4C2", "R4C3", 44 "R5C12", "R5C3", "R45C4" 45}; 46 47const uint8_t pulsepins[] = { A2, A3, 9, A1, 8, A0 }; 48const uint8_t sensepins[] = { 6, 14, 4, 5, 7, 16 }; 49const uint8_t debugswitch = 10; 50 51const uint8_t senselut[][6][2] = { 52 { {14, R2C1 }, {16, R3C1}, { 4, R4C1} }, 53 { { 6, R1C2 }, {14, R2C2}, {16, R3C2}, {4, R4C2}, {5, R5C12} }, 54 { { 6, R1C3 }, {14, R2C3}, {16, R3C3}, {4, R4C3}, {5, R5C3}, {7, R2C4} }, 55 { {16, R1C4 } }, 56 { { 6, R1C1 } }, 57 { { 4, R45C4}, {14, R3C4} } 58}; 59 60const uint8_t modkeys[] = { R1C1 }; 61 62const struct keycfg base_layer[BTN_COUNT] = { 63 [R1C1] = { DISABLED }, 64 [R1C2] = { KEY, '/' }, 65 [R1C3] = { KEY, '*' }, 66 [R1C4] = { FUNC, FUNC_BS }, 67 [R2C1] = { KEY, '7' }, 68 [R2C2] = { KEY, '8' }, 69 [R2C3] = { KEY, '9' }, 70 [R2C4] = { KEY, '-' }, 71 [R3C1] = { KEY, '4' }, 72 [R3C2] = { KEY, '5' }, 73 [R3C3] = { KEY, '6' }, 74 [R3C4] = { KEY, '+' }, 75 [R4C1] = { KEY, '1' }, 76 [R4C2] = { KEY, '2' }, 77 [R4C3] = { KEY, '3' }, 78 [R5C12] = { KEY, '0' }, 79 [R5C3] = { KEY, '.' }, 80 [R45C4] = { FUNC, FUNC_ENTER } 81}; 82 83const struct keycfg numlock_layer[BTN_COUNT] = { 84 [R1C1] = { DISABLED }, 85 [R1C2] = { KEY, '/' }, 86 [R1C3] = { KEY, '*' }, 87 [R1C4] = { FUNC, FUNC_BS }, 88 [R2C1] = { FUNC, FUNC_HOME }, 89 [R2C2] = { DISABLED }, 90 [R2C3] = { DISABLED }, 91 [R2C4] = { KEY, '-' }, 92 [R3C1] = { FUNC, FUNC_LEFT }, 93 [R3C2] = { DISABLED }, 94 [R3C3] = { FUNC, FUNC_RIGHT }, 95 [R3C4] = { KEY, '+' }, 96 [R4C1] = { DISABLED }, 97 [R4C2] = { DISABLED }, 98 [R4C3] = { DISABLED }, 99 [R5C12] = { DISABLED }, 100 [R5C3] = { FUNC, FUNC_DEL }, 101 [R45C4] = { FUNC, FUNC_ENTER } 102}; 103 104const struct keycfg *layers[1 << ARRSIZE(modkeys)] = { 105 [0] = base_layer, 106 [NUMLOCK] = numlock_layer 107}; 108 109char pin[9] = { 0 }; 110 111char linebuf[256] = { 0 }; 112 113int16_t inputpos = 0; 114char inputbuf[17] = { 0 }; 115char outputbuf[17] = { 0 }; 116 117int debugmode = 0; 118 119int pbstates[BTN_COUNT] = { 0 }; 120int bstates[BTN_COUNT] = { 0 }; 121 122LCD_I2C lcd(0x27, 16, 2); 123 124void 125lcd_refresh(void) 126{ 127 lcd.clear(); 128 lcd.noCursor(); 129 lcd.setCursor(0, 0); 130 lcd.print(inputbuf); 131 lcd.setCursor(0, 1); 132 lcd.print(outputbuf); 133 lcd.setCursor(inputpos, 0); 134 lcd.cursor(); 135} 136 137void 138call_func(char c) 139{ 140 switch (c) { 141 case FUNC_BS: 142 input_del(); 143 break; 144 case FUNC_ENTER: 145 input_enter(); 146 break; 147 case FUNC_LEFT: 148 inputpos--; 149 lcd_refresh(); 150 break; 151 case FUNC_RIGHT: 152 inputpos++; 153 lcd_refresh(); 154 break; 155 case FUNC_HOME: 156 inputpos = 0; 157 lcd_refresh(); 158 break; 159 case FUNC_DEL: 160 inputbuf[inputpos] = 0; 161 lcd_refresh(); 162 } 163} 164 165void 166input_put(char c) 167{ 168 if (inputpos >= 15) 169 return; 170 Serial.println("PUT"); 171 172 inputbuf[inputpos] = c; 173 inputpos++; 174 lcd_refresh(); 175} 176 177void 178input_del(void) 179{ 180 int i; 181 182 if (!inputpos) 183 return; 184 185 for (i = inputpos; i < sizeof(inputbuf); i++) 186 inputbuf[i-1] = inputbuf[i]; 187 inputpos--; 188 lcd_refresh(); 189} 190 191void 192input_enter(void) 193{ 194 if (!strncmp(inputbuf, pin, sizeof(inputbuf))) { 195 comm_open(); 196 } else { 197 snprintf(outputbuf, sizeof(outputbuf), "wrong!"); 198 } 199 lcd_refresh(); 200 memset(outputbuf, 0, sizeof(outputbuf)); 201} 202 203void 204blink(uint32_t ms) 205{ 206 digitalWrite(BLINK_LED, LOW); 207 delay(ms); 208 digitalWrite(BLINK_LED, HIGH); 209 delay(ms); 210} 211 212void 213comm_init(void) 214{ 215 size_t len; 216 217 while (!Serial.available()); 218 219 while (1) { 220 memset(linebuf, 0, sizeof(linebuf)); 221 len = Serial.readBytesUntil('\r', linebuf, sizeof(linebuf)); 222 if (!len) continue; 223 if (debugmode) { 224 Serial.print("<"); 225 Serial.println(linebuf); 226 } 227 if (!strncmp(linebuf, "!INIT", len)) 228 break; 229 } 230 231 Serial.println("!OK"); 232 233 blink(1000); 234} 235 236void 237comm_open(void) 238{ 239 size_t len; 240 241 blink(1000); 242 243 Serial.println("!FLAG"); 244 memset(linebuf, 0, sizeof(linebuf)); 245 len = Serial.readBytesUntil('\r', linebuf, sizeof(linebuf)); 246 if (debugmode) { 247 Serial.print("<"); 248 Serial.println(linebuf); 249 } 250 251 if (!strncmp(linebuf, "!OK", len)) { 252 len = Serial.readBytesUntil('\r', linebuf, sizeof(linebuf)); 253 strncpy(outputbuf, linebuf, sizeof(outputbuf)); 254 } else { 255 snprintf(outputbuf, sizeof(outputbuf), "error.."); 256 } 257} 258 259void 260getstates(void) 261{ 262 int i, k; 263 264 memcpy(pbstates, bstates, sizeof(bstates)); 265 memset(bstates, 0, sizeof(bstates)); 266 267 for (i = 0; i < ARRSIZE(pulsepins); i++) { 268 for (k = 0; k < ARRSIZE(pulsepins); k++) { 269 pinMode(pulsepins[k], k == i ? OUTPUT: INPUT); 270 digitalWrite(pulsepins[k], LOW); 271 } 272 delay(FEEL_DELAY); 273 274 for (k = 0; k < 6 && senselut[i][k][0]; k++) { 275 if (digitalRead(senselut[i][k][0]) == LOW) 276 bstates[senselut[i][k][1]] = true; 277 } 278 } 279} 280 281void 282setup(void) 283{ 284 int i; 285 286 snprintf(pin, 9, "13371337"); 287 288 for (i = 0; i < ARRSIZE(sensepins); i++) { 289 pinMode(sensepins[i], INPUT); 290 digitalWrite(sensepins[i], HIGH); 291 } 292 293 pinMode(debugswitch, INPUT); 294 digitalWrite(debugswitch, HIGH); 295 delay(10); 296 debugmode = (digitalRead(debugswitch) == LOW); 297 298 lcd.begin(); 299 lcd_refresh(); 300 301 lcd.noBacklight(); 302 303 Serial.begin(9600); 304 Serial.setTimeout(2000); 305 comm_init(); 306 307 lcd.backlight(); 308} 309 310void 311loop(void) 312{ 313 int i, k, layer; 314 bool hit; 315 316 getstates(); 317 318 layer = 0; 319 for (i = 0; i < ARRSIZE(modkeys); i++) 320 layer |= bstates[modkeys[i]] * (1 << i); 321 322 hit = false; 323 for (i = 0; i < BTN_COUNT; i++) { 324 if (bstates[i] && !pbstates[i]) { 325 hit = true; 326 if (debugmode) { 327 Serial.print("PRESS: "); 328 Serial.println(bnames[i]); 329 } 330 if (layers[layer]) { 331 if (layers[layer][i].type == KEY) { 332 input_put(layers[layer][i].c); 333 } else if (layers[layer][i].type == FUNC) { 334 call_func(layers[layer][i].c); 335 } 336 } 337 } else if (!bstates[i] && pbstates[i]) { 338 if (debugmode) { 339 Serial.print("RELEASE: "); 340 Serial.println(bnames[i]); 341 } 342 } 343 } 344 345 if (debugmode && hit) { 346 Serial.print("POS "); 347 Serial.println(inputpos); 348 } 349}