diff --git a/ascii_memory/ascii_memory.ino b/ascii_memory/ascii_memory.ino new file mode 100644 index 0000000..0c9a6f9 --- /dev/null +++ b/ascii_memory/ascii_memory.ino @@ -0,0 +1,336 @@ +#include + +#include + +// init extended ascii font [https://github.com/ecraven/g13/blob/815e0001cb5e24a184186506d2c95f4171e48547/g13_fonts.cc] +// other font: [https://github.com/AdamCDunlap/arduino/blob/940c9db5cbeb55ffcba3661697cf0495dd54f8c2/libraries/LEDArray/includes/characters.h] +// other font: [https://github.com/basti79/LCD-fonts/blob/master/5x8_vertikal_LSB_1.h] +uint8_t ascii_font[256][5] = { + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 + {0x1E, 0x35, 0x31, 0x35, 0x1E}, // 0x01 + {0x1E, 0x35, 0x37, 0x35, 0x1E}, // 0x02 + {0x0E, 0x1F, 0x3E, 0x1F, 0x0E}, // 0x03 + {0x08, 0x1C, 0x7F, 0x1C, 0x08}, // 0x04 + {0x18, 0x4A, 0x7F, 0x4A, 0x18}, // 0x05 + {0x1C, 0x4E, 0x7F, 0x4E, 0x1C}, // 0x06 + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x07 + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x08 + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09 + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A + {0x38, 0x44, 0x44, 0x47, 0x3B}, // 0x0B + {0x0E, 0x51, 0xF1, 0x51, 0x0E}, // 0x0C + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D + {0x60, 0x7E, 0x02, 0x33, 0x3F}, // 0x0E + {0x2A, 0x1C, 0x36, 0x1C, 0x2A}, // 0x0F + {0x3E, 0x1C, 0x1C, 0x08, 0x08}, // 0x10 + {0x08, 0x08, 0x1C, 0x1C, 0x3E}, // 0x11 + {0x00, 0x22, 0x7F, 0x22, 0x00}, // 0x12 + {0x00, 0x2E, 0x00, 0x2E, 0x00}, // 0x13 + {0x06, 0x7F, 0x01, 0x7F, 0x00}, // 0x14 + {0x00, 0x4A, 0x55, 0x29, 0x00}, // 0x15 + {0x00, 0x18, 0x18, 0x18, 0x18}, // 0x16 + {0x00, 0x4A, 0x5F, 0x4A, 0x00}, // 0x17 + {0x00, 0x02, 0x7F, 0x02, 0x00}, // 0x18 + {0x00, 0x20, 0x7F, 0x20, 0x00}, // 0x19 + {0x00, 0x08, 0x08, 0x1C, 0x08}, // 0x1A + {0x00, 0x08, 0x1C, 0x08, 0x08}, // 0x1B + {0x00, 0x3C, 0x20, 0x20, 0x20}, // 0x1C + {0x08, 0x1C, 0x08, 0x1C, 0x08}, // 0x1D + {0x20, 0x38, 0x3E, 0x38, 0x20}, // 0x1E + {0x02, 0x0E, 0x3E, 0x0E, 0x02}, // 0x1F + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 (Space) + {0x00, 0x00, 0x9E, 0x00, 0x00}, // 0x21 ! + {0x00, 0x0E, 0x00, 0x0E, 0x00}, // 0x22 " + {0x28, 0xFE, 0x28, 0xFE, 0x28}, // 0x23 # + {0x48, 0x54, 0xFE, 0x54, 0x24}, // 0x24 $ + {0x46, 0x26, 0x10, 0xC8, 0xC4}, // 0x25 % + {0x6C, 0x92, 0xAA, 0x44, 0xA0}, // 0x26 & + {0x00, 0x0A, 0x06, 0x00, 0x00}, // 0x27 ' + {0x00, 0x38, 0x44, 0x82, 0x00}, // 0x28 ( + {0x00, 0x82, 0x44, 0x38, 0x00}, // 0x29 ) + {0x10, 0x54, 0x38, 0x54, 0x10}, // 0x2A * + {0x10, 0x10, 0x7C, 0x10, 0x10}, // 0x2B + + {0x00, 0xA0, 0x60, 0x00, 0x00}, // 0x2C , + {0x10, 0x10, 0x10, 0x10, 0x10}, // 0x2D - + {0x00, 0x60, 0x60, 0x00, 0x00}, // 0x2E . + {0x40, 0x20, 0x10, 0x08, 0x04}, // 0x2F / + {0x7C, 0xA2, 0x92, 0x8A, 0x7C}, // 0x30 0 + {0x00, 0x84, 0xFE, 0x80, 0x00}, // 0x31 1 + {0x84, 0xC2, 0xA2, 0x92, 0x8C}, // 0x32 2 + {0x42, 0x82, 0x8A, 0x96, 0x62}, // 0x33 3 + {0x30, 0x28, 0x24, 0xFE, 0x20}, // 0x34 4 + {0x4E, 0x8A, 0x8A, 0x8A, 0x72}, // 0x35 5 + {0x78, 0x94, 0x92, 0x92, 0x60}, // 0x36 6 + {0x02, 0xE2, 0x12, 0x0A, 0x06}, // 0x37 7 + {0x6C, 0x92, 0x92, 0x92, 0x6C}, // 0x38 8 + {0x0C, 0x92, 0x92, 0x52, 0x3C}, // 0x39 9 + {0x00, 0x6C, 0x6C, 0x00, 0x00}, // 0x3A : + {0x00, 0xAC, 0x6C, 0x00, 0x00}, // 0x3B ; + {0x00, 0x10, 0x28, 0x44, 0x82}, // 0x3C < + {0x28, 0x28, 0x28, 0x28, 0x28}, // 0x3D = + {0x82, 0x44, 0x28, 0x10, 0x00}, // 0x3E > + {0x04, 0x02, 0xA2, 0x12, 0x0C}, // 0x3F ? + {0x64, 0x92, 0xF2, 0x82, 0x7C}, // 0x40 @ + {0xFC, 0x22, 0x22, 0x22, 0xFC}, // 0x41 A + {0xFE, 0x92, 0x92, 0x92, 0x6C}, // 0x42 B + {0x7C, 0x82, 0x82, 0x82, 0x44}, // 0x43 C + {0xFE, 0x82, 0x82, 0x44, 0x38}, // 0x44 D + {0xFE, 0x92, 0x92, 0x92, 0x82}, // 0x45 E + {0xFE, 0x12, 0x12, 0x02, 0x02}, // 0x46 F + {0x7C, 0x82, 0x82, 0xA2, 0x64}, // 0x47 G + {0xFE, 0x10, 0x10, 0x10, 0xFE}, // 0x48 H + {0x00, 0x82, 0xFE, 0x82, 0x00}, // 0x49 I + {0x40, 0x80, 0x82, 0x7E, 0x02}, // 0x4A J + {0xFE, 0x10, 0x28, 0x44, 0x82}, // 0x4B K + {0xFE, 0x80, 0x80, 0x80, 0x80}, // 0x4C L + {0xFE, 0x04, 0x08, 0x04, 0xFE}, // 0x4D M + {0xFE, 0x08, 0x10, 0x20, 0xFE}, // 0x4E N + {0x7C, 0x82, 0x82, 0x82, 0x7C}, // 0x4F O + {0xFE, 0x12, 0x12, 0x12, 0x0C}, // 0x50 P + {0x7C, 0x82, 0xA2, 0x42, 0xBC}, // 0x51 Q + {0xFE, 0x12, 0x32, 0x52, 0x8C}, // 0x52 R + {0x8C, 0x92, 0x92, 0x92, 0x62}, // 0x53 S + {0x02, 0x02, 0xFE, 0x02, 0x02}, // 0x54 T + {0x7E, 0x80, 0x80, 0x80, 0x7E}, // 0x55 U + {0x3E, 0x40, 0x80, 0x40, 0x3E}, // 0x56 V + {0xFE, 0x40, 0x30, 0x40, 0xFE}, // 0x57 W + {0xC6, 0x28, 0x10, 0x28, 0xC6}, // 0x58 X + {0x06, 0x08, 0xF0, 0x08, 0x06}, // 0x59 Y + {0xC2, 0xA2, 0x92, 0x8A, 0x86}, // 0x5A Z + {0x00, 0x00, 0xFE, 0x82, 0x82}, // 0x5B [ + {0x04, 0x08, 0x10, 0x20, 0x40}, // 0x5C "\" + {0x82, 0x82, 0xFE, 0x00, 0x00}, // 0x5D ] + {0x08, 0x04, 0x02, 0x04, 0x08}, // 0x5E ^ + {0x80, 0x80, 0x80, 0x80, 0x80}, // 0x5F _ + {0x00, 0x02, 0x04, 0x08, 0x00}, // 0x60 ` + {0x40, 0xA8, 0xA8, 0xA8, 0xF0}, // 0x61 a + {0xFE, 0x90, 0x88, 0x88, 0x70}, // 0x62 b + {0x70, 0x88, 0x88, 0x88, 0x40}, // 0x63 c + {0x70, 0x88, 0x88, 0x90, 0xFE}, // 0x64 d + {0x70, 0xA8, 0xA8, 0xA8, 0x30}, // 0x65 e + {0x10, 0xFC, 0x12, 0x02, 0x04}, // 0x66 f + {0x10, 0x28, 0xA8, 0xA8, 0x78}, // 0x67 g + {0xFE, 0x10, 0x08, 0x08, 0xF0}, // 0x68 h + {0x00, 0x88, 0xFA, 0x80, 0x00}, // 0x69 i + {0x40, 0x80, 0x88, 0x7A, 0x00}, // 0x6A j + {0x00, 0xFE, 0x20, 0x50, 0x88}, // 0x6B k + {0x00, 0x82, 0xFE, 0x80, 0x00}, // 0x6C l + {0xF8, 0x08, 0x30, 0x08, 0xF0}, // 0x6D m + {0xF8, 0x10, 0x08, 0x08, 0xF0}, // 0x6E n + {0x70, 0x88, 0x88, 0x88, 0x70}, // 0x6F o + {0xF8, 0x28, 0x28, 0x28, 0x10}, // 0x70 p + {0x10, 0x28, 0x28, 0x30, 0xF8}, // 0x71 q + {0xF8, 0x10, 0x08, 0x08, 0x10}, // 0x72 r + {0x90, 0xA8, 0xA8, 0xA8, 0x40}, // 0x73 s + {0x08, 0x7E, 0x88, 0x80, 0x40}, // 0x74 t + {0x78, 0x80, 0x80, 0x40, 0xF8}, // 0x75 u + {0x38, 0x40, 0x80, 0x40, 0x38}, // 0x76 v + {0x78, 0x80, 0x60, 0x80, 0x78}, // 0x77 w + {0x88, 0x50, 0x20, 0x50, 0x88}, // 0x78 x + {0x18, 0xA0, 0xA0, 0xA0, 0x78}, // 0x79 y + {0x88, 0xC8, 0xA8, 0x98, 0x88}, // 0x7A z + {0x00, 0x10, 0x6C, 0x82, 0x00}, // 0x7B { + {0x00, 0x00, 0xFE, 0x00, 0x00}, // 0x7C | + {0x00, 0x82, 0x6C, 0x10, 0x00}, // 0x7D } + {0x20, 0x10, 0x10, 0x20, 0x10}, // 0x7E + {0xF0, 0x88, 0x84, 0x88, 0xF0}, // 0x7F  + {0x28, 0x7C, 0xAA, 0x82, 0x44}, // 0x80 € + {0xF0, 0x29, 0x27, 0x21, 0xFF}, // 0x81  + {0x00, 0xA0, 0x60, 0x00, 0x00}, // 0x82 ‚ + {0x40, 0x90, 0x7C, 0x12, 0x04}, // 0x83 ƒ + {0xC0, 0xA0, 0x00, 0xC0, 0xA0}, // 0x84 „ + {0x80, 0x00, 0x80, 0x00, 0x80}, // 0x85 … + {0x00, 0x04, 0xFE, 0x04, 0x00}, // 0x86 † + {0x00, 0x44, 0xFE, 0x44, 0x00}, // 0x87 ‡ + {0x00, 0x04, 0x02, 0x04, 0x00}, // 0x88 ˆ + {0xC3, 0xD3, 0x08, 0xC4, 0xC2}, // 0x89 ‰ + {0x4C, 0x93, 0x92, 0x93, 0x64}, // 0x8A Š + {0x00, 0x10, 0x28, 0x00, 0x00}, // 0x8B ‹ + {0x7C, 0x82, 0x82, 0x7C, 0x92}, // 0x8C Œ + {0x02, 0xFE, 0x90, 0x90, 0x60}, // 0x8D  + {0xC2, 0xA3, 0x92, 0x8B, 0x86}, // 0x8E Ž + {0x44, 0x92, 0x8A, 0x92, 0x7C}, // 0x8F  + {0x70, 0x88, 0x90, 0x60, 0x98}, // 0x90  + {0x00, 0x02, 0x04, 0x08, 0x00}, // 0x91 ‘ + {0x00, 0x08, 0x04, 0x02, 0x00}, // 0x92 ’ + {0x02, 0x04, 0x0A, 0x04, 0x08}, // 0x93 “ + {0x08, 0x04, 0x0A, 0x04, 0x02}, // 0x94 ” + {0x00, 0x38, 0x38, 0x38, 0x00}, // 0x95 • + {0x00, 0x10, 0x10, 0x10, 0x10}, // 0x96 – + {0x10, 0x10, 0x10, 0x10, 0x10}, // 0x97 — + {0x02, 0x01, 0x02, 0x04, 0x02}, // 0x98 ˜ + {0xF1, 0x5B, 0x55, 0x51, 0x51}, // 0x99 ™ + {0x90, 0xA9, 0xAA, 0xA9, 0x40}, // 0x9A š + {0x00, 0x88, 0x50, 0x20, 0x00}, // 0x9B › + {0x70, 0x88, 0x70, 0xA8, 0xB0}, // 0x9C œ° + {0x38, 0x7C, 0xF8, 0x7C, 0x38}, // 0x9D  + {0x88, 0xC9, 0xAA, 0x99, 0x88}, // 0x9E ž + {0x1C, 0x21, 0xC0, 0x21, 0x1C}, // 0x9F Ÿ + {0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0 + {0x00, 0x00, 0xF2, 0x00, 0x00}, // 0xA1 ¡ + {0x38, 0x44, 0xFE, 0x44, 0x20}, // 0xA2 ¢ + {0x90, 0x7C, 0x92, 0x82, 0x40}, // 0xA3 £ + {0x44, 0x38, 0x28, 0x38, 0x44}, // 0xA4 ¤ + {0x2A, 0x2C, 0xF8, 0x2C, 0x2A}, // 0xA5 ¥ + {0x00, 0x00, 0xEE, 0x00, 0x00}, // 0xA6 ¦ + {0x40, 0x94, 0xAA, 0x52, 0x04}, // 0xA7 § + {0x00, 0x02, 0x00, 0x02, 0x00}, // 0xA8 ¨ + {0xFE, 0x82, 0xBA, 0x92, 0xFE}, // 0xA9 © + {0x90, 0xAA, 0xAA, 0xAA, 0xBC}, // 0xAA ª + {0x20, 0x50, 0xA8, 0x50, 0x88}, // 0xAB « + {0x20, 0x20, 0x20, 0x20, 0xE0}, // 0xAC ¬ + {0x20, 0x20, 0x20, 0x20, 0x20}, // 0xAD ­ + {0xFE, 0x82, 0xCA, 0xA2, 0xFE}, // 0xAE ® + {0x02, 0x02, 0x02, 0x02, 0x02}, // 0xAF ¯ + {0x0E, 0x11, 0x11, 0x0E, 0x00}, // 0xB0 ° + {0x88, 0x88, 0xBE, 0x88, 0x88}, // 0xB1 ± + {0x12, 0x19, 0x15, 0x12, 0x00}, // 0xB2 ² + {0x11, 0x15, 0x15, 0x0A, 0x00}, // 0xB3 ³ + {0x00, 0x08, 0x04, 0x02, 0x00}, // 0xB4 ´ + {0xFE, 0x20, 0x20, 0x10, 0x3E}, // 0xB5 µ + {0x0C, 0x12, 0x12, 0xFE, 0xFE}, // 0xB6 ¶ + {0x00, 0x30, 0x30, 0x00, 0x00}, // 0xB7 · + {0x00, 0x80, 0xB0, 0x40, 0x00}, // 0xB8 ¸ + {0x00, 0x02, 0x0F, 0x00, 0x00}, // 0xB9 ¹ + {0x00, 0x02, 0x05, 0x02, 0x00}, // 0xBA º + {0x44, 0x28, 0x54, 0x28, 0x10}, // 0xBB » + {0x22, 0x1F, 0x68, 0x54, 0xFA}, // 0xBC ¼ + {0x02, 0x1F, 0x90, 0xC8, 0xB0}, // 0xBD ½ + {0x15, 0x1F, 0x60, 0x50, 0xF8}, // 0xBE ¾ + {0x60, 0x90, 0x8A, 0x80, 0x40}, // 0xBF ¿ + {0xF0, 0x29, 0x26, 0x28, 0xF0}, // 0xC0 À + {0xF0, 0x28, 0x26, 0x29, 0xF0}, // 0xC1 Á + {0xF0, 0x2A, 0x29, 0x2A, 0xF0}, // 0xC2  + {0xF2, 0x29, 0x29, 0x2A, 0xF1}, // 0xC3 à + {0xF0, 0x29, 0x24, 0x29, 0xF0}, // 0xC4 Ä + {0xF0, 0x2A, 0x2D, 0x2A, 0xF0}, // 0xC5 Å + {0xF8, 0x24, 0xFE, 0x92, 0x92}, // 0xC6 Æ + {0x1E, 0x21, 0xA1, 0xE1, 0x12}, // 0xC7 Ç + {0xF8, 0xA9, 0xAA, 0xA8, 0x88}, // 0xC8 È + {0xF8, 0xA8, 0xAA, 0xA9, 0x88}, // 0xC9 É + {0xF8, 0xAA, 0xA9, 0xAA, 0x88}, // 0xCA Ê + {0xF8, 0xAA, 0xA8, 0xAA, 0x88}, // 0xCB Ë + {0x00, 0x89, 0xFA, 0x88, 0x00}, // 0xCC Ì + {0x00, 0x88, 0xFA, 0x89, 0x00}, // 0xCD Í + {0x00, 0x8A, 0xF9, 0x8A, 0x00}, // 0xCE Î + {0x00, 0x8A, 0xF8, 0x8A, 0x00}, // 0xCF Ï + {0x10, 0xFE, 0x92, 0x82, 0x7C}, // 0xD0 Ð + {0xFA, 0x11, 0x21, 0x42, 0xF9}, // 0xD1 Ñ + {0x78, 0x85, 0x86, 0x84, 0x78}, // 0xD2 Ò + {0x78, 0x84, 0x86, 0x85, 0x78}, // 0xD3 Ó + {0x70, 0x8A, 0x89, 0x8A, 0x70}, // 0xD4 Ô + {0x72, 0x89, 0x89, 0x8A, 0x71}, // 0xD5 Õ + {0x78, 0x85, 0x84, 0x85, 0x78}, // 0xD6 Ö + {0x44, 0x28, 0x10, 0x28, 0x44}, // 0xD7 × + {0x10, 0xAA, 0xFE, 0xAA, 0x10}, // 0xD8 Ø + {0x7C, 0x81, 0x82, 0x80, 0x7C}, // 0xD9 Ù + {0x7C, 0x80, 0x82, 0x81, 0x7C}, // 0xDA Ú + {0x78, 0x82, 0x81, 0x82, 0x78}, // 0xDB Û + {0x7C, 0x81, 0x80, 0x81, 0x7C}, // 0xDC Ü + {0x04, 0x08, 0xF2, 0x09, 0x04}, // 0xDD Ý + {0x81, 0xFF, 0x24, 0x24, 0x18}, // 0xDE Þ + {0x80, 0x7C, 0x92, 0x92, 0x6C}, // 0xDF ß + {0x40, 0xA9, 0xAA, 0xA8, 0xF0}, // 0xE0 à + {0x40, 0xA8, 0xAA, 0xA9, 0xF0}, // 0xE1 á + {0x40, 0xAA, 0xA9, 0xAA, 0xF0}, // 0xE2 â + {0x42, 0xA9, 0xA9, 0xAA, 0xF1}, // 0xE3 ã + {0x40, 0xAA, 0xA8, 0xAA, 0xF0}, // 0xE4 ä + {0x40, 0xAA, 0xAD, 0xAA, 0xF0}, // 0xE5 å + {0x64, 0x94, 0x78, 0x94, 0x58}, // 0xE6 æ + {0x18, 0x24, 0xA4, 0xE4, 0x10}, // 0xE7 ç + {0x70, 0xA9, 0xAA, 0xA8, 0x30}, // 0xE8 è + {0x70, 0xA8, 0xAA, 0xA9, 0x30}, // 0xE9 é + {0x70, 0xAA, 0xA9, 0xAA, 0x30}, // 0xEA ê + {0x70, 0xAA, 0xA8, 0xAA, 0x30}, // 0xEB ë + {0x00, 0x91, 0xFA, 0x80, 0x00}, // 0xEC ì + {0x00, 0x90, 0xFA, 0x81, 0x00}, // 0xED í + {0x00, 0x92, 0xF9, 0x82, 0x00}, // 0xEE î + {0x00, 0x92, 0xF8, 0x82, 0x00}, // 0xEF ï + {0x4A, 0xA4, 0xAA, 0xB0, 0x60}, // 0xF0 ð + {0xFA, 0x11, 0x09, 0x0A, 0xF1}, // 0xF1 ñ + {0x70, 0x89, 0x8A, 0x88, 0x70}, // 0xF2 ò + {0x70, 0x88, 0x8A, 0x89, 0x70}, // 0xF3 ó + {0x60, 0x94, 0x92, 0x94, 0x60}, // 0xF4 ô + {0x64, 0x92, 0x92, 0x94, 0x62}, // 0xF5 õ + {0x70, 0x8A, 0x88, 0x8A, 0x70}, // 0xF6 ö + {0x10, 0x10, 0x54, 0x10, 0x10}, // 0xF7 ÷ + {0x10, 0xA8, 0x7C, 0x2A, 0x10}, // 0xF8 ø + {0x78, 0x81, 0x82, 0x40, 0xF8}, // 0xF9 ù + {0x78, 0x80, 0x82, 0x41, 0xF8}, // 0xFA ú + {0x78, 0x82, 0x81, 0x42, 0xF8}, // 0xFB û + {0x78, 0x82, 0x80, 0x42, 0xF8}, // 0xFC ü + {0x18, 0xA0, 0xA4, 0xA2, 0x78}, // 0xFD v + {0x00, 0x82, 0xFE, 0xA8, 0x10}, // 0xFE þ + {0x18, 0xA2, 0xA0, 0xA2, 0x78} // 0xFF ÿ +}; + +AT24C32 at24c32; +uint8_t data; + +/** + setup + */ +void setup() +{ + Serial.begin(115200); + + at24c32.begin(); + + for (int ascii = 0; ascii < 256; ascii++) + { + for (int b = 0; b < 5; b++) + { + at24c32.write(ascii * 5 + b, ascii_font[ascii][b]); + Serial.print(ascii * 5 + b); + if (at24c32.read(ascii * 5 + b) == ascii_font[ascii][b]) + { + Serial.println(F(": check")); + } + else + { + Serial.print(F(": ERROR! ")); + Serial.print(ascii_font[ascii][b]); + Serial.print(F(" - ")); + Serial.println(at24c32.read(ascii * 5 + b)); + } + } + } + + Serial.println(F("ascii chars written!")); + + for (int i = 0; i < 256; i++) + { + at24c32.write(TEXT_ADDRESS + i, char('A')); + } + + Serial.println(F("Text resets to 'A'")); + + String text = "Liebe Rohrers, frohe Weihnachten (nachtrAglich)!"; + + at24c32.write(TEXT_SIZE_ADDRESS, text.length()); + + for (int i = 0; i < text.length(); i++) + { + at24c32.write(TEXT_ADDRESS + i, char(text[i])); + } + + Serial.println(F("text written!")); +} + +/** + loop + */ +void loop() +{ + // read text + uint8_t length = at24c32.read(TEXT_SIZE_ADDRESS); + + for (uint8_t i = 0; i < length; i++) + { + Serial.print(char(at24c32.read(TEXT_ADDRESS + i))); + } + + Serial.println(); + + delay(2000); +} diff --git a/libraries/AT23C32/AT24C32.cpp b/libraries/AT23C32/AT24C32.cpp new file mode 100644 index 0000000..41607fd --- /dev/null +++ b/libraries/AT23C32/AT24C32.cpp @@ -0,0 +1,49 @@ +#include + +#include + +#include + +void AT24C32::begin() +{ + Wire.begin(); +}; + +uint8_t AT24C32::read(int address) +{ + uint8_t result = 0; + bool read = true; + Wire.beginTransmission(AT24C32_I2C_ADDRESS); + if (Wire.endTransmission() == 0) + { + Wire.beginTransmission(AT24C32_I2C_ADDRESS); + Wire.write(address >> 8); + Wire.write(address & 0xff); + if (Wire.endTransmission() == 0) + { + Wire.requestFrom(AT24C32_I2C_ADDRESS, 1); + while (Wire.available() > 0 && read) + { + result = Wire.read(); + read = false; + } + + Wire.endTransmission(); + } + } + return result; +} + +void AT24C32::write(int address, uint8_t data) +{ + Wire.beginTransmission(AT24C32_I2C_ADDRESS); + if (Wire.endTransmission() == 0) + { + Wire.beginTransmission(AT24C32_I2C_ADDRESS); + Wire.write(address >> 8); + Wire.write(address & 0xff); + Wire.write(data); + Wire.endTransmission(); + delay(20); + } +} diff --git a/libraries/AT23C32/AT24C32.h b/libraries/AT23C32/AT24C32.h new file mode 100644 index 0000000..d34cd69 --- /dev/null +++ b/libraries/AT23C32/AT24C32.h @@ -0,0 +1,28 @@ +#ifndef AT24C32_h +#define AT24C32_h + +#include + +class AT24C32 +{ +public: + void begin(); + uint8_t read(int address); + void write(int address, uint8_t data); +}; + +// I2C address +#define AT24C32_I2C_ADDRESS 0x57 + +#define BRIGHTNESS_ADDRESS 0x0A00 + +#define COLOR_ADDRESS 0x0A01 + +#define VIEW_STATE_ADDRESS 0x0A02 + +#define TIME_MODE_ADDRESS 0x0A03 + +#define TEXT_SIZE_ADDRESS 0x0B00 +#define TEXT_ADDRESS 0x0B01 + +#endif diff --git a/libraries/Button/Button.cpp b/libraries/Button/Button.cpp new file mode 100644 index 0000000..ba53c19 --- /dev/null +++ b/libraries/Button/Button.cpp @@ -0,0 +1,33 @@ +#include + +#include + +#include "Button.h" + +Button::Button(uint8_t _pin, uint8_t _mode) +{ + pin = _pin; + mode = _mode; +} + +void Button::begin() +{ + if (mode == LOW) + { + pinMode(pin, INPUT_PULLUP); + } + else if (mode == HIGH) + { + pinMode(pin, INPUT); + } +} + +void Button::loop(ButtonCallbackFunction callback) +{ + if (digitalRead(pin) == mode) + { + (*callback)(); + // debounce + delay(250); + } +} \ No newline at end of file diff --git a/libraries/Button/Button.h b/libraries/Button/Button.h new file mode 100644 index 0000000..9608c12 --- /dev/null +++ b/libraries/Button/Button.h @@ -0,0 +1,20 @@ +#ifndef Button_h +#define Button_h + +#include + +typedef void (*ButtonCallbackFunction)(); + +class Button +{ +public: + Button(uint8_t _pin, uint8_t _mode); + void begin(); + void loop(ButtonCallbackFunction callback); + +private: + uint8_t mode; + uint8_t pin; +}; + +#endif \ No newline at end of file diff --git a/libraries/DS3231/DS3231.cpp b/libraries/DS3231/DS3231.cpp new file mode 100644 index 0000000..5f9d630 --- /dev/null +++ b/libraries/DS3231/DS3231.cpp @@ -0,0 +1,406 @@ +#include + +#include + +#include + +void DS3231::begin() +{ + Wire.begin(); +} + +uint8_t DS3231::getSeconds() +{ + uint8_t seconds; + // read minutes + seconds = getRegister(DS3231_SECONDS); + return bcdtodec(seconds); +} + +void DS3231::setSeconds(uint8_t seconds) +{ + // write seconds + setRegister(DS3231_SECONDS, dectobcd(seconds)); +} + +void DS3231::incrementSeconds() +{ + uint8_t seconds = getSeconds(); + + if (seconds == 58) + { + seconds = 0; + } + else + { + seconds += 2; + } + + setSeconds(seconds); +} + +void DS3231::decrementSeconds() +{ + uint8_t seconds = getSeconds(); + + if (seconds == 1) + { + seconds = 59; + } + else + { + seconds -= 2; + } + + setSeconds(seconds); +} + +uint8_t DS3231::getMinutes() +{ + uint8_t minutes; + // read minutes + minutes = getRegister(DS3231_MINUTES); + return bcdtodec(minutes); +} + +void DS3231::setMinutes(uint8_t minutes) +{ + // write minutes + setRegister(DS3231_MINUTES, dectobcd(minutes)); +} + +void DS3231::incrementMinutes() +{ + uint8_t minutes = getMinutes(); + + if (minutes == 59) + { + minutes = 0; + } + else + { + minutes++; + } + + setMinutes(minutes); +} + +void DS3231::decrementMinutes() +{ + uint8_t minutes = getMinutes(); + + if (minutes == 0) + { + minutes = 59; + } + else + { + minutes--; + } + + setMinutes(minutes); +} + +uint8_t DS3231::getHours() +{ + uint8_t hours; + // read hours + hours = getRegister(DS3231_HOURS); + return bcdtodec(hours); +} + +void DS3231::setHours(uint8_t hours) +{ + // write hours + setRegister(DS3231_HOURS, dectobcd(hours)); +} + +void DS3231::incrementHours() +{ + uint8_t hours = getHours(); + + if (hours == 23) + { + hours = 0; + } + else + { + hours++; + } + + setHours(hours); +} + +void DS3231::decrementHours() +{ + uint8_t hours = getHours(); + + if (hours == 0) + { + hours = 23; + } + else + { + hours--; + } + + setHours(hours); +} + +uint8_t DS3231::getDay() +{ + uint8_t day; + // read day + day = getRegister(DS3231_DAY); + return bcdtodec(day); +} + +void DS3231::setDay(uint8_t day) +{ + // write day + setRegister(DS3231_DAY, dectobcd(day)); +} + +uint8_t DS3231::getDate() +{ + uint8_t date; + // read date + date = getRegister(DS3231_DATE); + return bcdtodec(date); +} + +void DS3231::setDate(uint8_t date) +{ + // write date + setRegister(DS3231_DATE, dectobcd(date)); +} + +void DS3231::incrementDate() +{ + uint8_t date = getDate(); + date++; + if (date > 31) + { + date = 1; + } + setDate(date); +} + +void DS3231::decrementDate() +{ + uint8_t date = getDate(); + date--; + if (date < 1) + { + date = 31; + } + setDate(date); +} + +uint8_t DS3231::getMonth() +{ + uint8_t month; + // read month + month = getRegister(DS3231_MONTH); + + // read month, ingore century; + return bcdtodec(month & 0x1F); +} + +void DS3231::setMonth(uint8_t month) +{ + uint8_t century = getCentury(); + + month = dectobcd(month); + + if (century == 1) + { + month = month + 0x80; + } + + // write month + setRegister(DS3231_MONTH, month); +} + +void DS3231::incrementMonth() +{ + uint8_t month = getMonth(); + month++; + if (month > 12) + { + month = 1; + } + setMonth(month); +} + +void DS3231::decrementMonth() +{ + uint8_t month = getMonth(); + month--; + if (month < 1) + { + month = 12; + } + setMonth(month); +} + +int16_t DS3231::getYear() +{ + uint8_t century = getCentury(); + + int16_t year; + + // read year + year = getRegister(DS3231_YEAR); + + year = bcdtodec(year); + + if (century == 1) + { + year = 2000 + year; + } + else + { + year = 1900 + year; + } + + return year; +} + +void DS3231::setYear(int16_t year) +{ + if (year > 1999) + { + year = year - 2000; + setCentury(0x80); + } + else + { + year = year - 1900; + setCentury(0); + } + + setRegister(DS3231_YEAR, dectobcd(year)); +} + +void DS3231::incrementYear() +{ + int16_t year = getYear(); + year++; + if (year > 2099) + { + year = 1900; + } + setYear(year); +} + +void DS3231::decrementYear() +{ + int16_t year = getYear(); + year--; + if (year < 1900) + { + year = 2099; + } + setYear(year); +} + +uint8_t DS3231::getControlRegister() +{ + return bcdtodec(getRegister(DS3231_CONTROL)); +} + +void DS3231::setControlRegister(uint8_t value) +{ + setRegister(DS3231_CONTROL, dectobcd(value)); +} + +uint8_t DS3231::getStatusRegister() +{ + return bcdtodec(getRegister(DS3231_STATUS)); +} + +void DS3231::setStatusRegister(uint8_t value) +{ + setRegister(DS3231_STATUS, dectobcd(value)); +} + +uint8_t DS3231::getTemperature() +{ + int8_t msb_temp; + uint8_t msb_value = getRegister(DS3231_MSB_TEMP); + uint8_t lsb_temp = getRegister(DS3231_LSB_TEMP) >> 6; + float result; + + if ((msb_value & 0x80) != 0) + { + msb_temp = msb_value | ~((1 << 8) - 1); + } + else + { + msb_temp = msb_value; + } + + result = 0.25 * lsb_temp + msb_temp; + + return result; +} + +uint8_t DS3231::getRegister(uint8_t address) +{ + uint8_t value; + + Wire.beginTransmission(DS3231_I2C_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + + // request 1 byte + Wire.requestFrom(DS3231_I2C_ADDRESS, 1); + + // read value + value = Wire.read(); + + return value; +} + +void DS3231::setRegister(uint8_t address, uint8_t value) +{ + Wire.beginTransmission(DS3231_I2C_ADDRESS); + // start at address + Wire.write(address); + + // write value + Wire.write(value); + + Wire.endTransmission(); +} + +uint8_t DS3231::dectobcd(uint8_t value) +{ + return ((value / 10 * 16) + (value % 10)); +} + +uint8_t DS3231::bcdtodec(uint8_t value) +{ + return ((value / 16 * 10) + (value % 16)); +} + +uint8_t DS3231::getCentury() +{ + uint8_t century = 0; + + uint8_t month = getRegister(DS3231_MONTH); + + // read century from month + century = (month & 0x80) >> 7; + return century; +} + +void DS3231::setCentury(uint8_t century) +{ + uint8_t month = getMonth(); + + month = month + century; + + setRegister(DS3231_MONTH, month); +} \ No newline at end of file diff --git a/libraries/DS3231/DS3231.h b/libraries/DS3231/DS3231.h new file mode 100644 index 0000000..9e29e38 --- /dev/null +++ b/libraries/DS3231/DS3231.h @@ -0,0 +1,133 @@ +#ifndef DS3231_h +#define DS3231_h + +#include + +/** + TODO: alarms + */ +class DS3231 +{ +public: + // begin function + void begin(); + // get seconds + uint8_t getSeconds(); + // set seconds + void setSeconds(uint8_t seconds); + // increment seconds + void incrementSeconds(); + // decrement seconds + void decrementSeconds(); + // get minutes + uint8_t getMinutes(); + // set minutes + void setMinutes(uint8_t minutes); + // increment minutes + void incrementMinutes(); + // decrement minutes + void decrementMinutes(); + // get hours + uint8_t getHours(); + // set hours + void setHours(uint8_t hours); + // increment hours + void incrementHours(); + // decrement hours + void decrementHours(); + // get day + uint8_t getDay(); + // set day + void setDay(uint8_t day); + // get date + uint8_t getDate(); + // set date + void setDate(uint8_t date); + // increment date + void incrementDate(); + // decrement date + void decrementDate(); + // get month + uint8_t getMonth(); + // set month + void setMonth(uint8_t month); + // increment month + void incrementMonth(); + // decrement month + void decrementMonth(); + // get year + int16_t getYear(); + // set year + void setYear(int16_t year); + // increment year + void incrementYear(); + // decrement year + void decrementYear(); + // get control register + uint8_t getControlRegister(); + // set control register + void setControlRegister(uint8_t value); + // set status register + uint8_t getStatusRegister(); + // set status register + void setStatusRegister(uint8_t value); + // get temperature + uint8_t getTemperature(); + // helpers +protected: + // get register + uint8_t getRegister(uint8_t address); + // set register + void setRegister(uint8_t address, uint8_t value); + // decimal to binary coded decimal + uint8_t dectobcd(uint8_t value); + // binary coded decimal to decimal + uint8_t bcdtodec(uint8_t value); + // get century value + uint8_t getCentury(); + // set century value + void setCentury(uint8_t century); +}; + +// I2C address +#define DS3231_I2C_ADDRESS 0x68 + +// I2C registers +#define DS3231_SECONDS 0x00 +#define DS3231_MINUTES 0x01 +#define DS3231_HOURS 0x02 +#define DS3231_DAY 0x03 +#define DS3231_DATE 0x04 +#define DS3231_MONTH 0x05 +#define DS3231_YEAR 0x06 +#define DS3231_ALARM1_SECONDS 0x07 +#define DS3231_ALARM1_MINUTES 0x08 +#define DS3231_ALARM1_HOURS 0x09 +#define DS3231_ALARM1_DATE 0x0A +#define DS3231_ALARM2_MINUTES 0x0B +#define DS3231_ALARM2_HOURS 0x0C +#define DS3231_ALARM1_DATE 0x0D +#define DS3231_CONTROL 0x0E +#define DS3231_STATUS 0x0F +#define DS3231_AGING_OFFSET 0x10 +#define DS3231_MSB_TEMP 0x11 +#define DS3231_LSB_TEMP 0x12 + +// control registers +#define DS3231_CONTROL_A1IE 0x01 +#define DS3231_CONTROL_A2IE 0x02 +#define DS3231_CONTROL_INTCN 0x04 +#define DS3231_CONTROL_RS1 0x08 +#define DS3231_CONTROL_RS2 0x10 +#define DS3231_CONTROL_CONV 0x20 +#define DS3231_CONTROL_BBSQW 0x40 +#define DS3231_CONTROL_EOSC 0x80 + +// status registers +#define DS3231_STATUSL_A1F 0x01 +#define DS3231_STATUSL_A2F 0x02 +#define DS3231_STATUSL_BSY 0x04 +#define DS3231_STATUSL_EN32KHZ 0x08 +#define DS3231_STATUSL_OSF 0x80 + +#endif \ No newline at end of file diff --git a/libraries/States/ControlColorState.cpp b/libraries/States/ControlColorState.cpp new file mode 100644 index 0000000..d03b6a6 --- /dev/null +++ b/libraries/States/ControlColorState.cpp @@ -0,0 +1,128 @@ +#include + +ControlColorState::ControlColorState(AT24C32 &_at24c32) +{ + at24c32 = _at24c32; +} + +void ControlColorState::leftPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::COLOR_R: + controlState = ControlStates::COLOR_B; + break; + case ControlStates::COLOR_G: + controlState = ControlStates::COLOR_R; + break; + case ControlStates::COLOR_B: + controlState = ControlStates::COLOR_G; + break; + } +}; + +void ControlColorState::rightPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::COLOR_R: + controlState = ControlStates::COLOR_G; + break; + case ControlStates::COLOR_G: + controlState = ControlStates::COLOR_B; + break; + case ControlStates::COLOR_B: + controlState = ControlStates::COLOR_R; + break; + } +}; + +void ControlColorState::enterPressed(ViewStates &viewState, ControlStates &controlState) +{ + controlState = ControlStates::VIEW; +}; + +void ControlColorState::decrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::COLOR_R: + decrementColorR(); + break; + case ControlStates::COLOR_G: + decrementColorG(); + break; + case ControlStates::COLOR_B: + decrementColorB(); + break; + } +}; + +void ControlColorState::incrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::COLOR_R: + incrementColorR(); + break; + case ControlStates::COLOR_G: + incrementColorG(); + break; + case ControlStates::COLOR_B: + incrementColorB(); + break; + } +}; + +void ControlColorState::decrementColorR() +{ + uint8_t color = at24c32.read(COLOR_ADDRESS); + uint8_t red = (color >> 5); + red = (red - 1) % 8; + color = (red << 5) + (color & 0x1F); + at24c32.write(COLOR_ADDRESS, color); +} +void ControlColorState::incrementColorR() +{ + uint8_t color = at24c32.read(COLOR_ADDRESS); + uint8_t red = (color >> 5); + red = (red + 1) % 8; + color = (red << 5) + (color & 0x1F); + at24c32.write(COLOR_ADDRESS, color); +} + +void ControlColorState::decrementColorG() +{ + uint8_t color = at24c32.read(COLOR_ADDRESS); + uint8_t green = (color >> 2) & 0x07; + green = (green - 1) % 8; + color = (green << 2) + (color & 0xE3); + at24c32.write(COLOR_ADDRESS, color); +} + +void ControlColorState::incrementColorG() +{ + uint8_t color = at24c32.read(COLOR_ADDRESS); + uint8_t green = (color >> 2) & 0x07; + green = (green + 1) % 8; + color = (green << 2) + (color & 0xE3); + at24c32.write(COLOR_ADDRESS, color); +} + +void ControlColorState::decrementColorB() +{ + uint8_t color = at24c32.read(COLOR_ADDRESS); + uint8_t blue = color & 0x03; + blue = (blue - 1) % 4; + color = blue + (color & 0xFC); + at24c32.write(COLOR_ADDRESS, color); +} + +void ControlColorState::incrementColorB() +{ + uint8_t color = at24c32.read(COLOR_ADDRESS); + uint8_t blue = color & 0x03; + blue = (blue + 1) % 4; + color = blue + (color & 0xFC); + at24c32.write(COLOR_ADDRESS, color); +} \ No newline at end of file diff --git a/libraries/States/ControlDateState.cpp b/libraries/States/ControlDateState.cpp new file mode 100644 index 0000000..a5e101f --- /dev/null +++ b/libraries/States/ControlDateState.cpp @@ -0,0 +1,77 @@ + +#include + +ControlDateState::ControlDateState(DS3231 &_ds3231) +{ + ds3231 = _ds3231; +} + +void ControlDateState::leftPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::DATE_YEAR: + controlState = ControlStates::DATE_MONTH; + break; + case ControlStates::DATE_MONTH: + controlState = ControlStates::DATE_DATE; + break; + case ControlStates::DATE_DATE: + controlState = ControlStates::DATE_YEAR; + break; + } +}; + +void ControlDateState::rightPressed(ViewStates &viewState, ControlStates &controlState) +{ + + switch (controlState) + { + case ControlStates::DATE_DATE: + controlState = ControlStates::DATE_MONTH; + break; + case ControlStates::DATE_MONTH: + controlState = ControlStates::DATE_YEAR; + break; + case ControlStates::DATE_YEAR: + controlState = ControlStates::DATE_DATE; + break; + } +}; + +void ControlDateState::enterPressed(ViewStates &viewState, ControlStates &controlState) +{ + controlState = ControlStates::VIEW; +}; + +void ControlDateState::decrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::DATE_DATE: + ds3231.decrementDate(); + break; + case ControlStates::DATE_MONTH: + ds3231.decrementMonth(); + break; + case ControlStates::DATE_YEAR: + ds3231.decrementYear(); + break; + } +}; + +void ControlDateState::incrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::DATE_DATE: + ds3231.incrementDate(); + break; + case ControlStates::DATE_MONTH: + ds3231.incrementMonth(); + break; + case ControlStates::DATE_YEAR: + ds3231.incrementYear(); + break; + } +}; \ No newline at end of file diff --git a/libraries/States/ControlSecondsState.cpp b/libraries/States/ControlSecondsState.cpp new file mode 100644 index 0000000..f113c7b --- /dev/null +++ b/libraries/States/ControlSecondsState.cpp @@ -0,0 +1,26 @@ + +#include + +ControlSecondsState::ControlSecondsState(DS3231 &_ds3231) +{ + ds3231 = _ds3231; +} + +void ControlSecondsState::leftPressed(ViewStates &viewState, ControlStates &controlState){}; + +void ControlSecondsState::rightPressed(ViewStates &viewState, ControlStates &controlState){}; + +void ControlSecondsState::enterPressed(ViewStates &viewState, ControlStates &controlState) +{ + controlState = ControlStates::VIEW; +}; + +void ControlSecondsState::decrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + ds3231.decrementSeconds(); +}; + +void ControlSecondsState::incrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + ds3231.incrementSeconds(); +}; \ No newline at end of file diff --git a/libraries/States/ControlStates.h b/libraries/States/ControlStates.h new file mode 100644 index 0000000..1a7b3d8 --- /dev/null +++ b/libraries/States/ControlStates.h @@ -0,0 +1,130 @@ +#ifndef ControlState_h +#define ControlState_h + +#include +#include +#include + +/* + abstract control state + */ +class ControlState +{ +public: + virtual void leftPressed(ViewStates &viewState, ControlStates &controlState) = 0; + virtual void rightPressed(ViewStates &viewState, ControlStates &controlState) = 0; + virtual void enterPressed(ViewStates &viewState, ControlStates &controlState) = 0; + virtual void decrementPressed(ViewStates &viewState, ControlStates &controlState) = 0; + virtual void incrementPressed(ViewStates &viewState, ControlStates &controlState) = 0; +}; + +/* + control view state + */ +class ControlViewState : public ControlState +{ +public: + ControlViewState(AT24C32 &_at24c32); + void leftPressed(ViewStates &viewState, ControlStates &controlState); + void rightPressed(ViewStates &viewState, ControlStates &controlState); + void enterPressed(ViewStates &viewState, ControlStates &controlState); + void decrementPressed(ViewStates &viewState, ControlStates &controlState); + void incrementPressed(ViewStates &viewState, ControlStates &controlState); + +protected: + AT24C32 at24c32; +}; + +/* + control time state + */ +class ControlTimeState : public ControlState +{ +public: + ControlTimeState(DS3231 &_ds3231, AT24C32 &_at24c32); + void leftPressed(ViewStates &viewState, ControlStates &controlState); + void rightPressed(ViewStates &viewState, ControlStates &controlState); + void enterPressed(ViewStates &viewState, ControlStates &controlState); + void decrementPressed(ViewStates &viewState, ControlStates &controlState); + void incrementPressed(ViewStates &viewState, ControlStates &controlState); + +protected: + DS3231 ds3231; + AT24C32 at24c32; +}; + +/* + control seconds state + */ +class ControlSecondsState : public ControlState +{ +public: + ControlSecondsState(DS3231 &_ds3231); + void leftPressed(ViewStates &viewState, ControlStates &controlState); + void rightPressed(ViewStates &viewState, ControlStates &controlState); + void enterPressed(ViewStates &viewState, ControlStates &controlState); + void decrementPressed(ViewStates &viewState, ControlStates &controlState); + void incrementPressed(ViewStates &viewState, ControlStates &controlState); + +protected: + DS3231 ds3231; +}; + +/* + control date state + */ +class ControlDateState : public ControlState +{ +public: + ControlDateState(DS3231 &_ds3231); + void leftPressed(ViewStates &viewState, ControlStates &controlState); + void rightPressed(ViewStates &viewState, ControlStates &controlState); + void enterPressed(ViewStates &viewState, ControlStates &controlState); + void decrementPressed(ViewStates &viewState, ControlStates &controlState); + void incrementPressed(ViewStates &viewState, ControlStates &controlState); + +protected: + DS3231 ds3231; +}; + +/* + control color value state + */ +class ControlColorState : public ControlState +{ +public: + ControlColorState(AT24C32 &_at24c32); + void leftPressed(ViewStates &viewState, ControlStates &controlState); + void rightPressed(ViewStates &viewState, ControlStates &controlState); + void enterPressed(ViewStates &viewState, ControlStates &controlState); + void decrementPressed(ViewStates &viewState, ControlStates &controlState); + void incrementPressed(ViewStates &viewState, ControlStates &controlState); + +protected: + AT24C32 at24c32; + void decrementColorR(); + void incrementColorR(); + void decrementColorG(); + void incrementColorG(); + void decrementColorB(); + void incrementColorB(); +}; + +/* + control text state + */ +class ControlTextState : public ControlState +{ +public: + ControlTextState(AT24C32 &_at24c32); + void leftPressed(ViewStates &viewState, ControlStates &controlState); + void rightPressed(ViewStates &viewState, ControlStates &controlState); + void enterPressed(ViewStates &viewState, ControlStates &controlState); + void decrementPressed(ViewStates &viewState, ControlStates &controlState); + void incrementPressed(ViewStates &viewState, ControlStates &controlState); + +protected: + AT24C32 at24c32; +}; + +#endif \ No newline at end of file diff --git a/libraries/States/ControlTextState..cpp b/libraries/States/ControlTextState..cpp new file mode 100644 index 0000000..1b86d75 --- /dev/null +++ b/libraries/States/ControlTextState..cpp @@ -0,0 +1,62 @@ + +#include + +ControlTextState::ControlTextState(AT24C32 &_at24c32) +{ + at24c32 = _at24c32; +} + +void ControlTextState::leftPressed(ViewStates &viewState, ControlStates &controlState) +{ + uint8_t length = at24c32.read(TEXT_SIZE_ADDRESS); + if (length > 2) + { + length--; + at24c32.write(TEXT_SIZE_ADDRESS, length); + } +}; + +void ControlTextState::rightPressed(ViewStates &viewState, ControlStates &controlState) +{ + uint8_t length = at24c32.read(TEXT_SIZE_ADDRESS); + if (length < 0xFF) + { + length++; + at24c32.write(TEXT_SIZE_ADDRESS, length); + } +}; + +void ControlTextState::enterPressed(ViewStates &viewState, ControlStates &controlState) +{ + controlState = ControlStates::VIEW; +}; + +void ControlTextState::decrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + uint8_t position = at24c32.read(TEXT_SIZE_ADDRESS) - 1; + uint8_t char1 = at24c32.read(TEXT_ADDRESS + position); + if (char1 > 0) + { + char1--; + } + else + { + char1 = 0xFF; + } + at24c32.write(TEXT_ADDRESS + position, char1); +}; + +void ControlTextState::incrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + uint8_t position = at24c32.read(TEXT_SIZE_ADDRESS) - 1; + uint8_t char1 = at24c32.read(TEXT_ADDRESS + position); + if (char1 < 0xFF) + { + char1++; + } + else + { + char1 = 0; + } + at24c32.write(TEXT_ADDRESS + position, char1); +}; \ No newline at end of file diff --git a/libraries/States/ControlTimeState.cpp b/libraries/States/ControlTimeState.cpp new file mode 100644 index 0000000..57418bd --- /dev/null +++ b/libraries/States/ControlTimeState.cpp @@ -0,0 +1,82 @@ + +#include + +ControlTimeState::ControlTimeState(DS3231 &_ds3231, AT24C32 &_at24c32) +{ + ds3231 = _ds3231; + at24c32 = _at24c32; +} + +void ControlTimeState::leftPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::TIME_HOURS: + controlState = ControlStates::TIME_MODE; + break; + case ControlStates::TIME_MINUTES: + controlState = ControlStates::TIME_HOURS; + break; + case ControlStates::TIME_MODE: + controlState = ControlStates::TIME_MINUTES; + break; + } +}; + +void ControlTimeState::rightPressed(ViewStates &viewState, ControlStates &controlState) +{ + + switch (controlState) + { + case ControlStates::TIME_HOURS: + controlState = ControlStates::TIME_MINUTES; + break; + case ControlStates::TIME_MINUTES: + controlState = ControlStates::TIME_MODE; + break; + case ControlStates::TIME_MODE: + controlState = ControlStates::TIME_HOURS; + break; + } +}; + +void ControlTimeState::enterPressed(ViewStates &viewState, ControlStates &controlState) +{ + controlState = ControlStates::VIEW; +}; + +void ControlTimeState::decrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::TIME_HOURS: + ds3231.decrementHours(); + break; + case ControlStates::TIME_MINUTES: + ds3231.decrementMinutes(); + break; + case ControlStates::TIME_MODE: + uint8_t mode = at24c32.read(TIME_MODE_ADDRESS); + mode = (mode - 1) % 3; + at24c32.write(TIME_MODE_ADDRESS, mode); + break; + } +}; + +void ControlTimeState::incrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (controlState) + { + case ControlStates::TIME_HOURS: + ds3231.incrementHours(); + break; + case ControlStates::TIME_MINUTES: + ds3231.incrementMinutes(); + break; + case ControlStates::TIME_MODE: + uint8_t mode = at24c32.read(TIME_MODE_ADDRESS); + mode = (mode + 1) % 3; + at24c32.write(TIME_MODE_ADDRESS, mode); + break; + } +}; \ No newline at end of file diff --git a/libraries/States/ControlViewState.cpp b/libraries/States/ControlViewState.cpp new file mode 100644 index 0000000..1ca29e5 --- /dev/null +++ b/libraries/States/ControlViewState.cpp @@ -0,0 +1,92 @@ +#include + +ControlViewState::ControlViewState(AT24C32 &_at24c32) +{ + at24c32 = _at24c32; +} + +void ControlViewState::leftPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (viewState) + { + case ViewStates::TIME: + viewState = ViewStates::LED_DEMO; + break; + case ViewStates::TEMPERATURE: + viewState = ViewStates::TIME; + break; + case ViewStates::SECONDS: + viewState = ViewStates::TEMPERATURE; + break; + case ViewStates::DATE: + viewState = ViewStates::SECONDS; + break; + case ViewStates::TEXT: + viewState = ViewStates::DATE; + break; + case ViewStates::LED_DEMO: + viewState = ViewStates::TEXT; + break; + } +}; + +void ControlViewState::rightPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (viewState) + { + case ViewStates::TIME: + viewState = ViewStates::TEMPERATURE; + break; + case ViewStates::TEMPERATURE: + viewState = ViewStates::SECONDS; + break; + case ViewStates::SECONDS: + viewState = ViewStates::DATE; + break; + case ViewStates::DATE: + viewState = ViewStates::TEXT; + break; + case ViewStates::TEXT: + viewState = ViewStates::LED_DEMO; + break; + case ViewStates::LED_DEMO: + viewState = ViewStates::TIME; + break; + } +}; + +void ControlViewState::enterPressed(ViewStates &viewState, ControlStates &controlState) +{ + switch (viewState) + { + case ViewStates::TIME: + controlState = ControlStates::TIME_HOURS; + break; + case ViewStates::SECONDS: + controlState = ControlStates::TIME_SECONDS; + break; + case ViewStates::DATE: + controlState = ControlStates::DATE_DATE; + break; + case ViewStates::TEXT: + controlState = ControlStates::TEXT; + break; + case ViewStates::LED_DEMO: + controlState = ControlStates::COLOR_R; + break; + } +}; + +void ControlViewState::decrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + uint8_t value = at24c32.read(BRIGHTNESS_ADDRESS); + value = (value - 5) % 256; + at24c32.write(BRIGHTNESS_ADDRESS, value); +}; + +void ControlViewState::incrementPressed(ViewStates &viewState, ControlStates &controlState) +{ + uint8_t value = at24c32.read(BRIGHTNESS_ADDRESS); + value = (value + 5) % 256; + at24c32.write(BRIGHTNESS_ADDRESS, value); +}; \ No newline at end of file diff --git a/libraries/States/States.h b/libraries/States/States.h new file mode 100644 index 0000000..8357fe1 --- /dev/null +++ b/libraries/States/States.h @@ -0,0 +1,50 @@ +#ifndef States_h +#define States_h + +/** + view states + */ +enum class ViewStates +{ + TIME, + SECONDS, + TEMPERATURE, + DATE, + TEXT, + LED_DEMO, + REMOTE +}; + +/** + control states + */ +enum class ControlStates +{ + VIEW, + TIME_HOURS, + TIME_MINUTES, + TIME_MODE, + TIME_SECONDS, + COLOR_R, + COLOR_G, + COLOR_B, + DATE_DATE, + DATE_MONTH, + DATE_YEAR, + TEXT +}; + +/** + remote control states + */ +enum class RemoteStates +{ + VIEW, + TIME, + COLOR, + DATE, + TEXT, + DRAW +}; + +#endif \ No newline at end of file diff --git a/libraries/States/ViewDateState.cpp b/libraries/States/ViewDateState.cpp new file mode 100644 index 0000000..ff99e0c --- /dev/null +++ b/libraries/States/ViewDateState.cpp @@ -0,0 +1,96 @@ + +#include + +ViewDateState::ViewDateState(DS3231 &_ds3231, AT24C32 &_at24c32, char _delimiter) : ViewTextState(at24c32) +{ + ds3231 = _ds3231; + at24c32 = _at24c32; + delimiter = _delimiter; + renderOffset = (millis() / TEXT_INTERVAL); +}; + +void ViewDateState::render(uint8_t matrix[121], ControlStates controlState) +{ + + bool const blink = (millis() / CONTROL_BLINK_INTERVAL) % 2 == 0; + + length = 0; + position = 0; + + uint8_t date = ds3231.getDate(); + uint8_t month = ds3231.getMonth(); + int16_t year = ds3231.getYear(); + + if (controlState == ControlStates::DATE_DATE && blink) + { + length = 2; + text[0] = (date / 10) + 0x30; + text[1] = (date % 10) + 0x30; + ViewTextState::writeChars(matrix); + } + else if (controlState == ControlStates::DATE_MONTH && blink) + { + length = 2; + text[0] = (month / 10) + 0x30; + text[1] = (month % 10) + 0x30; + ViewTextState::writeChars(matrix); + } + else if (controlState == ControlStates::DATE_YEAR && blink) + { + if (year == 2000 || year == 1900) + { + length = 4; + text[0] = ((year / 100) / 10) + 0x30; + text[1] = ((year / 100) % 10) + 0x30; + position = (millis() / TEXT_INTERVAL) % length; + } + else + { + length = 2; + } + if (year > 1999) + { + year = year - 2000; + } + else + { + year = year - 1900; + } + + text[length - 2] = (year / 10) + 0x30; + text[length - 1] = (year % 10) + 0x30; + + ViewTextState::writeChars(matrix); + } + else if (controlState != ControlStates::DATE_DATE && controlState != ControlStates::DATE_MONTH && controlState != ControlStates::DATE_YEAR) + { + length = 10; + text[0] = (date / 10) + 0x30; + text[1] = (date % 10) + 0x30; + + text[2] = char(delimiter); + + text[3] = (month / 10) + 0x30; + text[4] = (month % 10) + 0x30; + + text[5] = char(delimiter); + + text[6] = ((year / 100) / 10) + 0x30; + text[7] = ((year / 100) % 10) + 0x30; + if (year > 1999) + { + text[8] = ((year - 2000) / 10) + 0x30; + text[9] = ((year - 2000) % 10) + 0x30; + } + else + { + text[8] = ((year - 1900) / 10) + 0x30; + text[9] = ((year - 1900) % 10) + 0x30; + } + + position = (millis() / TEXT_INTERVAL - renderOffset - 1) % length; + ViewTextState::writeChars(matrix); + } + + renderBinaryClock(matrix, ds3231); +}; \ No newline at end of file diff --git a/libraries/States/ViewLEDState.cpp b/libraries/States/ViewLEDState.cpp new file mode 100644 index 0000000..8cc6e07 --- /dev/null +++ b/libraries/States/ViewLEDState.cpp @@ -0,0 +1,76 @@ + +#include + +ViewLEDState::ViewLEDState(){ + +}; + +void ViewLEDState::render(uint8_t matrix[121], ControlStates controlState) +{ + + if (controlState != ControlStates::COLOR_R && controlState != ControlStates::COLOR_G && controlState != ControlStates::COLOR_B) + { + int const color = (millis() / 500) % 256; + + for (int i = 0; i < 121; i++) + { + matrix[i] = color - i % 256; + } + } + else + { + // special color edit view + bool const blink = (millis() / CONTROL_BLINK_INTERVAL) % 2 == 0; + + if (controlState != ControlStates::COLOR_R || blink) + { + uint8_t red = color >> 5; + matrix[0] = 0x07 << 5; + matrix[10] = 0x07 << 5; + matrix[11] = 0x07 << 5; + matrix[21] = 0x07 << 5; + for (int i = 0; i < red; i++) + { + // red + matrix[i + 2] = red << 5; + matrix[i + 13] = red << 5; + } + } + + if (controlState != ControlStates::COLOR_G || blink) + { + uint8_t green = (color >> 2) & 0x07; + matrix[22] = 0x07 << 2; + matrix[32] = 0x07 << 2; + matrix[33] = 0x07 << 2; + matrix[43] = 0x07 << 2; + for (int i = 0; i < green; i++) + { + // green + matrix[i + 24] = green << 2; + matrix[i + 35] = green << 2; + } + } + + if (controlState != ControlStates::COLOR_B || blink) + { + + uint8_t blue = color & 0x03; + matrix[44] = 0x03; + matrix[54] = 0x03; + matrix[55] = 0x03; + matrix[65] = 0x03; + for (int i = 0; i < blue; i++) + { + // blue + matrix[i + 46] = blue; + matrix[i + 57] = blue; + } + } + + for (int i = 77; i < 121; i++) + { + matrix[i] = color; + } + } +} \ No newline at end of file diff --git a/libraries/States/ViewRemoteState.cpp b/libraries/States/ViewRemoteState.cpp new file mode 100644 index 0000000..b84d43d --- /dev/null +++ b/libraries/States/ViewRemoteState.cpp @@ -0,0 +1,11 @@ + +#include + +ViewRemoteState::ViewRemoteState(){ + +}; + +void ViewRemoteState::render(uint8_t matrix[121], ControlStates controlState) +{ + // nothing, LEDs set via remote control +} \ No newline at end of file diff --git a/libraries/States/ViewSecondsState.cpp b/libraries/States/ViewSecondsState.cpp new file mode 100644 index 0000000..34854b8 --- /dev/null +++ b/libraries/States/ViewSecondsState.cpp @@ -0,0 +1,28 @@ + +#include + +ViewSecondsState::ViewSecondsState(DS3231 &_ds3231, AT24C32 &_at24c32) : ViewTextState(at24c32) +{ + ds3231 = _ds3231; + at24c32 = _at24c32; +}; + +void ViewSecondsState::render(uint8_t matrix[121], ControlStates controlState) +{ + uint8_t const seconds = ds3231.getSeconds(); + + bool const blink = (millis() / CONTROL_BLINK_INTERVAL) % 2 == 0; + + length = 0; + + if (controlState != ControlStates::TIME_SECONDS || blink) + { + length = 2; + text[0] = (seconds / 10) + 0x30; + text[1] = (seconds % 10) + 0x30; + } + + ViewTextState::writeChars(matrix); + + renderBinaryClock(matrix, ds3231); +} \ No newline at end of file diff --git a/libraries/States/ViewState.cpp b/libraries/States/ViewState.cpp new file mode 100644 index 0000000..06f63dd --- /dev/null +++ b/libraries/States/ViewState.cpp @@ -0,0 +1,29 @@ + +#include + +void ViewState::setColor(uint8_t _color) +{ + color = _color; +}; + +void ViewState::renderBinaryClock(uint8_t matrix[121], DS3231 &ds3231) +{ + uint8_t h = ds3231.getHours() % 12; + uint8_t mm = ds3231.getMinutes(); + + for (int b = 0; b < 4; b++) + { + if (bitRead(h, b)) + { + matrix[110 + b] = color; + } + } + + for (int b = 0; b < 6; b++) + { + if (bitRead(mm, b)) + { + matrix[115 + b] = color; + } + } +}; \ No newline at end of file diff --git a/libraries/States/ViewStates.h b/libraries/States/ViewStates.h new file mode 100644 index 0000000..0f53b99 --- /dev/null +++ b/libraries/States/ViewStates.h @@ -0,0 +1,142 @@ +#ifndef ViewState_h +#define ViewState_h + +#include +#include +#include + +using namespace std; + +// I2C address +#define TEXT_INTERVAL 1000 +#define CONTROL_BLINK_INTERVAL 250 + +/** + led matrix entry + */ +struct matrix_entry +{ + uint8_t row; + uint8_t columnFrom; + uint8_t columnTo; + bool notNull; +}; + +/** + abstract view state + */ +class ViewState +{ +public: + virtual void render(uint8_t matrix[121], ControlStates controlState) = 0; + void setColor(uint8_t _color); + +protected: + void renderBinaryClock(uint8_t matrix[121], DS3231 &ds3231); + uint8_t color = 0xFF; +}; + +/** + view time state + */ +class ViewTimeState : public ViewState +{ +public: + ViewTimeState(DS3231 &_ds3231, AT24C32 &_at24c32); + void render(uint8_t matrix[121], ControlStates controlState); + +protected: + DS3231 ds3231; + AT24C32 at24c32; + matrix_entry text[2]; + matrix_entry hours[12][2]; + matrix_entry minutes[12][3]; + uint8_t increment; + uint8_t mode = 0; + void init(); + void setWord(uint8_t matrix[121], matrix_entry word); + void setWessi(); + void setOssi(); +}; + +/** + view text state + */ +class ViewTextState : public ViewState +{ +public: + ViewTextState(AT24C32 &_at24c32); + void render(uint8_t matrix[121], ControlStates controlState); + +protected: + void writeText(uint8_t matrix[121]); + void writeChars(uint8_t matrix[121]); + AT24C32 at24c32; + uint8_t text[0xFF]; + uint8_t length = 0; + uint8_t position = 0; + uint8_t v_offset = 1; + long renderOffset; +}; + +/** + view seconds state + */ +class ViewSecondsState : public ViewTextState +{ +public: + ViewSecondsState(DS3231 &_ds3231, AT24C32 &_at24c32); + void render(uint8_t matrix[121], ControlStates controlState); + +protected: + DS3231 ds3231; +}; + +/** + view temperature state + */ +class ViewTemperatureState : public ViewTextState +{ +public: + ViewTemperatureState(DS3231 &_ds3231, AT24C32 &_at24c32); + void render(uint8_t matrix[121], ControlStates controlState); + +protected: + DS3231 ds3231; +}; + +/** + view date state + */ +class ViewDateState : public ViewTextState +{ +public: + ViewDateState(DS3231 &_ds3231, AT24C32 &_at24c32, char _delimiter); + void render(uint8_t matrix[121], ControlStates controlState); + +protected: + DS3231 ds3231; + char delimiter; +}; + +/** + view LED demo state + */ +class ViewLEDState : public ViewState +{ +public: + ViewLEDState(); + void render(uint8_t matrix[121], ControlStates controlState); +}; + +/** + view Remote demo state + */ +class ViewRemoteState : public ViewState +{ +public: + ViewRemoteState(); + void render(uint8_t matrix[121], ControlStates controlState); +}; + +#endif \ No newline at end of file diff --git a/libraries/States/ViewTemperatureState.cpp b/libraries/States/ViewTemperatureState.cpp new file mode 100644 index 0000000..9765c8a --- /dev/null +++ b/libraries/States/ViewTemperatureState.cpp @@ -0,0 +1,28 @@ + +#include + +ViewTemperatureState::ViewTemperatureState(DS3231 &_ds3231, AT24C32 &_at24c32) : ViewTextState(at24c32) +{ + ds3231 = _ds3231; + at24c32 = _at24c32; +}; + +void ViewTemperatureState::render(uint8_t matrix[121], ControlStates controlState) +{ + // ° + matrix[9] = color; + matrix[10] = color; + matrix[20] = color; + matrix[21] = color; + + int temperature = floor(ds3231.getTemperature()); + + length = 2; + + text[0] = (temperature / 10) + 0x30; + text[1] = (temperature % 10) + 0x30; + + ViewTextState::writeChars(matrix); + + renderBinaryClock(matrix, ds3231); +} \ No newline at end of file diff --git a/libraries/States/ViewTextState.cpp b/libraries/States/ViewTextState.cpp new file mode 100644 index 0000000..72979db --- /dev/null +++ b/libraries/States/ViewTextState.cpp @@ -0,0 +1,85 @@ + +#include + +ViewTextState::ViewTextState(AT24C32 &_at24c32) +{ + at24c32 = _at24c32; + renderOffset = (millis() / TEXT_INTERVAL); +}; + +void ViewTextState::render(uint8_t matrix[121], ControlStates controlState) +{ + length = at24c32.read(TEXT_SIZE_ADDRESS); + + if (controlState != ControlStates::TEXT) + { + for (uint8_t i = 0; i < length; i++) + { + text[i] = at24c32.read(TEXT_ADDRESS + i); + } + writeText(matrix); + } + else + { + bool const blink = (millis() / CONTROL_BLINK_INTERVAL) % 2 == 0; + position = 0; + text[0] = 0x20; + text[1] = 0x20; + if (length > 2) + { + text[0] = at24c32.read(TEXT_ADDRESS + length - 2); + if (blink) + { + text[1] = at24c32.read(TEXT_ADDRESS + length - 1); + } + } + else if (length > 1 && blink) + { + text[0] = at24c32.read(TEXT_ADDRESS + length - 1); + } + writeChars(matrix); + } +} + +void ViewTextState::writeText(uint8_t matrix[121]) +{ + position = (millis() / TEXT_INTERVAL - renderOffset - 1) % (length + 2); + writeChars(matrix); +} + +void ViewTextState::writeChars(uint8_t matrix[121]) +{ + uint8_t char1 = 0x20; + + uint8_t char2 = 0x20; + + if (length > position) + { + char1 = text[position]; + } + + if (length > position + 1) + { + char2 = text[position + 1]; + } + + for (int col = 0; col < 5; col++) + { + // created ascii chars in 'ascii_memory.ino' to AT23C32 epromm + uint8_t char1Byte = at24c32.read(char1 * 5 + col); + uint8_t char2Byte = at24c32.read(char2 * 5 + col); + + for (int row = 0; row < 8; row++) + { + if (!!(char1Byte & (1 << row))) + { + matrix[(row + v_offset) * 11 + col] = color; + } + + if (!!(char2Byte & (1 << row))) + { + matrix[(row + v_offset) * 11 + col + 6] = color; + } + } + } +} \ No newline at end of file diff --git a/libraries/States/ViewTimeState.cpp b/libraries/States/ViewTimeState.cpp new file mode 100644 index 0000000..daa3f03 --- /dev/null +++ b/libraries/States/ViewTimeState.cpp @@ -0,0 +1,219 @@ + +#include + +ViewTimeState::ViewTimeState(DS3231 &_ds3231, AT24C32 &_at24c32) +{ + ds3231 = _ds3231; + at24c32 = _at24c32; + init(); +} + +/* + default german matrix layout + + 'E', 'S', 'K', 'I', 'S', 'T', 'L', 'F', 'Ü', 'N', 'F', + 'Z', 'E', 'H', 'N', 'Z', 'W', 'A', 'N', 'Z', 'I', 'G', + 'D', 'R', 'E', 'I', 'V', 'I', 'E', 'R', 'T', 'E', 'L', + 'T', 'A', 'N', 'A', 'C', 'H', 'V', 'O', 'R', 'J', 'M', + 'H', 'A', 'L', 'B', 'X', 'Z', 'W', 'Ö', 'L', 'F', 'P', + 'Z', 'W', 'E', 'I', 'N', 'S', 'I', 'E', 'B', 'E', 'N', + 'K', 'D', 'R', 'E', 'I', 'R', 'H', 'F', 'Ü', 'N', 'F', + 'E', 'L', 'F', 'N', 'E', 'U', 'N', 'V', 'I', 'E', 'R', + 'W', 'A', 'C', 'H', 'T', 'Z', 'E', 'H', 'N', 'R', 'S', + 'B', 'S', 'E', 'C', 'H', 'S', 'F', 'M', 'U', 'H', 'R', + 'B', 'S', 'E', 'C', 'H', 'S', 'F', 'M', 'U', 'H', 'R', + '□', '□', '□', '□', '▣', '□', '□', '□', '□', '□', '□', + + */ +void ViewTimeState::init() +{ + text[0] = {0, 0, 1, true}; + text[1] = {0, 3, 5, true}; + + hours[0][0] = {4, 5, 9, true}; + hours[0][1] = {0, 0, 0, false}; + hours[1][0] = {5, 2, 4, true}; + hours[1][1] = {5, 2, 5, true}; + hours[2][0] = {5, 0, 3, true}; + hours[2][1] = {0, 0, 0, false}; + hours[3][0] = {6, 1, 4, true}; + hours[3][1] = {0, 0, 0, false}; + hours[4][0] = {7, 7, 10, true}; + hours[4][1] = {0, 0, 0, false}; + hours[5][0] = {6, 7, 10, true}; + hours[5][1] = {0, 0, 0, false}; + hours[6][0] = {9, 1, 5, true}; + hours[6][1] = {0, 0, 0, false}; + hours[7][0] = {5, 5, 10, true}; + hours[7][1] = {0, 0, 0, false}; + hours[8][0] = {8, 1, 4, true}; + hours[8][1] = {0, 0, 0, false}; + hours[9][0] = {7, 3, 6, true}; + hours[9][1] = {0, 0, 0, false}; + hours[10][0] = {8, 5, 8, true}; + hours[10][1] = {0, 0, 0, false}; + hours[11][0] = {7, 0, 2, true}; + hours[11][1] = {0, 0, 0, false}; + + // 0 + minutes[0][0] = {9, 8, 10, true}; + minutes[0][1] = {0, 0, 0, false}; + minutes[0][2] = {0, 0, 0, false}; + // 5 + minutes[1][0] = {0, 7, 10, true}; + minutes[1][1] = {3, 2, 5, true}; + minutes[1][2] = {0, 0, 0, false}; + // 10 + minutes[2][0] = {1, 0, 3, true}; + minutes[2][1] = {3, 2, 5, true}; + minutes[2][2] = {0, 0, 0, false}; + // 15 + minutes[3][0] = {2, 4, 10, true}; + minutes[3][1] = {3, 2, 5, true}; + minutes[3][2] = {0, 0, 0, false}; + // 20 + minutes[4][0] = {1, 4, 10, true}; + minutes[4][1] = {3, 2, 5, true}; + minutes[4][2] = {0, 0, 0, false}; + // 25 + minutes[5][0] = {0, 7, 10, true}; + minutes[5][1] = {3, 6, 8, true}; + minutes[5][2] = {4, 0, 3, true}; + // 30 + minutes[6][0] = {4, 0, 3, true}; + minutes[6][1] = {0, 0, 0, false}; + minutes[6][2] = {0, 0, 0, false}; + // 35 + minutes[7][0] = {0, 7, 10, true}; + minutes[7][1] = {3, 2, 5, true}; + minutes[7][2] = {4, 0, 3, true}; + // 40 + minutes[8][0] = {1, 4, 10, true}; + minutes[8][1] = {3, 6, 8, true}; + minutes[8][2] = {0, 0, 0, false}; + // 45 + minutes[9][0] = {2, 4, 10, true}; + minutes[9][1] = {3, 6, 8, true}; + minutes[9][2] = {0, 0, 0, false}; + // 50 + minutes[10][0] = {1, 0, 3, true}; + minutes[10][1] = {3, 6, 8, true}; + minutes[10][2] = {0, 0, 0, false}; + // 55 + minutes[11][0] = {0, 7, 10, true}; + minutes[11][1] = {3, 6, 8, true}; + minutes[11][2] = {0, 0, 0, false}; + + increment = 24; +} + +void ViewTimeState::setWessi() +{ + init(); + minutes[4][0] = {1, 0, 3, true}; + minutes[4][1] = {3, 6, 8, true}; + minutes[4][2] = {4, 0, 3, true}; + + minutes[8][0] = {1, 0, 3, true}; + minutes[8][1] = {3, 2, 5, true}; + minutes[8][2] = {4, 0, 3, true}; + + increment = 19; +} + +void ViewTimeState::setOssi() +{ + setWessi(); + + minutes[3][0] = {2, 4, 10, true}; + minutes[3][1] = {0, 0, 0, false}; + + minutes[9][0] = {2, 0, 10, true}; + minutes[9][1] = {0, 0, 0, false}; + increment = 14; +} + +void ViewTimeState::setWord(uint8_t matrix[121], matrix_entry word) +{ + int row; + for (int i = word.columnFrom; i <= word.columnTo; i++) + { + row = word.row * 11 + i; + matrix[row] = color; + } +} + +void ViewTimeState::render(uint8_t matrix[121], ControlStates controlState) +{ + + uint8_t currentMode = at24c32.read(TIME_MODE_ADDRESS); + + if (mode != currentMode) + { + mode = currentMode; + switch (mode) + { + case 1: + setWessi(); + break; + case 2: + setOssi(); + break; + default: + init(); + } + } + + bool const blink = (millis() / CONTROL_BLINK_INTERVAL) % 2 == 0; + + if (controlState != ControlStates::TIME_MODE || blink) + { + setWord(matrix, text[0]); + setWord(matrix, text[1]); + } + + uint8_t mm = ds3231.getMinutes(); + uint8_t m = mm / 5; + uint8_t h = ds3231.getHours() % 12; + uint8_t s = ds3231.getSeconds(); + + // increment hours + if (mm > increment) + { + h = (h + 1) % 12; + } + + // set hours + if (controlState != ControlStates::TIME_HOURS || blink) + { + setWord(matrix, hours[h][0]); + if (mm >= 5 && hours[h][1].notNull == true) + { + setWord(matrix, hours[h][1]); + } + } + + // set 5 minutes + if (controlState != ControlStates::TIME_MINUTES || blink) + { + for (int i = 0; i < 3; i++) + { + if (minutes[m][i].notNull == true) + { + setWord(matrix, minutes[m][i]); + } + } + } + + // set minutes + if (mm % 5 > 0) + { + if (controlState != ControlStates::TIME_MINUTES || blink) + { + setWord(matrix, {10, 0, mm % 5 - 1}); + } + } + + // set seconds + setWord(matrix, {10, 5, 5 + (s / 10)}); +} \ No newline at end of file diff --git a/wordclock.ino b/wordclock.ino new file mode 100644 index 0000000..4c73c47 --- /dev/null +++ b/wordclock.ino @@ -0,0 +1,385 @@ +#include +#include + +#include +#include + +#include +#include +#include +#include + +// debug +#define DEBUG 1 + +// Neopixel +#define MATRIX_PIN 12 +#define MATRIX_SIZE 121 +Adafruit_NeoPixel pixels = Adafruit_NeoPixel(MATRIX_SIZE, MATRIX_PIN, NEO_GRB + NEO_KHZ800); + +// Date view delimiter +#define DATE_DELIMITER '.' + +// Buttons +#define LEFT_PIN 11 +#define DECREMENT_PIN 10 +#define ENTER_PIN 9 +#define INCREMENT_PIN 8 +#define RIGHT_PIN 7 + +Button leftBtn = Button(LEFT_PIN, LOW); +Button decrementBtn = Button(DECREMENT_PIN, LOW); +Button enterBtn = Button(ENTER_PIN, LOW); +Button incrementBtn = Button(INCREMENT_PIN, LOW); +Button rightBtn = Button(RIGHT_PIN, LOW); + +// LED matrix +uint8_t matrix[MATRIX_SIZE]; + +// EPROMM AT24C32 +AT24C32 at24c32; + +// RTC DS3231 +DS3231 ds3231; + +// states +ControlStates controlState = ControlStates::VIEW; +ControlStates oldControlState = ControlStates::VIEW; +ViewStates viewState = ViewStates::TIME; +ViewStates oldViewState = ViewStates::TIME; + +// control state +ControlState *currentControlState = new ControlViewState(at24c32); + +// view state +ViewState *currentViewState = new ViewTimeState(ds3231, at24c32); + +/** + setup + */ +void setup() +{ +#ifdef DEBUG + Serial.begin(9600); +#endif + pixels.begin(); + ds3231.begin(); + at24c32.begin(); + + leftBtn.begin(); + decrementBtn.begin(); + enterBtn.begin(); + incrementBtn.begin(); + rightBtn.begin(); + + viewState = ViewStates(at24c32.read(VIEW_STATE_ADDRESS) % 6); + + printStatus(); +} + +/** + loop + */ +void loop() +{ + checkControlState(); + controls(); + checkViewState(); + // render + renderInterval(); +} + +/** + check current control state and change eventually + */ +void checkControlState() +{ + if (controlState != oldControlState) + { + delete currentControlState; + switch (controlState) + { + case ControlStates::VIEW: + currentControlState = new ControlViewState(at24c32); + break; + case ControlStates::TIME_HOURS: + currentControlState = new ControlTimeState(ds3231, at24c32); + break; + case ControlStates::TIME_MINUTES: + currentControlState = new ControlTimeState(ds3231, at24c32); + break; + case ControlStates::TIME_MODE: + currentControlState = new ControlTimeState(ds3231, at24c32); + break; + case ControlStates::TIME_SECONDS: + currentControlState = new ControlSecondsState(ds3231); + break; + case ControlStates::DATE_DATE: + currentControlState = new ControlDateState(ds3231); + break; + case ControlStates::DATE_MONTH: + currentControlState = new ControlDateState(ds3231); + break; + case ControlStates::DATE_YEAR: + currentControlState = new ControlDateState(ds3231); + break; + case ControlStates::COLOR_R: + currentControlState = new ControlColorState(at24c32); + break; + case ControlStates::COLOR_G: + currentControlState = new ControlColorState(at24c32); + break; + case ControlStates::COLOR_B: + currentControlState = new ControlColorState(at24c32); + break; + case ControlStates::TEXT: + currentControlState = new ControlTextState(at24c32); + break; + default: + currentControlState = new ControlViewState(at24c32); + } + oldControlState = controlState; + + printStatus(); + } +} + +/** + check current view state and change eventually + */ +void checkViewState() +{ + if (viewState != oldViewState) + { + delete currentViewState; + switch (viewState) + { + case ViewStates::TIME: + currentViewState = new ViewTimeState(ds3231, at24c32); + break; + case ViewStates::SECONDS: + currentViewState = new ViewSecondsState(ds3231, at24c32); + break; + case ViewStates::TEMPERATURE: + currentViewState = new ViewTemperatureState(ds3231, at24c32); + break; + case ViewStates::DATE: + currentViewState = new ViewDateState(ds3231, at24c32, DATE_DELIMITER); + break; + case ViewStates::TEXT: + currentViewState = new ViewTextState(at24c32); + break; + case ViewStates::LED_DEMO: + currentViewState = new ViewLEDState(); + break; + default: + currentViewState = new ViewTimeState(ds3231, at24c32); + } + + oldViewState = viewState; + at24c32.write(VIEW_STATE_ADDRESS, uint8_t(viewState)); + + printStatus(); + } +} + +/** + check inputs + */ +void controls() +{ + leftBtn.loop(leftCallback); + decrementBtn.loop(decrementCallback); + enterBtn.loop(enterCallback); + incrementBtn.loop(incrementCallback); + rightBtn.loop(rightCallback); +} + +/** + left callback + */ +void leftCallback() +{ + // delegate to current control state + currentControlState->leftPressed(viewState, controlState); +#ifdef DEBUG + Serial.print(F("< ")); +#endif +} + +/** + decrement callback + */ +void decrementCallback() +{ + // delegate to current control state + currentControlState->decrementPressed(viewState, controlState); +#ifdef DEBUG + Serial.print(F("- ")); +#endif +} + +/** + enter callback + */ +void enterCallback() +{ + // delegate to current control state + currentControlState->enterPressed(viewState, controlState); +#ifdef DEBUG + Serial.print(F("# ")); +#endif +} + +/** + increment callback + */ +void incrementCallback() +{ + // delegate to current control state + currentControlState->incrementPressed(viewState, controlState); +#ifdef DEBUG + Serial.print(F("+ ")); +#endif +} + +/** + right callback + */ +void rightCallback() +{ + // delegate to current control state + currentControlState->rightPressed(viewState, controlState); +#ifdef DEBUG + Serial.print(F("> ")); +#endif +} + +/** + periodic rendering + */ +void renderInterval() +{ + static const unsigned long REFRESH_INTERVAL = 100; + static unsigned long lastRefreshTime = 0; + + if (millis() - lastRefreshTime >= REFRESH_INTERVAL) + { + lastRefreshTime += REFRESH_INTERVAL; + render(); + } +} + +/** + render + */ +void render() +{ + // set default color + uint8_t const color = at24c32.read(COLOR_ADDRESS); + currentViewState->setColor(color); + + // set brightness + uint8_t const brightness = at24c32.read(BRIGHTNESS_ADDRESS); + pixels.setBrightness(brightness); + + // reset matrix (to black) + for (int i = 0; i < MATRIX_SIZE; i++) + { + matrix[i] = 0x00; + } + + // render matrix + currentViewState->render(matrix, controlState); + + // set pixel + for (int i = 0; i < MATRIX_SIZE; i++) + { + uint8_t const r = (matrix[i] >> 5) * 255 / 7; + uint8_t const g = ((matrix[i] >> 2) & 0x07) * 255 / 7; + uint8_t const b = (matrix[i] & 0x03) * 255 / 3; + pixels.setPixelColor(i, pixels.Color(r, g, b)); + } + + pixels.show(); +} + +/** + print current status VIEW STATE \t CONTROL STATE \t FREE RAM + */ +void printStatus() +{ +#ifdef DEBUG + switch (viewState) + { + case ViewStates::TIME: + Serial.print(F("TIME")); + break; + case ViewStates::SECONDS: + Serial.print(F("SECS")); + break; + case ViewStates::TEMPERATURE: + Serial.print(F("TEMP")); + break; + case ViewStates::DATE: + Serial.print(F("DATE")); + break; + case ViewStates::TEXT: + Serial.print(F("TEXT")); + break; + case ViewStates::LED_DEMO: + Serial.print(F("LEDS")); + break; + default: + Serial.print(F("TIME")); + } + + Serial.print(F("\t")); + switch (controlState) + { + case ControlStates::VIEW: + Serial.print(F("VIEW ")); + break; + case ControlStates::TIME_HOURS: + Serial.print(F("HOURS")); + break; + case ControlStates::TIME_MINUTES: + Serial.print(F("MINS ")); + break; + case ControlStates::TIME_MODE: + Serial.print(F("MODE ")); + break; + case ControlStates::TIME_SECONDS: + Serial.print(F("SECS ")); + break; + case ControlStates::DATE_DATE: + Serial.print(F("DATE ")); + break; + case ControlStates::DATE_MONTH: + Serial.print(F("MONTH")); + break; + case ControlStates::DATE_YEAR: + Serial.print(F("YEAR ")); + break; + case ControlStates::COLOR_R: + Serial.print(F("COLOR_R")); + break; + case ControlStates::COLOR_G: + Serial.print(F("COLOR_G")); + break; + case ControlStates::COLOR_B: + Serial.print(F("COLOR_B")); + break; + case ControlStates::TEXT: + Serial.print(F("TEXT ")); + break; + default: + Serial.print(F("VIEW ")); + } + + extern int __heap_start, *__brkval; + int v; + Serial.print(F("\tRAM: ")); + Serial.println((int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval)); +#endif +}