diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-06-23 16:53:54 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-06-23 16:53:54 +0000 |
commit | 6a556c1740174d76da3f652de2a4ca0777b931c4 (patch) | |
tree | 7fb79cedee84ec829b359a2e8cee0f3c707dbfe5 /firmware/drivers/lcd-recorder.c | |
parent | bec1afada554b4624d0ef9b43b3443d1f0583cf3 (diff) | |
download | rockbox-6a556c1740174d76da3f652de2a4ca0777b931c4.tar.gz rockbox-6a556c1740174d76da3f652de2a4ca0777b931c4.zip |
Preparations for implementing the new graphics api: Ordered lcd bitmap driver defines, variables and functions by function groups. Centralised some definitions, code cleanup.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6844 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-recorder.c')
-rw-r--r-- | firmware/drivers/lcd-recorder.c | 832 |
1 files changed, 397 insertions, 435 deletions
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c index ea28e5cc2f..52455a1ff5 100644 --- a/firmware/drivers/lcd-recorder.c +++ b/firmware/drivers/lcd-recorder.c | |||
@@ -18,8 +18,6 @@ | |||
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "config.h" | 19 | #include "config.h" |
20 | 20 | ||
21 | #ifdef HAVE_LCD_BITMAP | ||
22 | |||
23 | #include "lcd.h" | 21 | #include "lcd.h" |
24 | #include "kernel.h" | 22 | #include "kernel.h" |
25 | #include "thread.h" | 23 | #include "thread.h" |
@@ -73,32 +71,12 @@ | |||
73 | #define LCD_CNTL_HIGHCOL 0x10 /* Upper column address */ | 71 | #define LCD_CNTL_HIGHCOL 0x10 /* Upper column address */ |
74 | #define LCD_CNTL_LOWCOL 0x00 /* Lower column address */ | 72 | #define LCD_CNTL_LOWCOL 0x00 /* Lower column address */ |
75 | 73 | ||
76 | #define SCROLL_SPACING 3 | ||
77 | |||
78 | #define SCROLLABLE_LINES 13 | 74 | #define SCROLLABLE_LINES 13 |
79 | 75 | ||
80 | struct scrollinfo { | 76 | /*** globals ***/ |
81 | char line[MAX_PATH + LCD_WIDTH/2 + SCROLL_SPACING + 2]; | ||
82 | int len; /* length of line in chars */ | ||
83 | int width; /* length of line in pixels */ | ||
84 | int offset; | ||
85 | int startx; | ||
86 | bool backward; /* scroll presently forward or backward? */ | ||
87 | bool bidir; | ||
88 | bool invert; /* invert the scrolled text */ | ||
89 | long start_tick; | ||
90 | }; | ||
91 | 77 | ||
92 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 78 | unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; |
93 | 79 | ||
94 | static void scroll_thread(void); | ||
95 | static char scroll_stack[DEFAULT_STACK_SIZE]; | ||
96 | static const char scroll_name[] = "scroll"; | ||
97 | static char scroll_ticks = 12; /* # of ticks between updates*/ | ||
98 | static int scroll_delay = HZ/2; /* ticks delay before start */ | ||
99 | static char scroll_step = 6; /* pixels per scroll step */ | ||
100 | static int bidir_limit = 50; /* percent */ | ||
101 | static struct scrollinfo scroll[SCROLLABLE_LINES]; | ||
102 | static int xmargin = 0; | 80 | static int xmargin = 0; |
103 | static int ymargin = 0; | 81 | static int ymargin = 0; |
104 | static int curfont = FONT_SYSFIXED; | 82 | static int curfont = FONT_SYSFIXED; |
@@ -106,18 +84,36 @@ static int curfont = FONT_SYSFIXED; | |||
106 | static int xoffset; /* needed for flip */ | 84 | static int xoffset; /* needed for flip */ |
107 | #endif | 85 | #endif |
108 | 86 | ||
109 | unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; | ||
110 | |||
111 | /* All zeros and ones bitmaps for area filling */ | 87 | /* All zeros and ones bitmaps for area filling */ |
112 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 88 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
113 | static const unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, | 89 | static const unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, |
114 | 0xff, 0xff, 0xff, 0xff}; | 90 | 0xff, 0xff, 0xff, 0xff}; |
115 | 91 | ||
92 | /* scrolling */ | ||
93 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | ||
94 | static void scroll_thread(void); | ||
95 | static char scroll_stack[DEFAULT_STACK_SIZE]; | ||
96 | static const char scroll_name[] = "scroll"; | ||
97 | static char scroll_ticks = 12; /* # of ticks between updates*/ | ||
98 | static int scroll_delay = HZ/2; /* ticks delay before start */ | ||
99 | static char scroll_step = 6; /* pixels per scroll step */ | ||
100 | static int bidir_limit = 50; /* percent */ | ||
101 | static struct scrollinfo scroll[SCROLLABLE_LINES]; | ||
102 | |||
103 | static const char scroll_tick_table[16] = { | ||
104 | /* Hz values: | ||
105 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
106 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
107 | }; | ||
108 | |||
109 | /*** driver routines ***/ | ||
110 | |||
111 | /* optimised archos recorder code is in lcd.S */ | ||
116 | 112 | ||
117 | #if CONFIG_CPU == TCC730 | 113 | #if CONFIG_CPU == TCC730 |
118 | /* Optimization opportunity: | 114 | /* Optimization opportunity: |
119 | In the following I do exactly as in the archos firmware. | 115 | In the following I do exactly as in the archos firmware. |
120 | There is probably is a better way (ie. do only one mask operation) | 116 | There is probably a better way (ie. do only one mask operation) |
121 | */ | 117 | */ |
122 | void lcd_write_command(int cmd) { | 118 | void lcd_write_command(int cmd) { |
123 | P2 &= 0xF7; | 119 | P2 &= 0xF7; |
@@ -143,6 +139,7 @@ void lcd_write_data( const unsigned char* data, int count ) { | |||
143 | } | 139 | } |
144 | #endif | 140 | #endif |
145 | 141 | ||
142 | /*** hardware configuration ***/ | ||
146 | 143 | ||
147 | int lcd_default_contrast(void) | 144 | int lcd_default_contrast(void) |
148 | { | 145 | { |
@@ -155,6 +152,73 @@ int lcd_default_contrast(void) | |||
155 | #endif | 152 | #endif |
156 | } | 153 | } |
157 | 154 | ||
155 | #ifndef SIMULATOR | ||
156 | |||
157 | void lcd_set_contrast(int val) | ||
158 | { | ||
159 | lcd_write_command(LCD_CNTL_CONTRAST); | ||
160 | lcd_write_command(val); | ||
161 | } | ||
162 | |||
163 | void lcd_set_invert_display(bool yesno) | ||
164 | { | ||
165 | if (yesno) | ||
166 | lcd_write_command(LCD_SET_REVERSE_DISPLAY); | ||
167 | else | ||
168 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); | ||
169 | } | ||
170 | |||
171 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
172 | void lcd_set_flip(bool yesno) | ||
173 | { | ||
174 | #ifdef HAVE_DISPLAY_FLIPPED | ||
175 | if (!yesno) | ||
176 | #else | ||
177 | if (yesno) | ||
178 | #endif | ||
179 | #if CONFIG_LCD == LCD_GMINI100 | ||
180 | { | ||
181 | lcd_write_command(LCD_SET_SEGMENT_REMAP | 0x01); | ||
182 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); | ||
183 | xoffset = 132 - LCD_WIDTH; | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | lcd_write_command(LCD_SET_SEGMENT_REMAP); | ||
188 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); | ||
189 | xoffset = 0; | ||
190 | } | ||
191 | #else | ||
192 | |||
193 | { | ||
194 | lcd_write_command(LCD_SET_SEGMENT_REMAP); | ||
195 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION); | ||
196 | xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 112 we have */ | ||
197 | } | ||
198 | else | ||
199 | { | ||
200 | lcd_write_command(LCD_SET_SEGMENT_REMAP | 0x01); | ||
201 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); | ||
202 | xoffset = 0; | ||
203 | } | ||
204 | #endif | ||
205 | } | ||
206 | |||
207 | /* Rolls up the lcd display by the specified amount of lines. | ||
208 | * Lines that are rolled out over the top of the screen are | ||
209 | * rolled in from the bottom again. This is a hardware | ||
210 | * remapping only and all operations on the lcd are affected. | ||
211 | * -> | ||
212 | * @param int lines - The number of lines that are rolled. | ||
213 | * The value must be 0 <= pixels < LCD_HEIGHT. */ | ||
214 | void lcd_roll(int lines) | ||
215 | { | ||
216 | lcd_write_command(LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1))); | ||
217 | } | ||
218 | |||
219 | #endif /* !SIMULATOR */ | ||
220 | |||
221 | /* LCD init */ | ||
158 | #ifdef SIMULATOR | 222 | #ifdef SIMULATOR |
159 | 223 | ||
160 | void lcd_init(void) | 224 | void lcd_init(void) |
@@ -162,13 +226,9 @@ void lcd_init(void) | |||
162 | create_thread(scroll_thread, scroll_stack, | 226 | create_thread(scroll_thread, scroll_stack, |
163 | sizeof(scroll_stack), scroll_name); | 227 | sizeof(scroll_stack), scroll_name); |
164 | } | 228 | } |
165 | |||
166 | #else | 229 | #else |
167 | 230 | ||
168 | /* | 231 | void lcd_init(void) |
169 | * Initialize LCD | ||
170 | */ | ||
171 | void lcd_init (void) | ||
172 | { | 232 | { |
173 | #if CONFIG_CPU == TCC730 | 233 | #if CONFIG_CPU == TCC730 |
174 | /* Initialise P0 & some P2 output pins: | 234 | /* Initialise P0 & some P2 output pins: |
@@ -188,7 +248,8 @@ void lcd_init (void) | |||
188 | lcd_write_command(LCD_SOFTWARE_RESET); | 248 | lcd_write_command(LCD_SOFTWARE_RESET); |
189 | lcd_write_command(LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO + 4); | 249 | lcd_write_command(LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO + 4); |
190 | lcd_write_command(LCD_SET_1OVER4_BIAS_RATIO + 0); /* force 1/4 bias: 0 */ | 250 | lcd_write_command(LCD_SET_1OVER4_BIAS_RATIO + 0); /* force 1/4 bias: 0 */ |
191 | lcd_write_command(LCD_SET_POWER_CONTROL_REGISTER + 7); /* power control register: op-amp=1, regulator=1, booster=1 */ | 251 | lcd_write_command(LCD_SET_POWER_CONTROL_REGISTER + 7); |
252 | /* power control register: op-amp=1, regulator=1, booster=1 */ | ||
192 | lcd_write_command(LCD_SET_DISPLAY_ON); | 253 | lcd_write_command(LCD_SET_DISPLAY_ON); |
193 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); | 254 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); |
194 | lcd_set_flip(false); | 255 | lcd_set_flip(false); |
@@ -200,15 +261,17 @@ void lcd_init (void) | |||
200 | 261 | ||
201 | lcd_clear_display(); | 262 | lcd_clear_display(); |
202 | lcd_update(); | 263 | lcd_update(); |
264 | |||
203 | create_thread(scroll_thread, scroll_stack, | 265 | create_thread(scroll_thread, scroll_stack, |
204 | sizeof(scroll_stack), scroll_name); | 266 | sizeof(scroll_stack), scroll_name); |
205 | } | 267 | } |
206 | 268 | ||
269 | /*** Update functions ***/ | ||
207 | 270 | ||
208 | /* Performance function that works with an external buffer | 271 | /* Performance function that works with an external buffer |
209 | note that y and height are in 8-pixel units! */ | 272 | note that y and height are in 8-pixel units! */ |
210 | void lcd_blit (const unsigned char* p_data, int x, int y, int width, | 273 | void lcd_blit(const unsigned char* p_data, int x, int y, int width, |
211 | int height, int stride) | 274 | int height, int stride) |
212 | { | 275 | { |
213 | /* Copy display bitmap to hardware */ | 276 | /* Copy display bitmap to hardware */ |
214 | while (height--) | 277 | while (height--) |
@@ -223,12 +286,10 @@ void lcd_blit (const unsigned char* p_data, int x, int y, int width, | |||
223 | } | 286 | } |
224 | 287 | ||
225 | 288 | ||
226 | /* | 289 | /* Update the display. |
227 | * Update the display. | 290 | This must be called after all other LCD functions that change the display. */ |
228 | * This must be called after all other LCD functions that change the display. | 291 | void lcd_update(void) __attribute__ ((section (".icode"))); |
229 | */ | 292 | void lcd_update(void) |
230 | void lcd_update (void) __attribute__ ((section (".icode"))); | ||
231 | void lcd_update (void) | ||
232 | { | 293 | { |
233 | int y; | 294 | int y; |
234 | 295 | ||
@@ -243,12 +304,9 @@ void lcd_update (void) | |||
243 | } | 304 | } |
244 | } | 305 | } |
245 | 306 | ||
246 | /* | 307 | /* Update a fraction of the display. */ |
247 | * Update a fraction of the display. | 308 | void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); |
248 | */ | 309 | void lcd_update_rect(int x_start, int y, int width, int height) |
249 | void lcd_update_rect (int, int, int, int) __attribute__ ((section (".icode"))); | ||
250 | void lcd_update_rect (int x_start, int y, | ||
251 | int width, int height) | ||
252 | { | 310 | { |
253 | int ymax; | 311 | int ymax; |
254 | 312 | ||
@@ -273,76 +331,9 @@ void lcd_update_rect (int x_start, int y, | |||
273 | lcd_write_data (&lcd_framebuffer[y][x_start], width); | 331 | lcd_write_data (&lcd_framebuffer[y][x_start], width); |
274 | } | 332 | } |
275 | } | 333 | } |
334 | #endif /* !SIMULATOR */ | ||
276 | 335 | ||
277 | void lcd_set_contrast(int val) | 336 | /*** parameter handling ***/ |
278 | { | ||
279 | lcd_write_command(LCD_CNTL_CONTRAST); | ||
280 | lcd_write_command(val); | ||
281 | } | ||
282 | |||
283 | void lcd_set_invert_display(bool yesno) | ||
284 | { | ||
285 | if (yesno) | ||
286 | lcd_write_command(LCD_SET_REVERSE_DISPLAY); | ||
287 | else | ||
288 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); | ||
289 | } | ||
290 | |||
291 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
292 | void lcd_set_flip(bool yesno) | ||
293 | { | ||
294 | #ifdef HAVE_DISPLAY_FLIPPED | ||
295 | if (!yesno) | ||
296 | #else | ||
297 | if (yesno) | ||
298 | #endif | ||
299 | #if CONFIG_LCD == LCD_GMINI100 | ||
300 | { | ||
301 | lcd_write_command(LCD_SET_SEGMENT_REMAP | 0x01); | ||
302 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); | ||
303 | xoffset = 132 - LCD_WIDTH; | ||
304 | } else { | ||
305 | lcd_write_command(LCD_SET_SEGMENT_REMAP); | ||
306 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); | ||
307 | xoffset = 0; | ||
308 | } | ||
309 | #else | ||
310 | |||
311 | { | ||
312 | lcd_write_command(LCD_SET_SEGMENT_REMAP); | ||
313 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION); | ||
314 | xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 112 we have */ | ||
315 | } | ||
316 | else | ||
317 | { | ||
318 | lcd_write_command(LCD_SET_SEGMENT_REMAP | 0x01); | ||
319 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08); | ||
320 | xoffset = 0; | ||
321 | } | ||
322 | #endif | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * Rolls up the lcd display by the specified amount of lines. | ||
327 | * Lines that are rolled out over the top of the screen are | ||
328 | * rolled in from the bottom again. This is a hardware | ||
329 | * remapping only and all operations on the lcd are affected. | ||
330 | * -> | ||
331 | * @param int lines - The number of lines that are rolled. | ||
332 | * The value must be 0 <= pixels < LCD_HEIGHT. | ||
333 | */ | ||
334 | void lcd_roll(int lines) | ||
335 | { | ||
336 | lcd_write_command(LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1))); | ||
337 | } | ||
338 | |||
339 | #endif /* SIMULATOR */ | ||
340 | |||
341 | void lcd_clear_display (void) | ||
342 | { | ||
343 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | ||
344 | scrolling_lines = 0; | ||
345 | } | ||
346 | 337 | ||
347 | void lcd_setmargins(int x, int y) | 338 | void lcd_setmargins(int x, int y) |
348 | { | 339 | { |
@@ -370,111 +361,237 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
370 | return font_getstringsize(str, w, h, curfont); | 361 | return font_getstringsize(str, w, h, curfont); |
371 | } | 362 | } |
372 | 363 | ||
373 | /* put a string at a given char position */ | 364 | /*** drawing functions ***/ |
374 | void lcd_puts(int x, int y, const unsigned char *str) | 365 | |
366 | void lcd_clear_display(void) | ||
375 | { | 367 | { |
376 | lcd_puts_style(x, y, str, STYLE_DEFAULT); | 368 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); |
369 | scrolling_lines = 0; | ||
377 | } | 370 | } |
378 | 371 | ||
379 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | 372 | /* Set a single pixel */ |
373 | void lcd_drawpixel(int x, int y) | ||
380 | { | 374 | { |
381 | int xpos,ypos,w,h; | 375 | DRAW_PIXEL(x,y); |
376 | } | ||
377 | |||
378 | /* Clear a single pixel */ | ||
379 | void lcd_clearpixel(int x, int y) | ||
380 | { | ||
381 | CLEAR_PIXEL(x,y); | ||
382 | } | ||
383 | |||
384 | /* Invert a single pixel */ | ||
385 | void lcd_invertpixel(int x, int y) | ||
386 | { | ||
387 | INVERT_PIXEL(x,y); | ||
388 | } | ||
389 | |||
390 | void lcd_drawline(int x1, int y1, int x2, int y2) | ||
391 | { | ||
392 | int numpixels; | ||
393 | int i; | ||
394 | int deltax, deltay; | ||
395 | int d, dinc1, dinc2; | ||
396 | int x, xinc1, xinc2; | ||
397 | int y, yinc1, yinc2; | ||
382 | 398 | ||
383 | #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS) | 399 | deltax = abs(x2 - x1); |
384 | /* We make the simulator truncate the string if it reaches the right edge, | 400 | deltay = abs(y2 - y1); |
385 | as otherwise it'll wrap. The real target doesn't wrap. */ | ||
386 | 401 | ||
387 | char buffer[12]; | 402 | if(deltax >= deltay) |
388 | if(strlen(str)+x > 11 ) { | 403 | { |
389 | strncpy(buffer, str, sizeof buffer); | 404 | numpixels = deltax; |
390 | buffer[11-x]=0; | 405 | d = 2 * deltay - deltax; |
391 | str = buffer; | 406 | dinc1 = deltay * 2; |
407 | dinc2 = (deltay - deltax) * 2; | ||
408 | xinc1 = 1; | ||
409 | xinc2 = 1; | ||
410 | yinc1 = 0; | ||
411 | yinc2 = 1; | ||
392 | } | 412 | } |
393 | xmargin = 0; | 413 | else |
394 | ymargin = 8; | 414 | { |
395 | #endif | 415 | numpixels = deltay; |
416 | d = 2 * deltax - deltay; | ||
417 | dinc1 = deltax * 2; | ||
418 | dinc2 = (deltax - deltay) * 2; | ||
419 | xinc1 = 0; | ||
420 | xinc2 = 1; | ||
421 | yinc1 = 1; | ||
422 | yinc2 = 1; | ||
423 | } | ||
424 | numpixels++; /* include endpoints */ | ||
396 | 425 | ||
397 | /* make sure scrolling is turned off on the line we are updating */ | 426 | if(x1 > x2) |
398 | scrolling_lines &= ~(1 << y); | 427 | { |
428 | xinc1 = -xinc1; | ||
429 | xinc2 = -xinc2; | ||
430 | } | ||
399 | 431 | ||
400 | if(!str || !str[0]) | 432 | if(y1 > y2) |
401 | return; | 433 | { |
434 | yinc1 = -yinc1; | ||
435 | yinc2 = -yinc2; | ||
436 | } | ||
402 | 437 | ||
403 | lcd_getstringsize(str, &w, &h); | 438 | x = x1; |
404 | xpos = xmargin + x*w / strlen(str); | 439 | y = y1; |
405 | ypos = ymargin + y*h; | ||
406 | lcd_putsxy(xpos, ypos, str); | ||
407 | lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | ||
408 | if (style & STYLE_INVERT) | ||
409 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, h); | ||
410 | 440 | ||
411 | #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS) | 441 | for(i=0; i<numpixels; i++) |
412 | lcd_update(); | 442 | { |
413 | #endif | 443 | DRAW_PIXEL(x,y); |
444 | |||
445 | if(d < 0) | ||
446 | { | ||
447 | d += dinc1; | ||
448 | x += xinc1; | ||
449 | y += yinc1; | ||
450 | } | ||
451 | else | ||
452 | { | ||
453 | d += dinc2; | ||
454 | x += xinc2; | ||
455 | y += yinc2; | ||
456 | } | ||
457 | } | ||
414 | } | 458 | } |
415 | 459 | ||
416 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 460 | void lcd_clearline(int x1, int y1, int x2, int y2) |
417 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
418 | { | 461 | { |
419 | int ch; | 462 | int numpixels; |
420 | struct font* pf = font_get(curfont); | 463 | int i; |
464 | int deltax, deltay; | ||
465 | int d, dinc1, dinc2; | ||
466 | int x, xinc1, xinc2; | ||
467 | int y, yinc1, yinc2; | ||
421 | 468 | ||
422 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) | 469 | deltax = abs(x2 - x1); |
470 | deltay = abs(y2 - y1); | ||
471 | |||
472 | if(deltax >= deltay) | ||
423 | { | 473 | { |
424 | int gwidth, width; | 474 | numpixels = deltax; |
475 | d = 2 * deltay - deltax; | ||
476 | dinc1 = deltay * 2; | ||
477 | dinc2 = (deltay - deltax) * 2; | ||
478 | xinc1 = 1; | ||
479 | xinc2 = 1; | ||
480 | yinc1 = 0; | ||
481 | yinc2 = 1; | ||
482 | } | ||
483 | else | ||
484 | { | ||
485 | numpixels = deltay; | ||
486 | d = 2 * deltax - deltay; | ||
487 | dinc1 = deltax * 2; | ||
488 | dinc2 = (deltax - deltay) * 2; | ||
489 | xinc1 = 0; | ||
490 | xinc2 = 1; | ||
491 | yinc1 = 1; | ||
492 | yinc2 = 1; | ||
493 | } | ||
494 | numpixels++; /* include endpoints */ | ||
425 | 495 | ||
426 | /* check input range */ | 496 | if(x1 > x2) |
427 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | 497 | { |
428 | ch = pf->defaultchar; | 498 | xinc1 = -xinc1; |
429 | ch -= pf->firstchar; | 499 | xinc2 = -xinc2; |
500 | } | ||
430 | 501 | ||
431 | /* get proportional width and glyph bits */ | 502 | if(y1 > y2) |
432 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | 503 | { |
433 | width = MIN (gwidth, LCD_WIDTH - x); | 504 | yinc1 = -yinc1; |
505 | yinc2 = -yinc2; | ||
506 | } | ||
434 | 507 | ||
435 | if (ofs != 0) | 508 | x = x1; |
509 | y = y1; | ||
510 | |||
511 | for(i=0; i<numpixels; i++) | ||
512 | { | ||
513 | CLEAR_PIXEL(x,y); | ||
514 | |||
515 | if(d < 0) | ||
436 | { | 516 | { |
437 | if (ofs > width) | 517 | d += dinc1; |
438 | { | 518 | x += xinc1; |
439 | ofs -= width; | 519 | y += yinc1; |
440 | continue; | ||
441 | } | ||
442 | width -= ofs; | ||
443 | } | 520 | } |
444 | 521 | else | |
445 | if (width > 0) | ||
446 | { | 522 | { |
447 | unsigned int i; | 523 | d += dinc2; |
448 | const unsigned char* bits = pf->bits + | 524 | x += xinc2; |
449 | (pf->offset ? pf->offset[ch] | 525 | y += yinc2; |
450 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
451 | |||
452 | if (ofs != 0) | ||
453 | { | ||
454 | for (i = 0; i < pf->height; i += 8) | ||
455 | { | ||
456 | lcd_bitmap (bits + ofs, x, y + i, width, | ||
457 | MIN(8, pf->height - i), true); | ||
458 | bits += gwidth; | ||
459 | } | ||
460 | } | ||
461 | else | ||
462 | lcd_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
463 | pf->height, true); | ||
464 | x += width; | ||
465 | } | 526 | } |
466 | ofs = 0; | ||
467 | } | 527 | } |
468 | } | 528 | } |
469 | 529 | ||
470 | /* put a string at a given pixel position */ | 530 | /* Draw a rectangle with upper left corner at (x, y) and size (nx, ny) */ |
471 | void lcd_putsxy(int x, int y, const unsigned char *str) | 531 | void lcd_drawrect(int x, int y, int nx, int ny) |
472 | { | 532 | { |
473 | lcd_putsxyofs(x, y, 0, str); | 533 | int i; |
534 | |||
535 | if (x > LCD_WIDTH) | ||
536 | return; | ||
537 | if (y > LCD_HEIGHT) | ||
538 | return; | ||
539 | |||
540 | if (x + nx > LCD_WIDTH) | ||
541 | nx = LCD_WIDTH - x; | ||
542 | if (y + ny > LCD_HEIGHT) | ||
543 | ny = LCD_HEIGHT - y; | ||
544 | |||
545 | /* vertical lines */ | ||
546 | for (i = 0; i < ny; i++) { | ||
547 | DRAW_PIXEL(x, (y + i)); | ||
548 | DRAW_PIXEL((x + nx - 1), (y + i)); | ||
549 | } | ||
550 | |||
551 | /* horizontal lines */ | ||
552 | for (i = 0; i < nx; i++) { | ||
553 | DRAW_PIXEL((x + i),y); | ||
554 | DRAW_PIXEL((x + i),(y + ny - 1)); | ||
555 | } | ||
474 | } | 556 | } |
475 | 557 | ||
476 | /* | 558 | /* Clear a rectangular area at (x, y), size (nx, ny) */ |
477 | * About Rockbox' internal bitmap format: | 559 | void lcd_clearrect(int x, int y, int nx, int ny) |
560 | { | ||
561 | int i; | ||
562 | for (i = 0; i < nx; i++) | ||
563 | lcd_bitmap(zeros, x+i, y, 1, ny, true); | ||
564 | } | ||
565 | |||
566 | /* Fill a rectangular area at (x, y), size (nx, ny) */ | ||
567 | void lcd_fillrect(int x, int y, int nx, int ny) | ||
568 | { | ||
569 | int i; | ||
570 | for (i = 0; i < nx; i++) | ||
571 | lcd_bitmap(ones, x+i, y, 1, ny, true); | ||
572 | } | ||
573 | |||
574 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | ||
575 | void lcd_invertrect(int x, int y, int nx, int ny) | ||
576 | { | ||
577 | int i, j; | ||
578 | |||
579 | if (x > LCD_WIDTH) | ||
580 | return; | ||
581 | if (y > LCD_HEIGHT) | ||
582 | return; | ||
583 | |||
584 | if (x + nx > LCD_WIDTH) | ||
585 | nx = LCD_WIDTH - x; | ||
586 | if (y + ny > LCD_HEIGHT) | ||
587 | ny = LCD_HEIGHT - y; | ||
588 | |||
589 | for (i = 0; i < nx; i++) | ||
590 | for (j = 0; j < ny; j++) | ||
591 | INVERT_PIXEL((x + i), (y + j)); | ||
592 | } | ||
593 | |||
594 | /* About Rockbox' internal bitmap format: | ||
478 | * | 595 | * |
479 | * A bitmap contains one bit for every pixel that defines if that pixel is | 596 | * A bitmap contains one bit for every pixel that defines if that pixel is |
480 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB | 597 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB |
@@ -483,17 +600,14 @@ void lcd_putsxy(int x, int y, const unsigned char *str) | |||
483 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | 600 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows |
484 | * 0..7, the second row defines pixel row 8..15 etc. | 601 | * 0..7, the second row defines pixel row 8..15 etc. |
485 | * | 602 | * |
486 | * This is the same as the internal lcd hw format. | 603 | * This is the same as the internal lcd hw format. */ |
487 | */ | 604 | |
488 | 605 | /* Draw a bitmap at (x, y), size (nx, ny) | |
489 | /* | 606 | if 'clear' is true, clear destination area first */ |
490 | * Draw a bitmap at (x, y), size (nx, ny) | 607 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, |
491 | * if 'clear' is true, clear destination area first | 608 | bool clear) __attribute__ ((section (".icode"))); |
492 | */ | 609 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, |
493 | void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | 610 | bool clear) |
494 | bool clear) __attribute__ ((section (".icode"))); | ||
495 | void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | ||
496 | bool clear) | ||
497 | { | 611 | { |
498 | const unsigned char *src_col; | 612 | const unsigned char *src_col; |
499 | unsigned char *dst, *dst_col; | 613 | unsigned char *dst, *dst_col; |
@@ -577,77 +691,95 @@ void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | |||
577 | } | 691 | } |
578 | } | 692 | } |
579 | 693 | ||
580 | /* | 694 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
581 | * Draw a rectangle with upper left corner at (x, y) | 695 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) |
582 | * and size (nx, ny) | ||
583 | */ | ||
584 | void lcd_drawrect (int x, int y, int nx, int ny) | ||
585 | { | 696 | { |
586 | int i; | 697 | int ch; |
698 | struct font* pf = font_get(curfont); | ||
587 | 699 | ||
588 | if (x > LCD_WIDTH) | 700 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) |
589 | return; | 701 | { |
590 | if (y > LCD_HEIGHT) | 702 | int gwidth, width; |
591 | return; | ||
592 | 703 | ||
593 | if (x + nx > LCD_WIDTH) | 704 | /* check input range */ |
594 | nx = LCD_WIDTH - x; | 705 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) |
595 | if (y + ny > LCD_HEIGHT) | 706 | ch = pf->defaultchar; |
596 | ny = LCD_HEIGHT - y; | 707 | ch -= pf->firstchar; |
597 | 708 | ||
598 | /* vertical lines */ | 709 | /* get proportional width and glyph bits */ |
599 | for (i = 0; i < ny; i++) { | 710 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; |
600 | DRAW_PIXEL(x, (y + i)); | 711 | width = MIN (gwidth, LCD_WIDTH - x); |
601 | DRAW_PIXEL((x + nx - 1), (y + i)); | ||
602 | } | ||
603 | 712 | ||
604 | /* horizontal lines */ | 713 | if (ofs != 0) |
605 | for (i = 0; i < nx; i++) { | 714 | { |
606 | DRAW_PIXEL((x + i),y); | 715 | if (ofs > width) |
607 | DRAW_PIXEL((x + i),(y + ny - 1)); | 716 | { |
717 | ofs -= width; | ||
718 | continue; | ||
719 | } | ||
720 | width -= ofs; | ||
721 | } | ||
722 | |||
723 | if (width > 0) | ||
724 | { | ||
725 | unsigned int i; | ||
726 | const unsigned char* bits = pf->bits + | ||
727 | (pf->offset ? pf->offset[ch] | ||
728 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
729 | |||
730 | if (ofs != 0) | ||
731 | { | ||
732 | for (i = 0; i < pf->height; i += 8) | ||
733 | { | ||
734 | lcd_bitmap (bits + ofs, x, y + i, width, | ||
735 | MIN(8, pf->height - i), true); | ||
736 | bits += gwidth; | ||
737 | } | ||
738 | } | ||
739 | else | ||
740 | lcd_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
741 | pf->height, true); | ||
742 | x += width; | ||
743 | } | ||
744 | ofs = 0; | ||
608 | } | 745 | } |
609 | } | 746 | } |
610 | 747 | ||
611 | /* | 748 | /* put a string at a given pixel position */ |
612 | * Clear a rectangular area at (x, y), size (nx, ny) | 749 | void lcd_putsxy(int x, int y, const unsigned char *str) |
613 | */ | ||
614 | void lcd_clearrect (int x, int y, int nx, int ny) | ||
615 | { | 750 | { |
616 | int i; | 751 | lcd_putsxyofs(x, y, 0, str); |
617 | for (i = 0; i < nx; i++) | ||
618 | lcd_bitmap (zeros, x+i, y, 1, ny, true); | ||
619 | } | 752 | } |
620 | 753 | ||
621 | /* | 754 | /*** Line oriented text output ***/ |
622 | * Fill a rectangular area at (x, y), size (nx, ny) | ||
623 | */ | ||
624 | void lcd_fillrect (int x, int y, int nx, int ny) | ||
625 | { | ||
626 | int i; | ||
627 | for (i = 0; i < nx; i++) | ||
628 | lcd_bitmap (ones, x+i, y, 1, ny, true); | ||
629 | } | ||
630 | 755 | ||
631 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | 756 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) |
632 | void lcd_invertrect (int x, int y, int nx, int ny) | ||
633 | { | 757 | { |
634 | int i, j; | 758 | int xpos,ypos,w,h; |
635 | 759 | ||
636 | if (x > LCD_WIDTH) | 760 | /* make sure scrolling is turned off on the line we are updating */ |
637 | return; | 761 | scrolling_lines &= ~(1 << y); |
638 | if (y > LCD_HEIGHT) | 762 | |
763 | if(!str || !str[0]) | ||
639 | return; | 764 | return; |
640 | 765 | ||
641 | if (x + nx > LCD_WIDTH) | 766 | lcd_getstringsize(str, &w, &h); |
642 | nx = LCD_WIDTH - x; | 767 | xpos = xmargin + x*w / strlen(str); |
643 | if (y + ny > LCD_HEIGHT) | 768 | ypos = ymargin + y*h; |
644 | ny = LCD_HEIGHT - y; | 769 | lcd_putsxy(xpos, ypos, str); |
770 | lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | ||
771 | if (style & STYLE_INVERT) | ||
772 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, h); | ||
773 | } | ||
645 | 774 | ||
646 | for (i = 0; i < nx; i++) | 775 | /* put a string at a given char position */ |
647 | for (j = 0; j < ny; j++) | 776 | void lcd_puts(int x, int y, const unsigned char *str) |
648 | INVERT_PIXEL((x + i), (y + j)); | 777 | { |
778 | lcd_puts_style(x, y, str, STYLE_DEFAULT); | ||
649 | } | 779 | } |
650 | 780 | ||
781 | /*** scrolling ***/ | ||
782 | |||
651 | /* Reverse the invert setting of the scrolling line (if any) at given char | 783 | /* Reverse the invert setting of the scrolling line (if any) at given char |
652 | position. Setting will go into affect next time line scrolls. */ | 784 | position. Setting will go into affect next time line scrolls. */ |
653 | void lcd_invertscroll(int x, int y) | 785 | void lcd_invertscroll(int x, int y) |
@@ -660,168 +792,29 @@ void lcd_invertscroll(int x, int y) | |||
660 | s->invert = !s->invert; | 792 | s->invert = !s->invert; |
661 | } | 793 | } |
662 | 794 | ||
663 | void lcd_drawline( int x1, int y1, int x2, int y2 ) | 795 | void lcd_stop_scroll(void) |
664 | { | 796 | { |
665 | int numpixels; | 797 | scrolling_lines=0; |
666 | int i; | ||
667 | int deltax, deltay; | ||
668 | int d, dinc1, dinc2; | ||
669 | int x, xinc1, xinc2; | ||
670 | int y, yinc1, yinc2; | ||
671 | |||
672 | deltax = abs(x2 - x1); | ||
673 | deltay = abs(y2 - y1); | ||
674 | |||
675 | if(deltax >= deltay) | ||
676 | { | ||
677 | numpixels = deltax; | ||
678 | d = 2 * deltay - deltax; | ||
679 | dinc1 = deltay * 2; | ||
680 | dinc2 = (deltay - deltax) * 2; | ||
681 | xinc1 = 1; | ||
682 | xinc2 = 1; | ||
683 | yinc1 = 0; | ||
684 | yinc2 = 1; | ||
685 | } | ||
686 | else | ||
687 | { | ||
688 | numpixels = deltay; | ||
689 | d = 2 * deltax - deltay; | ||
690 | dinc1 = deltax * 2; | ||
691 | dinc2 = (deltax - deltay) * 2; | ||
692 | xinc1 = 0; | ||
693 | xinc2 = 1; | ||
694 | yinc1 = 1; | ||
695 | yinc2 = 1; | ||
696 | } | ||
697 | numpixels++; /* include endpoints */ | ||
698 | |||
699 | if(x1 > x2) | ||
700 | { | ||
701 | xinc1 = -xinc1; | ||
702 | xinc2 = -xinc2; | ||
703 | } | ||
704 | |||
705 | if(y1 > y2) | ||
706 | { | ||
707 | yinc1 = -yinc1; | ||
708 | yinc2 = -yinc2; | ||
709 | } | ||
710 | |||
711 | x = x1; | ||
712 | y = y1; | ||
713 | |||
714 | for(i=0; i<numpixels; i++) | ||
715 | { | ||
716 | DRAW_PIXEL(x,y); | ||
717 | |||
718 | if(d < 0) | ||
719 | { | ||
720 | d += dinc1; | ||
721 | x += xinc1; | ||
722 | y += yinc1; | ||
723 | } | ||
724 | else | ||
725 | { | ||
726 | d += dinc2; | ||
727 | x += xinc2; | ||
728 | y += yinc2; | ||
729 | } | ||
730 | } | ||
731 | } | 798 | } |
732 | 799 | ||
733 | void lcd_clearline( int x1, int y1, int x2, int y2 ) | 800 | void lcd_scroll_speed(int speed) |
734 | { | 801 | { |
735 | int numpixels; | 802 | scroll_ticks = scroll_tick_table[speed]; |
736 | int i; | ||
737 | int deltax, deltay; | ||
738 | int d, dinc1, dinc2; | ||
739 | int x, xinc1, xinc2; | ||
740 | int y, yinc1, yinc2; | ||
741 | |||
742 | deltax = abs(x2 - x1); | ||
743 | deltay = abs(y2 - y1); | ||
744 | |||
745 | if(deltax >= deltay) | ||
746 | { | ||
747 | numpixels = deltax; | ||
748 | d = 2 * deltay - deltax; | ||
749 | dinc1 = deltay * 2; | ||
750 | dinc2 = (deltay - deltax) * 2; | ||
751 | xinc1 = 1; | ||
752 | xinc2 = 1; | ||
753 | yinc1 = 0; | ||
754 | yinc2 = 1; | ||
755 | } | ||
756 | else | ||
757 | { | ||
758 | numpixels = deltay; | ||
759 | d = 2 * deltax - deltay; | ||
760 | dinc1 = deltax * 2; | ||
761 | dinc2 = (deltax - deltay) * 2; | ||
762 | xinc1 = 0; | ||
763 | xinc2 = 1; | ||
764 | yinc1 = 1; | ||
765 | yinc2 = 1; | ||
766 | } | ||
767 | numpixels++; /* include endpoints */ | ||
768 | |||
769 | if(x1 > x2) | ||
770 | { | ||
771 | xinc1 = -xinc1; | ||
772 | xinc2 = -xinc2; | ||
773 | } | ||
774 | |||
775 | if(y1 > y2) | ||
776 | { | ||
777 | yinc1 = -yinc1; | ||
778 | yinc2 = -yinc2; | ||
779 | } | ||
780 | |||
781 | x = x1; | ||
782 | y = y1; | ||
783 | |||
784 | for(i=0; i<numpixels; i++) | ||
785 | { | ||
786 | CLEAR_PIXEL(x,y); | ||
787 | |||
788 | if(d < 0) | ||
789 | { | ||
790 | d += dinc1; | ||
791 | x += xinc1; | ||
792 | y += yinc1; | ||
793 | } | ||
794 | else | ||
795 | { | ||
796 | d += dinc2; | ||
797 | x += xinc2; | ||
798 | y += yinc2; | ||
799 | } | ||
800 | } | ||
801 | } | 803 | } |
802 | 804 | ||
803 | /* | 805 | void lcd_scroll_step(int step) |
804 | * Set a single pixel | ||
805 | */ | ||
806 | void lcd_drawpixel(int x, int y) | ||
807 | { | 806 | { |
808 | DRAW_PIXEL(x,y); | 807 | scroll_step = step; |
809 | } | 808 | } |
810 | 809 | ||
811 | /* | 810 | void lcd_scroll_delay(int ms) |
812 | * Clear a single pixel | ||
813 | */ | ||
814 | void lcd_clearpixel(int x, int y) | ||
815 | { | 811 | { |
816 | CLEAR_PIXEL(x,y); | 812 | scroll_delay = ms / (HZ / 10); |
817 | } | 813 | } |
818 | 814 | ||
819 | /* | 815 | void lcd_bidir_scroll(int percent) |
820 | * Invert a single pixel | ||
821 | */ | ||
822 | void lcd_invertpixel(int x, int y) | ||
823 | { | 816 | { |
824 | INVERT_PIXEL(x,y); | 817 | bidir_limit = percent; |
825 | } | 818 | } |
826 | 819 | ||
827 | void lcd_puts_scroll(int x, int y, const unsigned char *string) | 820 | void lcd_puts_scroll(int x, int y, const unsigned char *string) |
@@ -886,36 +879,6 @@ void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) | |||
886 | scrolling_lines &= ~(1<<y); | 879 | scrolling_lines &= ~(1<<y); |
887 | } | 880 | } |
888 | 881 | ||
889 | void lcd_stop_scroll(void) | ||
890 | { | ||
891 | scrolling_lines=0; | ||
892 | } | ||
893 | |||
894 | static const char scroll_tick_table[16] = { | ||
895 | /* Hz values: | ||
896 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
897 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
898 | }; | ||
899 | |||
900 | void lcd_scroll_speed(int speed) | ||
901 | { | ||
902 | scroll_ticks = scroll_tick_table[speed]; | ||
903 | } | ||
904 | |||
905 | void lcd_scroll_step(int step) | ||
906 | { | ||
907 | scroll_step = step; | ||
908 | } | ||
909 | |||
910 | void lcd_scroll_delay(int ms) | ||
911 | { | ||
912 | scroll_delay = ms / (HZ / 10); | ||
913 | } | ||
914 | |||
915 | void lcd_bidir_scroll(int percent) | ||
916 | { | ||
917 | bidir_limit = percent; | ||
918 | } | ||
919 | static void scroll_thread(void) | 882 | static void scroll_thread(void) |
920 | { | 883 | { |
921 | struct font* pf; | 884 | struct font* pf; |
@@ -978,4 +941,3 @@ static void scroll_thread(void) | |||
978 | } | 941 | } |
979 | } | 942 | } |
980 | 943 | ||
981 | #endif | ||