summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/lcd.c')
-rw-r--r--firmware/drivers/lcd.c383
1 files changed, 165 insertions, 218 deletions
diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c
index 252652b29a..0df831e259 100644
--- a/firmware/drivers/lcd.c
+++ b/firmware/drivers/lcd.c
@@ -82,104 +82,50 @@
82 * 82 *
83 */ 83 */
84 84
85void lcd_write(bool command, int byte) __attribute__ ((section (".icode"))); 85void lcd_write_command(int byte) __attribute__ ((section (".icode")));
86void lcd_write(bool command, int byte) 86void lcd_write_command(int byte)
87{ 87{
88 asm("and.b %0, @(r0,gbr)" 88 asm (
89 : 89 "and.b %0, @(r0,gbr)"
90 : /* %0 */ "I"(~(LCD_CS|LCD_DS|LCD_SD|LCD_SC)), 90 : /* outputs */
91 /* %1 */ "z"(LCDR)); 91 : /* inputs */
92 92 /* %0 */ "I"(~(LCD_CS|LCD_DS|LCD_SD|LCD_SC)),
93 if (command) 93 /* %1 = r0 */ "z"(LCDR)
94 asm ("shll8 %0\n" 94 );
95 "0: \n\t" 95
96 "and.b %2,@(r0,gbr)\n\t" 96 asm (
97 "shll %0\n\t" 97 "0: \n"
98 "bf 1f\n\t" 98 "and.b %2,@(r0,gbr) \n"
99 "or.b %3,@(r0,gbr)\n" 99 "shll %0 \n"
100 "1: \n\t" 100 "bf 1f \n"
101 "or.b %4,@(r0,gbr)\n" 101 "or.b %3,@(r0,gbr) \n"
102 "add #-1,%1\n\t" 102 "1: \n"
103 "cmp/pl %1\n\t" 103 "or.b %4,@(r0,gbr) \n"
104 "bt 0b" 104 "add #-1,%1 \n"
105 : 105 "cmp/pl %1 \n"
106 : /* %0 */ "r"(((unsigned)byte)<<16), 106 "bt 0b \n"
107 /* %1 */ "r"(8), 107 : /* outputs */
108 /* %2 */ "I"(~(LCD_SC|LCD_SD|LCD_DS)), 108 : /* inputs */
109 /* %3 */ "I"(LCD_SD), 109 /* %0 */ "r"(((unsigned)byte)<<24),
110 /* %4 */ "I"(LCD_SC), 110 /* %1 */ "r"(8),
111 /* %5 */ "z"(LCDR)); 111 /* %2 */ "I"(~(LCD_SC|LCD_SD|LCD_DS)),
112 else 112 /* %3 */ "I"(LCD_SD),
113 asm ("shll8 %0\n" 113 /* %4 */ "I"(LCD_SC),
114 "0: \n\t" 114 /* %5 = r0 */ "z"(LCDR)
115 "and.b %2, @(r0,gbr)\n\t" 115 );
116 "shll %0\n\t" 116
117 "bf 1f\n\t" 117 asm (
118 "or.b %3, @(r0,gbr)\n" 118 "or.b %0, @(r0,gbr)"
119 "1: \n\t" 119 : /* outputs */
120 "or.b %4, @(r0,gbr)\n" 120 : /* inputs */
121 "and.b %2, @(r0,gbr)\n\t" 121 /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC),
122 "shll %0\n\t" 122 /* %1 = r0 */ "z"(LCDR)
123 "bf 1f\n\t" 123 );
124 "or.b %3, @(r0,gbr)\n"
125 "1: \n\t"
126 "or.b %4, @(r0,gbr)\n"
127 "and.b %2, @(r0,gbr)\n\t"
128 "shll %0\n\t"
129 "bf 1f\n\t"
130 "or.b %3, @(r0,gbr)\n"
131 "1: \n\t"
132 "or.b %4, @(r0,gbr)\n"
133 "and.b %2, @(r0,gbr)\n\t"
134 "shll %0\n\t"
135 "bf 1f\n\t"
136 "or.b %3, @(r0,gbr)\n"
137 "1: \n\t"
138 "or.b %4, @(r0,gbr)\n"
139 "and.b %2, @(r0,gbr)\n\t"
140 "shll %0\n\t"
141 "bf 1f\n\t"
142 "or.b %3, @(r0,gbr)\n"
143 "1: \n\t"
144 "or.b %4, @(r0,gbr)\n"
145 "and.b %2, @(r0,gbr)\n\t"
146 "shll %0\n\t"
147 "bf 1f\n\t"
148 "or.b %3, @(r0,gbr)\n"
149 "1: \n\t"
150 "or.b %4, @(r0,gbr)\n"
151 "and.b %2, @(r0,gbr)\n\t"
152 "shll %0\n\t"
153 "bf 1f\n\t"
154 "or.b %3, @(r0,gbr)\n"
155 "1: \n\t"
156 "or.b %4, @(r0,gbr)\n"
157 "and.b %2, @(r0,gbr)\n\t"
158 "shll %0\n\t"
159 "bf 1f\n\t"
160 "or.b %3, @(r0,gbr)\n"
161 "1: \n\t"
162 "or.b %4, @(r0,gbr)\n"
163 :
164 : /* %0 */ "r"(((unsigned)byte)<<16),
165 /* %1 */ "r"(8),
166 /* %2 */ "I"(~(LCD_SC|LCD_SD)),
167 /* %3 */ "I"(LCD_SD|LCD_DS),
168 /* %4 */ "I"(LCD_SC|LCD_DS),
169 /* %5 */ "z"(LCDR));
170
171 asm("or.b %0, @(r0,gbr)"
172 :
173 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC),
174 /* %1 */ "z"(LCDR));
175} 124}
176 125
177 126
178/* A high performance function to write data to the display, 127/* A high performance function to write data to the display,
179 one or multiple bytes. 128 one or multiple bytes. */
180 Ultimately, all calls to lcd_write(false, xxx) should be substituted by
181 this, it will be most efficient if the LCD buffer is tilted to have the
182 X row as consecutive bytes, so we can write a whole row */
183void lcd_write_data(unsigned char* p_bytes, int count) __attribute__ ((section (".icode"))); 129void lcd_write_data(unsigned char* p_bytes, int count) __attribute__ ((section (".icode")));
184 130
185#ifdef HAVE_LCD_CHARCELLS 131#ifdef HAVE_LCD_CHARCELLS
@@ -199,16 +145,16 @@ void lcd_write_data(unsigned char* p_bytes, int count)
199 145
200 /* precalculate the values for later bit toggling, init data write */ 146 /* precalculate the values for later bit toggling, init data write */
201 asm ( 147 asm (
202 "mov.b @%2,%0\n" /* sda1 = PBDRL */ 148 "mov.b @%2,%0 \n" /* sda1 = PBDRL */
203 "or %4,%0\n" /* sda1 |= LCD_DS | LCD_SD DS and SD high, */ 149 "or %4,%0 \n" /* sda1 |= LCD_DS | LCD_SD DS and SD high, */
204 "and %3,%0\n" /* sda1 &= ~(LCD_CS | LCD_SC) CS and SC low */ 150 "and %3,%0 \n" /* sda1 &= ~(LCD_CS | LCD_SC) CS and SC low */
205 "mov %0,%1\n" /* sda1 -> clk0sda0 */ 151 "mov %0,%1 \n" /* sda1 -> clk0sda0 */
206 "and %5,%1\n" /* clk0sda0 &= ~LCD_SD both low */ 152 "and %5,%1 \n" /* clk0sda0 &= ~LCD_SD both low */
207 "mov.b %1,@%2\n" /* PBDRL = clk0sda0 */ 153 "mov.b %1,@%2 \n" /* PBDRL = clk0sda0 */
208 : // outputs 154 : /* outputs */
209 /* %0 */ "=r"(sda1), 155 /* %0 */ "=r"(sda1),
210 /* %1 */ "=r"(clk0sda0) 156 /* %1 */ "=r"(clk0sda0)
211 : // inputs 157 : /* inputs */
212 /* %2 */ "r"(LCDR), 158 /* %2 */ "r"(LCDR),
213 /* %3 */ "r"(~(LCD_CS | LCD_SC)), 159 /* %3 */ "r"(~(LCD_CS | LCD_SC)),
214 /* %4 */ "r"(LCD_DS | LCD_SD), 160 /* %4 */ "r"(LCD_DS | LCD_SD),
@@ -217,72 +163,71 @@ void lcd_write_data(unsigned char* p_bytes, int count)
217 163
218 /* unrolled loop to serialize the byte */ 164 /* unrolled loop to serialize the byte */
219 asm ( 165 asm (
220 "mov %4,r0\n" /* we need &PBDRL in r0 for "or.b x,@(r0,gbr)" */ 166 "shll %0 \n" /* shift the MSB into carry */
221 167
222 "shll %0\n" /* shift the MSB into carry */ 168 "bf 1f \n"
223 "bf 1f\n" 169 "mov.b %1,@%4 \n" /* if it was a "1": set SD high, SC low still */
224 "mov.b %1,@%4\n" /* if it was a "1": set SD high, SC low still */ 170 "1: \n"
225 "1: \n" 171 "or.b %2,@(r0,gbr) \n" /* rise SC (independent of SD level) */
226 "or.b %2, @(r0,gbr)\n" /* rise SC (independent of SD level) */ 172 "shll %0 \n" /* shift for next round, now for longer hold time */
227 "shll %0\n" /* shift for next round, now for longer hold time */ 173 "mov.b %3,@%4 \n" /* SC and SD low again */
228 "mov.b %3,@%4\n" /* SC and SD low again */ 174
229 175 "bf 1f \n"
230 "bf 1f\n" 176 "mov.b %1,@%4 \n"
231 "mov.b %1,@%4\n" 177 "1: \n"
232 "1: \n" 178 "or.b %2,@(r0,gbr) \n"
233 "or.b %2, @(r0,gbr)\n" 179 "shll %0 \n"
234 "shll %0\n" 180 "mov.b %3,@%4 \n"
235 "mov.b %3,@%4\n" 181
236 182 "bf 1f \n"
237 "bf 1f\n" 183 "mov.b %1,@%4 \n"
238 "mov.b %1,@%4\n" 184 "1: \n"
239 "1: \n" 185 "or.b %2,@(r0,gbr) \n"
240 "or.b %2, @(r0,gbr)\n" 186 "shll %0 \n"
241 "shll %0\n" 187 "mov.b %3,@%4 \n"
242 "mov.b %3,@%4\n" 188
243 189 "bf 1f \n"
244 "bf 1f\n" 190 "mov.b %1,@%4 \n"
245 "mov.b %1,@%4\n" 191 "1: \n"
246 "1: \n" 192 "or.b %2,@(r0,gbr) \n"
247 "or.b %2, @(r0,gbr)\n" 193 "shll %0 \n"
248 "shll %0\n" 194 "mov.b %3,@%4 \n"
249 "mov.b %3,@%4\n" 195
250 196 "bf 1f \n"
251 "bf 1f\n" 197 "mov.b %1,@%4 \n"
252 "mov.b %1,@%4\n" 198 "1: \n"
253 "1: \n" 199 "or.b %2,@(r0,gbr) \n"
254 "or.b %2, @(r0,gbr)\n" 200 "shll %0 \n"
255 "shll %0\n" 201 "mov.b %3,@%4 \n"
256 "mov.b %3,@%4\n" 202
257 203 "bf 1f \n"
258 "bf 1f\n" 204 "mov.b %1,@%4 \n"
259 "mov.b %1,@%4\n" 205 "1: \n"
260 "1: \n" 206 "or.b %2,@(r0,gbr) \n"
261 "or.b %2, @(r0,gbr)\n" 207 "shll %0 \n"
262 "shll %0\n" 208 "mov.b %3,@%4 \n"
263 "mov.b %3,@%4\n" 209
264 210 "bf 1f \n"
265 "bf 1f\n" 211 "mov.b %1,@%4 \n"
266 "mov.b %1,@%4\n" 212 "1: \n"
267 "1: \n" 213 "or.b %2,@(r0,gbr) \n"
268 "or.b %2, @(r0,gbr)\n" 214 "shll %0 \n"
269 "shll %0\n" 215 "mov.b %3,@%4 \n"
270 "mov.b %3,@%4\n" 216
271 217 "bf 1f \n"
272 "bf 1f\n" 218 "mov.b %1,@%4 \n" /* set SD high, SC low still */
273 "mov.b %1,@%4\n" /* set SD high, SC low still */ 219 "1: \n"
274 "1: \n" 220 "or.b %2,@(r0,gbr) \n" /* rise SC (independent of SD level) */
275 "or.b %2, @(r0,gbr)\n" /* rise SC (independent of SD level) */ 221
276 222 "or.b %5,@(r0,gbr) \n" /* restore port */
277 "or.b %5, @(r0,gbr)\n" /* restore port */ 223 : /* outputs */
278 : 224 : /* inputs */
279 : /* %0 */ "r"(byte), 225 /* %0 */ "r"(byte),
280 /* %1 */ "r"(sda1), 226 /* %1 */ "r"(sda1),
281 /* %2 */ "I"(LCD_SC), 227 /* %2 */ "I"(LCD_SC),
282 /* %3 */ "r"(clk0sda0), 228 /* %3 */ "r"(clk0sda0),
283 /* %4 */ "r"(LCDR), 229 /* %4 = r0 */ "z"(LCDR),
284 /* %5 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC) 230 /* %5 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC)
285 : "r0"
286 ); 231 );
287 232
288 /* This is the place to reenable the interrupts, if we have disabled 233 /* This is the place to reenable the interrupts, if we have disabled
@@ -309,11 +254,11 @@ void lcd_write_data(unsigned char* p_bytes, int count)
309 254
310 /* precalculate the values for later bit toggling, init data write */ 255 /* precalculate the values for later bit toggling, init data write */
311 asm ( 256 asm (
312 "mov.b @%1,r0\n" /* r0 = PBDRL */ 257 "mov.b @%1,r0 \n" /* r0 = PBDRL */
313 "or %3,r0\n" /* r0 |= LCD_DS | LCD_SD DS and SD high, */ 258 "or %3,r0 \n" /* r0 |= LCD_DS | LCD_SD DS and SD high, */
314 "and %2,r0\n" /* r0 &= ~(LCD_CS | LCD_SC) CS and SC low */ 259 "and %2,r0 \n" /* r0 &= ~(LCD_CS | LCD_SC) CS and SC low */
315 "mov.b r0,@%1\n" /* PBDRL = r0 */ 260 "mov.b r0,@%1 \n" /* PBDRL = r0 */
316 "neg r0,%0\n" /* sda1 = 0-r0 */ 261 "neg r0,%0 \n" /* sda1 = 0-r0 */
317 : /* outputs: */ 262 : /* outputs: */
318 /* %0 */ "=r"(sda1) 263 /* %0 */ "=r"(sda1)
319 : /* inputs: */ 264 : /* inputs: */
@@ -326,56 +271,56 @@ void lcd_write_data(unsigned char* p_bytes, int count)
326 271
327 /* unrolled loop to serialize the byte */ 272 /* unrolled loop to serialize the byte */
328 asm ( 273 asm (
329 "shll %0 \n" /* shift the MSB into carry */ 274 "shll %0 \n" /* shift the MSB into carry */
330 "negc %1, r0\n" /* carry to SD, SC low */ 275 "negc %1, r0 \n" /* carry to SD, SC low */
331 "mov.b r0,@%3\n" /* set data to port */ 276 "mov.b r0,@%3 \n" /* set data to port */
332 "or %2, r0\n" /* rise SC (independent of SD level) */ 277 "or %2, r0 \n" /* rise SC (independent of SD level) */
333 "mov.b r0,@%3\n" /* set to port */ 278 "mov.b r0,@%3 \n" /* set to port */
334 279
335 "shll %0 \n" 280 "shll %0 \n"
336 "negc %1, r0\n" 281 "negc %1, r0 \n"
337 "mov.b r0,@%3\n" 282 "mov.b r0,@%3 \n"
338 "or %2, r0\n" 283 "or %2, r0 \n"
339 "mov.b r0,@%3\n" 284 "mov.b r0,@%3 \n"
340 285
341 "shll %0 \n" 286 "shll %0 \n"
342 "negc %1, r0\n" 287 "negc %1, r0 \n"
343 "mov.b r0,@%3\n" 288 "mov.b r0,@%3 \n"
344 "or %2, r0\n" 289 "or %2, r0 \n"
345 "mov.b r0,@%3\n" 290 "mov.b r0,@%3 \n"
346 291
347 "shll %0 \n" 292 "shll %0 \n"
348 "negc %1, r0\n" 293 "negc %1, r0 \n"
349 "mov.b r0,@%3\n" 294 "mov.b r0,@%3 \n"
350 "or %2, r0\n" 295 "or %2, r0 \n"
351 "mov.b r0,@%3\n" 296 "mov.b r0,@%3 \n"
352 297
353 "shll %0 \n" 298 "shll %0 \n"
354 "negc %1, r0\n" 299 "negc %1, r0 \n"
355 "mov.b r0,@%3\n" 300 "mov.b r0,@%3 \n"
356 "or %2, r0\n" 301 "or %2, r0 \n"
357 "mov.b r0,@%3\n" 302 "mov.b r0,@%3 \n"
358 303
359 "shll %0 \n" 304 "shll %0 \n"
360 "negc %1, r0\n" 305 "negc %1, r0 \n"
361 "mov.b r0,@%3\n" 306 "mov.b r0,@%3 \n"
362 "or %2, r0\n" 307 "or %2, r0 \n"
363 "mov.b r0,@%3\n" 308 "mov.b r0,@%3 \n"
364 309
365 "shll %0 \n" 310 "shll %0 \n"
366 "negc %1, r0\n" 311 "negc %1, r0 \n"
367 "mov.b r0,@%3\n" 312 "mov.b r0,@%3 \n"
368 "or %2, r0\n" 313 "or %2, r0 \n"
369 "mov.b r0,@%3\n" 314 "mov.b r0,@%3 \n"
370 315
371 "shll %0 \n" 316 "shll %0 \n"
372 "negc %1, r0\n" 317 "negc %1, r0 \n"
373 "mov.b r0,@%3\n" 318 "mov.b r0,@%3 \n"
374 "or %2, r0\n" 319 "or %2, r0 \n"
375 "mov.b r0,@%3\n" 320 "mov.b r0,@%3 \n"
376 321
377 "or %4, r0\n" /* restore port */ 322 "or %4, r0 \n" /* restore port */
378 "mov.b r0,@%3\n" 323 "mov.b r0,@%3 \n"
379 : /* outputs: */ 324 : /* outputs: */
380 : /* inputs: */ 325 : /* inputs: */
381 /* %0 */ "r"(byte), 326 /* %0 */ "r"(byte),
@@ -393,3 +338,5 @@ void lcd_write_data(unsigned char* p_bytes, int count)
393 } while (--count); /* tail loop is faster */ 338 } while (--count); /* tail loop is faster */
394} 339}
395#endif /* #ifdef HAVE_LCD_CHARCELLS */ 340#endif /* #ifdef HAVE_LCD_CHARCELLS */
341
342