summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2003-12-12 22:11:08 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2003-12-12 22:11:08 +0000
commit56271b571abdff74672d174345ae3197e170953c (patch)
tree1511da159203b4992de0bbec842def93b3a8284d /firmware/drivers
parente3be10107d74b3124ad4ff365f9894c09a316297 (diff)
downloadrockbox-56271b571abdff74672d174345ae3197e170953c.tar.gz
rockbox-56271b571abdff74672d174345ae3197e170953c.zip
LCD flip (upside down) and a high-performance blit function
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4143 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/lcd-recorder.c48
-rw-r--r--firmware/drivers/lcd.c113
2 files changed, 154 insertions, 7 deletions
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c
index a409c9fc63..0a95e82c3d 100644
--- a/firmware/drivers/lcd-recorder.c
+++ b/firmware/drivers/lcd-recorder.c
@@ -103,10 +103,8 @@ static struct scrollinfo scroll[SCROLLABLE_LINES];
103static int xmargin = 0; 103static int xmargin = 0;
104static int ymargin = 0; 104static int ymargin = 0;
105static int curfont = FONT_SYSFIXED; 105static int curfont = FONT_SYSFIXED;
106static int xoffset = 0; /* needed for flip */
106 107
107#ifndef SIMULATOR
108static
109#endif
110unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; 108unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
111 109
112/* All zeros and ones bitmaps for area filling */ 110/* All zeros and ones bitmaps for area filling */
@@ -163,6 +161,25 @@ void lcd_init (void)
163 sizeof(scroll_stack), scroll_name); 161 sizeof(scroll_stack), scroll_name);
164} 162}
165 163
164
165/* Performance function that works with an external buffer
166 note that y and height are in 8-pixel units! */
167void lcd_blit (unsigned char* p_data, int x, int y, int width, int height, int stride) __attribute__ ((section (".icode")));
168void lcd_blit (unsigned char* p_data, int x, int y, int width, int height, int stride)
169{
170 /* Copy display bitmap to hardware */
171 while (height--)
172 {
173 lcd_write (true, LCD_CNTL_PAGE | (y++ & 0xf));
174 lcd_write (true, LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
175 lcd_write (true, LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
176
177 lcd_write_data(p_data, width);
178 p_data += stride;
179 }
180}
181
182
166/* 183/*
167 * Update the display. 184 * Update the display.
168 * This must be called after all other LCD functions that change the display. 185 * This must be called after all other LCD functions that change the display.
@@ -176,8 +193,8 @@ void lcd_update (void)
176 for (y = 0; y < LCD_HEIGHT/8; y++) 193 for (y = 0; y < LCD_HEIGHT/8; y++)
177 { 194 {
178 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf)); 195 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf));
179 lcd_write (true, LCD_CNTL_HIGHCOL); 196 lcd_write (true, LCD_CNTL_HIGHCOL | ((xoffset>>4) & 0xf));
180 lcd_write (true, LCD_CNTL_LOWCOL); 197 lcd_write (true, LCD_CNTL_LOWCOL | (xoffset & 0xf));
181 198
182 for (x = 0; x < LCD_WIDTH; x++) 199 for (x = 0; x < LCD_WIDTH; x++)
183 lcd_write (false, lcd_framebuffer[x][y]); 200 lcd_write (false, lcd_framebuffer[x][y]);
@@ -210,8 +227,8 @@ void lcd_update_rect (int x_start, int y,
210 for (; y <= ymax; y++) 227 for (; y <= ymax; y++)
211 { 228 {
212 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf)); 229 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf));
213 lcd_write (true, LCD_CNTL_HIGHCOL | ((x_start>>4) & 0xf)); 230 lcd_write (true, LCD_CNTL_HIGHCOL | (((x_start+xoffset)>>4) & 0xf));
214 lcd_write (true, LCD_CNTL_LOWCOL | (x_start & 0xf)); 231 lcd_write (true, LCD_CNTL_LOWCOL | ((x_start+xoffset) & 0xf));
215 232
216 for (x = x_start; x < xmax; x++) 233 for (x = x_start; x < xmax; x++)
217 lcd_write (false, lcd_framebuffer[x][y]); 234 lcd_write (false, lcd_framebuffer[x][y]);
@@ -232,6 +249,23 @@ void lcd_set_invert_display(bool yesno)
232 lcd_write(true, LCD_SET_NORMAL_DISPLAY); 249 lcd_write(true, LCD_SET_NORMAL_DISPLAY);
233} 250}
234 251
252/* turn the display upside down (call lcd_update() afterwards) */
253void lcd_set_flip(bool yesno)
254{
255 if (yesno)
256 {
257 lcd_write(true, LCD_SET_SEGMENT_REMAP);
258 lcd_write(true, LCD_SET_COM_OUTPUT_SCAN_DIRECTION);
259 xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 112 we have */
260 }
261 else
262 {
263 lcd_write(true, LCD_SET_SEGMENT_REMAP | 0x01);
264 lcd_write(true, LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08);
265 xoffset = 0;
266 }
267}
268
235/** 269/**
236 * Rolls up the lcd display by the specified amount of lines. 270 * Rolls up the lcd display by the specified amount of lines.
237 * Lines that are rolled out over the top of the screen are 271 * Lines that are rolled out over the top of the screen are
diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c
index 3f6acee301..aaa93b3385 100644
--- a/firmware/drivers/lcd.c
+++ b/firmware/drivers/lcd.c
@@ -173,3 +173,116 @@ void lcd_write(bool command, int byte)
173 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC), 173 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC),
174 /* %1 */ "z"(LCDR)); 174 /* %1 */ "z"(LCDR));
175} 175}
176
177
178/* A high performance function to write data to the display,
179 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 */
183/* FixMe: somehow the red LED is affected by this, although I don't touch
184 any other bit. Therefore not used yet, except for lcd_blit() */
185void lcd_write_data(unsigned char* p_bytes, int count) __attribute__ ((section (".icode")));
186void lcd_write_data(unsigned char* p_bytes, int count)
187{
188 do
189 {
190 unsigned byte;
191 unsigned sda1; /* precalculated SC=low,SD=1 */
192 unsigned clk0sda0; /* precalculated SC and SD low */
193
194 cli(); /* make port modifications atomic */
195
196 /* precalculate the values for later bit toggling, init data write */
197 asm (
198 "mov.b @%2,%0\n" /* sda1 = PBDRL */
199 "or %4,%0\n" /* sda1 |= LCD_DS | LCD_SD DS and SD high, */
200 "and %3,%0\n" /* sda1 &= ~(LCD_CS | LCD_SC) CS and SC low */
201 "mov %0,%1\n" /* sda1 -> clk0sda0 */
202 "and %5,%1\n" /* clk0sda0 &= ~LCD_SD both low */
203 "mov.b %1,@%2\n" /* PBDRL = clk0sda0 */
204 : // outputs
205 /* %0 */ "=r"(sda1),
206 /* %1 */ "=r"(clk0sda0)
207 : // inputs
208 /* %2 */ "r"(LCDR),
209 /* %3 */ "r"(~(LCD_CS | LCD_SC)),
210 /* %4 */ "r"(LCD_DS | LCD_SD),
211 /* %5 */ "r"(~LCD_SD)
212 );
213
214 byte = *p_bytes++ << 24; /* fetch to MSB position */
215
216 /* unrolled loop to serialize the byte */
217 asm (
218 "mov %4,r0\n" /* we need &PBDRL in r0 for "or.b x,@(r0,gbr)" */
219
220 "shll %0\n" /* shift the MSB into carry */
221 "bf 1f\n"
222 "mov.b %1,@%4\n" /* if it was a "1": set SD high, SC low still */
223 "1: \n"
224 "or.b %2, @(r0,gbr)\n" /* rise SC (independent of SD level) */
225 "shll %0\n" /* shift for next round, now for longer hold time */
226 "mov.b %3,@%4\n" /* SC and SD low again */
227
228 "bf 1f\n"
229 "mov.b %1,@%4\n"
230 "1: \n"
231 "or.b %2, @(r0,gbr)\n"
232 "shll %0\n"
233 "mov.b %3,@%4\n"
234
235 "bf 1f\n"
236 "mov.b %1,@%4\n"
237 "1: \n"
238 "or.b %2, @(r0,gbr)\n"
239 "shll %0\n"
240 "mov.b %3,@%4\n"
241
242 "bf 1f\n"
243 "mov.b %1,@%4\n"
244 "1: \n"
245 "or.b %2, @(r0,gbr)\n"
246 "shll %0\n"
247 "mov.b %3,@%4\n"
248
249 "bf 1f\n"
250 "mov.b %1,@%4\n"
251 "1: \n"
252 "or.b %2, @(r0,gbr)\n"
253 "shll %0\n"
254 "mov.b %3,@%4\n"
255
256 "bf 1f\n"
257 "mov.b %1,@%4\n"
258 "1: \n"
259 "or.b %2, @(r0,gbr)\n"
260 "shll %0\n"
261 "mov.b %3,@%4\n"
262
263 "bf 1f\n"
264 "mov.b %1,@%4\n"
265 "1: \n"
266 "or.b %2, @(r0,gbr)\n"
267 "shll %0\n"
268 "mov.b %3,@%4\n"
269
270 "bf 1f\n"
271 "mov.b %1,@%4\n"
272 "1: \n"
273 "or.b %2, @(r0,gbr)\n"
274
275 "or.b %5, @(r0,gbr)\n" /* restore port */
276 :
277 : /* %0 */ "r"(byte),
278 /* %1 */ "r"(sda1),
279 /* %2 */ "I"(LCD_SC),
280 /* %3 */ "r"(clk0sda0),
281 /* %4 */ "r"(LCDR),
282 /* %5 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC)
283 );
284
285 sti();
286
287 } while (--count); /* tail loop is faster */
288}