lcd.cpp (4582B)
1 #include "lcd.h" 2 #include "hidModule.h" 3 4 #include <util/delay.h> 5 #include "font.h" 6 7 /* 8 A0~ chip select 9 A1 Backlight 10 A2~ Reset 11 A3~ Write 12 A4~ Command 13 A5~ Read 14 A6~ Vsync 15 A7~ Hsync 16 17 C[0-7] DATA BUS 18 */ 19 namespace lcd { 20 21 void send(const uint8_t d) 22 { 23 control() = defaultControl & n_write; 24 data() = d; 25 control() = defaultControl; 26 } 27 28 void send(const uint16_t d) 29 { 30 send(uint8_t(d >> 8)); 31 send(uint8_t(d)); 32 } 33 34 template <typename...Ts> 35 void cmd(const uint8_t c, Ts... params) 36 { 37 control() = defaultControl & n_command & n_write; 38 data() = c; 39 control() = defaultControl; 40 41 // https://stackoverflow.com/questions/25680461/variadic-template-pack-expansion#25683817 42 // TODO:(C++17) (send(params), ...); 43 char dummy[] __attribute__((unused)) {0, (send(uint8_t(params)), '\0')...}; 44 } 45 46 void fillScreen(uint16_t colour) 47 { 48 cmd(0x2C); 49 uint8_t j = (320ul * 240) / (256 * 2); 50 uint8_t i = 0; // uses wraparound 51 do 52 { 53 do { 54 lcd::send(colour); 55 lcd::send(colour); 56 } while (--i); 57 } while (--j); 58 } 59 60 void init() 61 { 62 controlDir() = 0xFF; 63 dataDir() = 0xFF; 64 65 control() = defaultControl & n_reset; 66 _delay_us(16); 67 control() = defaultControl; 68 _delay_ms(128); 69 70 71 cmd(0x11); // awake 72 _delay_ms(6); 73 74 cmd(0x3A, 0x55); // 16 bits per pixel 75 76 fillScreen(0); 77 78 cmd(0x36, 0x20); // x/y -> y/x 79 80 cmd(0x29); // display ON 81 } 82 83 union colour 84 { 85 struct __attribute__((packed)) { 86 uint8_t r:5; 87 uint8_t g:6; 88 uint8_t b:5; 89 }; 90 uint16_t word; 91 92 constexpr colour(uint16_t const val = 0) 93 : word(val) 94 {} 95 96 constexpr colour(uint8_t const red, uint8_t const green, uint8_t const blue) 97 : r(red) 98 , g(green) 99 , b(blue) 100 {} 101 constexpr operator uint16_t() const 102 { 103 return word; 104 } 105 static constexpr auto grey(uint8_t val) 106 { 107 return colour(val >> 1, val, val >> 1); 108 } 109 } p; 110 111 static_assert(sizeof(colour) == sizeof(uint16_t), "not correct size"); 112 113 [[noreturn]] 114 void test() 115 { 116 117 118 init(); 119 120 cmd(0x2C); 121 122 for (;;) 123 { 124 //if (0 == ++p.r) if (0 == ++p.b) --p.g; 125 126 //send(p.word); 127 //send(uint16_t(0xF800)); 128 auto x = hid::sampleInput(); 129 send(x); 130 send(x); 131 } 132 } 133 134 void setColumns(const uint16_t start, const uint16_t end) 135 { 136 cmd(0x2A); 137 send(start); 138 send(end); 139 } 140 141 void setRows(const uint16_t start, const uint16_t end) 142 { 143 cmd(0x2B); 144 send(start); 145 send(end); 146 } 147 148 struct drawSequence 149 { 150 drawSequence() 151 { 152 cmd(0x2C); 153 } 154 ~drawSequence() 155 { 156 cmd(0); 157 } 158 }; 159 160 struct 161 { 162 void putc(const char c) 163 { 164 switch (c) 165 { 166 case '\n': 167 newline(); 168 return; 169 case '\f': 170 y = 0; 171 // fallthrough 172 case '\r': 173 cr(); 174 return; 175 case 0x7F: 176 x -= 8; 177 putc(' '); 178 x -= 8; 179 return; 180 } 181 182 setColumns(x, x + 7); 183 setRows(y, y + 7); 184 advance(); 185 186 auto g = drawSequence(); 187 188 auto bytePtr = flashPtr<uint8_t>(fonts::mash[c - ' ']); 189 190 uint8_t x = 8; 191 do 192 { 193 auto byte = bytePtr.load_post_inc(); 194 send(byte & bit(7) ? foreground : background); 195 send(byte & bit(6) ? foreground : background); 196 send(byte & bit(5) ? foreground : background); 197 send(byte & bit(4) ? foreground : background); 198 send(byte & bit(3) ? foreground : background); 199 send(byte & bit(2) ? foreground : background); 200 send(byte & bit(1) ? foreground : background); 201 send(byte & bit(0) ? foreground : background); 202 } 203 while (--x); 204 } 205 void newline() 206 { 207 y += 8; 208 cr(); 209 } 210 void cr() 211 { 212 x = 0; 213 } 214 void advance(uint8_t count = 1) 215 { 216 if (x >= 320 - 8) newline(); 217 else x += count * 8; 218 } 219 void puts_ram(char const* str) 220 { 221 while (auto c = *str++) putc(c); 222 } 223 void puts(flashPtr<char> str) 224 { 225 while (auto c = str.load_post_inc()) putc(c); 226 } 227 void putu(uint16_t val) 228 { 229 if (val >= 10) 230 { 231 putu(val / 10); 232 putc(val % 10 + '0'); 233 } 234 else 235 { 236 putc(val + '0'); 237 } 238 } 239 void puti(int16_t val) 240 { 241 if (val < 0) 242 { 243 putc('-'); 244 putu(-val); // does not handle min(int16_t) 245 return; 246 } 247 putu(val); 248 } 249 250 uint16_t x = 0, y = 0; 251 uint16_t foreground = white; 252 uint16_t background = dgrey; 253 fonts::glyph const* glyphs = fonts::mash; 254 } lout; 255 256 char const testStr[] [[gnu::__progmem__]] = "\n\nHello, World!\nIt is a very nice day today, what are you up to this afternoon?\n"; 257 258 char const clearNum[] [[gnu::__progmem__]] = "\r \r"; 259 260 void testFont() 261 { 262 lout.foreground = green; 263 for (char c = ' '; c < 0x7F;) 264 { 265 lout.putc(c); 266 if (not (++c % 0x10)) lout.newline(); 267 } 268 lout.background = black; 269 lout.foreground = colour(0xF,0x0,0xF); 270 271 lout.puts(testStr); 272 lout.putu(5); 273 lout.newline(); 274 lout.newline(); 275 return; 276 lout.foreground = white; 277 int16_t x = -32000; 278 for (;;) 279 { 280 lout.puti(x); 281 x += 10; 282 _delay_ms(50); 283 lout.puts(clearNum); 284 } 285 } 286 287 }