summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/neo/keyboard.c4
-rw-r--r--firmware/drivers/lcd-player.c36
-rw-r--r--firmware/drivers/lcd-recorder.c60
-rw-r--r--firmware/drivers/lcd.c383
-rw-r--r--firmware/export/lcd.h2
5 files changed, 217 insertions, 268 deletions
diff --git a/apps/neo/keyboard.c b/apps/neo/keyboard.c
index 7433b4b6c7..d81d7629b3 100644
--- a/apps/neo/keyboard.c
+++ b/apps/neo/keyboard.c
@@ -94,7 +94,7 @@ int kbd_input(char* text, int buflen)
94 lcd_puts(0, 0, kbdbuffer); 94 lcd_puts(0, 0, kbdbuffer);
95 kbd_show_legend(screen); 95 kbd_show_legend(screen);
96 lcd_cursor(cursorpos, 0); 96 lcd_cursor(cursorpos, 0);
97 lcd_write(true, LCD_BLINKCUR); 97 lcd_write_command(LCD_BLINKCUR);
98 98
99 pstart = pcursor = kbdbuffer; 99 pstart = pcursor = kbdbuffer;
100 100
@@ -140,7 +140,7 @@ int kbd_input(char* text, int buflen)
140 case BUTTON_IR|NEO_IR_BUTTON_STOP: 140 case BUTTON_IR|NEO_IR_BUTTON_STOP:
141 141
142 /* Remove blinking cursor */ 142 /* Remove blinking cursor */
143 lcd_write(true,LCD_OFFCUR); 143 lcd_write_command(LCD_OFFCUR);
144 done = true; 144 done = true;
145 } 145 }
146 } 146 }
diff --git a/firmware/drivers/lcd-player.c b/firmware/drivers/lcd-player.c
index 90e1d48e00..d040342862 100644
--- a/firmware/drivers/lcd-player.c
+++ b/firmware/drivers/lcd-player.c
@@ -111,6 +111,8 @@ static char lcd_cram;
111static char lcd_pram; 111static char lcd_pram;
112static char lcd_iram; 112static char lcd_iram;
113 113
114static unsigned char lcd_data_byte; /* global write buffer */
115
114unsigned short buffer_xlcd[11][2]; 116unsigned short buffer_xlcd[11][2];
115unsigned short buffer_lcd_mirror[11][2]; 117unsigned short buffer_lcd_mirror[11][2];
116 118
@@ -122,7 +124,7 @@ unsigned char hardware_buffer_lcd[11][2];
122static void lcd_free_pat(int map_ch) 124static void lcd_free_pat(int map_ch)
123{ 125{
124 int x, y; 126 int x, y;
125 unsigned short substitute_char; 127 unsigned char substitute_char;
126 128
127 int pat; 129 int pat;
128 pat=extended_chars_mapped[map_ch]; 130 pat=extended_chars_mapped[map_ch];
@@ -140,8 +142,8 @@ static void lcd_free_pat(int map_ch)
140#ifdef SIMULATOR 142#ifdef SIMULATOR
141 hardware_buffer_lcd[x][y]=substitute_char; 143 hardware_buffer_lcd[x][y]=substitute_char;
142#else 144#else
143 lcd_write(true, LCD_CURSOR(x, y)); 145 lcd_write_command(LCD_CURSOR(x, y));
144 lcd_write(false, substitute_char); 146 lcd_write_data(&substitute_char, 1);
145#endif 147#endif
146 } 148 }
147 } 149 }
@@ -240,8 +242,8 @@ void xlcd_update(void)
240#ifdef SIMULATOR 242#ifdef SIMULATOR
241 hardware_buffer_lcd[x][y]=hw_ch; 243 hardware_buffer_lcd[x][y]=hw_ch;
242#else 244#else
243 lcd_write(true,LCD_CURSOR(x,y)); 245 lcd_write_command(LCD_CURSOR(x,y));
244 lcd_write(false, hw_ch); 246 lcd_write_data(&hw_ch, 1);
245#endif 247#endif
246 } 248 }
247 } 249 }
@@ -274,8 +276,9 @@ bool lcdx_putc(int x, int y, unsigned short ch)
274#ifdef SIMULATOR 276#ifdef SIMULATOR
275 hardware_buffer_lcd[x][y]=lcd_char; 277 hardware_buffer_lcd[x][y]=lcd_char;
276#else 278#else
277 lcd_write(true, LCD_CURSOR(x, y)); 279 lcd_data_byte = (unsigned char) lcd_char;
278 lcd_write(false, lcd_char); 280 lcd_write_command(LCD_CURSOR(x, y));
281 lcd_write_data(&lcd_data_byte, 1);
279#endif 282#endif
280 return false; 283 return false;
281} 284}
@@ -405,16 +408,14 @@ void lcd_define_pattern(int pat, char *pattern)
405#ifndef SIMULATOR 408#ifndef SIMULATOR
406void lcd_define_hw_pattern (int which,char *pattern,int length) 409void lcd_define_hw_pattern (int which,char *pattern,int length)
407{ 410{
408 int i; 411 lcd_write_command(lcd_pram | which);
409 lcd_write(true,lcd_pram | which); 412 lcd_write_data(pattern, length);
410 for (i=0;i<length;i++)
411 lcd_write(false,pattern[i]);
412} 413}
413 414
414void lcd_double_height(bool on) 415void lcd_double_height(bool on)
415{ 416{
416 if(new_lcd) 417 if(new_lcd)
417 lcd_write(true,on?9:8); 418 lcd_write_command(on?9:8);
418} 419}
419 420
420static char icon_pos[] = 421static char icon_pos[] =
@@ -463,20 +464,21 @@ void lcd_icon(int icon, bool enable)
463 pos = icon_pos[icon]; 464 pos = icon_pos[icon];
464 mask = icon_mask[icon]; 465 mask = icon_mask[icon];
465 466
466 lcd_write(true, LCD_ICON(pos)); 467 lcd_write_command(LCD_ICON(pos));
467 468
468 if(enable) 469 if(enable)
469 icon_mirror[pos] |= mask; 470 icon_mirror[pos] |= mask;
470 else 471 else
471 icon_mirror[pos] &= ~mask; 472 icon_mirror[pos] &= ~mask;
472 473
473 lcd_write(false, icon_mirror[pos]); 474 lcd_write_data(&icon_mirror[pos], 1);
474} 475}
475 476
476void lcd_set_contrast(int val) 477void lcd_set_contrast(int val)
477{ 478{
478 lcd_write(true, lcd_contrast_set); 479 lcd_data_byte = (unsigned char) (31 - val);
479 lcd_write(false, 31-val); 480 lcd_write_command(lcd_contrast_set);
481 lcd_write_data(&lcd_data_byte, 1);
480} 482}
481#endif /* SIMULATOR */ 483#endif /* SIMULATOR */
482 484
@@ -763,7 +765,7 @@ void lcd_cursor(int x, int y)
763 value=0x80|(x+0x54); 765 value=0x80|(x+0x54);
764 break; 766 break;
765 } 767 }
766 lcd_write(true,value); 768 lcd_write_command(value);
767} 769}
768#endif 770#endif
769 771
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c
index f7eb529fea..8cf5f12b8b 100644
--- a/firmware/drivers/lcd-recorder.c
+++ b/firmware/drivers/lcd-recorder.c
@@ -143,19 +143,19 @@ void lcd_init (void)
143 PBIOR |= 0x000f; /* IOR = 1 */ 143 PBIOR |= 0x000f; /* IOR = 1 */
144 144
145 /* inits like the original firmware */ 145 /* inits like the original firmware */
146 lcd_write(true, LCD_SOFTWARE_RESET); 146 lcd_write_command(LCD_SOFTWARE_RESET);
147 lcd_write(true, LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO + 4); 147 lcd_write_command(LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO + 4);
148 lcd_write(true, LCD_SET_1OVER4_BIAS_RATIO + 0); /* force 1/4 bias: 0 */ 148 lcd_write_command(LCD_SET_1OVER4_BIAS_RATIO + 0); /* force 1/4 bias: 0 */
149 lcd_write(true, LCD_SET_POWER_CONTROL_REGISTER + 7); /* power control register: op-amp=1, regulator=1, booster=1 */ 149 lcd_write_command(LCD_SET_POWER_CONTROL_REGISTER + 7); /* power control register: op-amp=1, regulator=1, booster=1 */
150 lcd_write(true, LCD_SET_DISPLAY_ON); 150 lcd_write_command(LCD_SET_DISPLAY_ON);
151 lcd_write(true, LCD_SET_NORMAL_DISPLAY); 151 lcd_write_command(LCD_SET_NORMAL_DISPLAY);
152 lcd_write(true, LCD_SET_SEGMENT_REMAP + 1); /* mirror horizontal: 1 */ 152 lcd_write_command(LCD_SET_SEGMENT_REMAP + 1); /* mirror horizontal: 1 */
153 lcd_write(true, LCD_SET_COM_OUTPUT_SCAN_DIRECTION + 8); /* mirror vertical: 1 */ 153 lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION + 8); /* mirror vertical: 1 */
154 lcd_write(true, LCD_SET_DISPLAY_START_LINE + 0); 154 lcd_write_command(LCD_SET_DISPLAY_START_LINE + 0);
155 lcd_set_contrast(lcd_default_contrast()); 155 lcd_set_contrast(lcd_default_contrast());
156 lcd_write(true, LCD_SET_PAGE_ADDRESS); 156 lcd_write_command(LCD_SET_PAGE_ADDRESS);
157 lcd_write(true, LCD_SET_LOWER_COLUMN_ADDRESS + 0); 157 lcd_write_command(LCD_SET_LOWER_COLUMN_ADDRESS + 0);
158 lcd_write(true, LCD_SET_HIGHER_COLUMN_ADDRESS + 0); 158 lcd_write_command(LCD_SET_HIGHER_COLUMN_ADDRESS + 0);
159 159
160 lcd_clear_display(); 160 lcd_clear_display();
161 lcd_update(); 161 lcd_update();
@@ -171,9 +171,9 @@ void lcd_blit (unsigned char* p_data, int x, int y, int width, int height, int s
171 /* Copy display bitmap to hardware */ 171 /* Copy display bitmap to hardware */
172 while (height--) 172 while (height--)
173 { 173 {
174 lcd_write (true, LCD_CNTL_PAGE | (y++ & 0xf)); 174 lcd_write_command (LCD_CNTL_PAGE | (y++ & 0xf));
175 lcd_write (true, LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf)); 175 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
176 lcd_write (true, LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf)); 176 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
177 177
178 lcd_write_data(p_data, width); 178 lcd_write_data(p_data, width);
179 p_data += stride; 179 p_data += stride;
@@ -193,9 +193,9 @@ void lcd_update (void)
193 /* Copy display bitmap to hardware */ 193 /* Copy display bitmap to hardware */
194 for (y = 0; y < LCD_HEIGHT/8; y++) 194 for (y = 0; y < LCD_HEIGHT/8; y++)
195 { 195 {
196 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf)); 196 lcd_write_command (LCD_CNTL_PAGE | (y & 0xf));
197 lcd_write (true, LCD_CNTL_HIGHCOL | ((xoffset>>4) & 0xf)); 197 lcd_write_command (LCD_CNTL_HIGHCOL | ((xoffset>>4) & 0xf));
198 lcd_write (true, LCD_CNTL_LOWCOL | (xoffset & 0xf)); 198 lcd_write_command (LCD_CNTL_LOWCOL | (xoffset & 0xf));
199 199
200 lcd_write_data (lcd_framebuffer[y], LCD_WIDTH); 200 lcd_write_data (lcd_framebuffer[y], LCD_WIDTH);
201 } 201 }
@@ -224,9 +224,9 @@ void lcd_update_rect (int x_start, int y,
224 /* Copy specified rectange bitmap to hardware */ 224 /* Copy specified rectange bitmap to hardware */
225 for (; y <= ymax; y++) 225 for (; y <= ymax; y++)
226 { 226 {
227 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf)); 227 lcd_write_command (LCD_CNTL_PAGE | (y & 0xf));
228 lcd_write (true, LCD_CNTL_HIGHCOL | (((x_start+xoffset)>>4) & 0xf)); 228 lcd_write_command (LCD_CNTL_HIGHCOL | (((x_start+xoffset)>>4) & 0xf));
229 lcd_write (true, LCD_CNTL_LOWCOL | ((x_start+xoffset) & 0xf)); 229 lcd_write_command (LCD_CNTL_LOWCOL | ((x_start+xoffset) & 0xf));
230 230
231 lcd_write_data (&lcd_framebuffer[y][x_start], width); 231 lcd_write_data (&lcd_framebuffer[y][x_start], width);
232 } 232 }
@@ -234,16 +234,16 @@ void lcd_update_rect (int x_start, int y,
234 234
235void lcd_set_contrast(int val) 235void lcd_set_contrast(int val)
236{ 236{
237 lcd_write(true, LCD_CNTL_CONTRAST); 237 lcd_write_command(LCD_CNTL_CONTRAST);
238 lcd_write(true, val); 238 lcd_write_command(val);
239} 239}
240 240
241void lcd_set_invert_display(bool yesno) 241void lcd_set_invert_display(bool yesno)
242{ 242{
243 if (yesno) 243 if (yesno)
244 lcd_write(true, LCD_SET_REVERSE_DISPLAY); 244 lcd_write_command(LCD_SET_REVERSE_DISPLAY);
245 else 245 else
246 lcd_write(true, LCD_SET_NORMAL_DISPLAY); 246 lcd_write_command(LCD_SET_NORMAL_DISPLAY);
247} 247}
248 248
249/* turn the display upside down (call lcd_update() afterwards) */ 249/* turn the display upside down (call lcd_update() afterwards) */
@@ -251,14 +251,14 @@ void lcd_set_flip(bool yesno)
251{ 251{
252 if (yesno) 252 if (yesno)
253 { 253 {
254 lcd_write(true, LCD_SET_SEGMENT_REMAP); 254 lcd_write_command(LCD_SET_SEGMENT_REMAP);
255 lcd_write(true, LCD_SET_COM_OUTPUT_SCAN_DIRECTION); 255 lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION);
256 xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 112 we have */ 256 xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 112 we have */
257 } 257 }
258 else 258 else
259 { 259 {
260 lcd_write(true, LCD_SET_SEGMENT_REMAP | 0x01); 260 lcd_write_command(LCD_SET_SEGMENT_REMAP | 0x01);
261 lcd_write(true, LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); 261 lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08);
262 xoffset = 0; 262 xoffset = 0;
263 } 263 }
264} 264}
@@ -274,7 +274,7 @@ void lcd_set_flip(bool yesno)
274 */ 274 */
275void lcd_roll(int lines) 275void lcd_roll(int lines)
276{ 276{
277 lcd_write(true, LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1))); 277 lcd_write_command(LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1)));
278} 278}
279 279
280#endif /* SIMULATOR */ 280#endif /* SIMULATOR */
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
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 733efdded3..20023bf1c6 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -43,7 +43,7 @@ extern void lcd_stop_scroll(void);
43extern void lcd_scroll_speed( int speed ); 43extern void lcd_scroll_speed( int speed );
44extern void lcd_scroll_delay( int ms ); 44extern void lcd_scroll_delay( int ms );
45extern void lcd_set_contrast(int val); 45extern void lcd_set_contrast(int val);
46extern void lcd_write( bool command, int byte ); 46extern void lcd_write_command( int byte );
47extern void lcd_write_data( unsigned char* p_bytes, int count ); 47extern void lcd_write_data( unsigned char* p_bytes, int count );
48extern int lcd_default_contrast(void); 48extern int lcd_default_contrast(void);
49 49