diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-h100-remote.c | 832 | ||||
-rw-r--r-- | firmware/drivers/lcd-h100.c | 858 | ||||
-rw-r--r-- | firmware/drivers/lcd-player.c | 14 | ||||
-rw-r--r-- | firmware/drivers/lcd-recorder.c | 832 | ||||
-rw-r--r-- | firmware/export/lcd-remote.h | 79 | ||||
-rw-r--r-- | firmware/export/lcd.h | 113 |
6 files changed, 1319 insertions, 1409 deletions
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-h100-remote.c index 04a4b7f7a0..4798a51743 100644 --- a/firmware/drivers/lcd-h100-remote.c +++ b/firmware/drivers/lcd-h100-remote.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include "config.h" | 20 | #include "config.h" |
21 | #include "cpu.h" | 21 | #include "cpu.h" |
22 | #include "lcd.h" | ||
22 | #include "lcd-remote.h" | 23 | #include "lcd-remote.h" |
23 | #include "kernel.h" | 24 | #include "kernel.h" |
24 | #include "thread.h" | 25 | #include "thread.h" |
@@ -29,18 +30,41 @@ | |||
29 | #include "system.h" | 30 | #include "system.h" |
30 | #include "font.h" | 31 | #include "font.h" |
31 | 32 | ||
32 | /* All zeros and ones bitmaps for area filling */ | 33 | /*** definitions ***/ |
33 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
34 | static const unsigned char ones[8] = { | ||
35 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
36 | }; | ||
37 | 34 | ||
38 | static int curfont = FONT_SYSFIXED; | 35 | #define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0 |
39 | static int xmargin = 0; | 36 | #define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1 |
40 | static int ymargin = 0; | 37 | #define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0 |
41 | #ifndef SIMULATOR | 38 | #define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8 |
42 | static int xoffset; /* needed for flip */ | 39 | #define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae |
43 | #endif | 40 | #define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4 |
41 | #define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6 | ||
42 | #define LCD_REMOTE_CNTL_NOP 0xe3 | ||
43 | #define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b | ||
44 | #define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20 | ||
45 | #define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2 | ||
46 | #define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81 | ||
47 | #define LCD_REMOTE_CNTL_INIT_LINE 0x40 | ||
48 | #define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0 | ||
49 | |||
50 | #define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */ | ||
51 | #define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */ | ||
52 | |||
53 | #define CS_LO GPIO1_OUT &= ~0x00000004 | ||
54 | #define CS_HI GPIO1_OUT |= 0x00000004 | ||
55 | #define CLK_LO GPIO_OUT &= ~0x10000000 | ||
56 | #define CLK_HI GPIO_OUT |= 0x10000000 | ||
57 | #define DATA_LO GPIO1_OUT &= ~0x00040000 | ||
58 | #define DATA_HI GPIO1_OUT |= 0x00040000 | ||
59 | #define RS_LO GPIO_OUT &= ~0x00010000 | ||
60 | #define RS_HI GPIO_OUT |= 0x00010000 | ||
61 | |||
62 | /* delay loop */ | ||
63 | #define DELAY do { int _x; for(_x=0;_x<3;_x++);} while (0) | ||
64 | |||
65 | #define SCROLLABLE_LINES 13 | ||
66 | |||
67 | /*** globals ***/ | ||
44 | 68 | ||
45 | unsigned char lcd_remote_framebuffer[LCD_REMOTE_HEIGHT/8][LCD_REMOTE_WIDTH] | 69 | unsigned char lcd_remote_framebuffer[LCD_REMOTE_HEIGHT/8][LCD_REMOTE_WIDTH] |
46 | #ifndef SIMULATOR | 70 | #ifndef SIMULATOR |
@@ -48,38 +72,34 @@ unsigned char lcd_remote_framebuffer[LCD_REMOTE_HEIGHT/8][LCD_REMOTE_WIDTH] | |||
48 | #endif | 72 | #endif |
49 | ; | 73 | ; |
50 | 74 | ||
51 | #define SCROLL_SPACING 3 | 75 | static int curfont = FONT_SYSFIXED; |
52 | #define SCROLLABLE_LINES 26 | 76 | static int xmargin = 0; |
53 | 77 | static int ymargin = 0; | |
54 | struct scrollinfo { | ||
55 | char line[MAX_PATH + LCD_REMOTE_WIDTH/2 + SCROLL_SPACING + 2]; | ||
56 | int len; /* length of line in chars */ | ||
57 | int width; /* length of line in pixels */ | ||
58 | int offset; | ||
59 | int startx; | ||
60 | bool backward; /* scroll presently forward or backward? */ | ||
61 | bool bidir; | ||
62 | bool invert; /* invert the scrolled text */ | ||
63 | long start_tick; | ||
64 | }; | ||
65 | |||
66 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | ||
67 | |||
68 | #ifndef SIMULATOR | 78 | #ifndef SIMULATOR |
69 | static int countdown; /* for remote plugging debounce */ | 79 | static int xoffset; /* needed for flip */ |
80 | |||
81 | /* remote hotplug */ | ||
82 | static int countdown; /* for remote plugging debounce */ | ||
70 | static bool last_remote_status = false; | 83 | static bool last_remote_status = false; |
71 | static bool init_remote = false; /* scroll thread should init lcd */ | 84 | static bool init_remote = false; /* scroll thread should init lcd */ |
72 | static bool remote_initialized = false; | 85 | static bool remote_initialized = false; |
73 | 86 | /* cached settings values */ | |
74 | /* cached settings values, for hotplug init */ | ||
75 | static bool cached_invert = false; | 87 | static bool cached_invert = false; |
76 | static bool cached_flip = false; | 88 | static bool cached_flip = false; |
77 | static int cached_contrast = 32; | 89 | static int cached_contrast = 32; |
78 | static int cached_roll = 0; | 90 | static int cached_roll = 0; |
91 | #endif | ||
79 | 92 | ||
93 | /* All zeros and ones bitmaps for area filling */ | ||
94 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
95 | static const unsigned char ones[8] = { | ||
96 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
97 | }; | ||
98 | |||
99 | /* scrolling */ | ||
100 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | ||
80 | static void scroll_thread(void); | 101 | static void scroll_thread(void); |
81 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | 102 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; |
82 | #endif | ||
83 | static const char scroll_name[] = "remote_scroll"; | 103 | static const char scroll_name[] = "remote_scroll"; |
84 | static char scroll_ticks = 12; /* # of ticks between updates*/ | 104 | static char scroll_ticks = 12; /* # of ticks between updates*/ |
85 | static int scroll_delay = HZ/2; /* ticks delay before start */ | 105 | static int scroll_delay = HZ/2; /* ticks delay before start */ |
@@ -87,18 +107,13 @@ static char scroll_step = 6; /* pixels per scroll step */ | |||
87 | static int bidir_limit = 50; /* percent */ | 107 | static int bidir_limit = 50; /* percent */ |
88 | static struct scrollinfo scroll[SCROLLABLE_LINES]; | 108 | static struct scrollinfo scroll[SCROLLABLE_LINES]; |
89 | 109 | ||
110 | static const char scroll_tick_table[16] = { | ||
111 | /* Hz values: | ||
112 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
113 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
114 | }; | ||
90 | 115 | ||
91 | #define CS_LO GPIO1_OUT &= ~0x00000004 | 116 | /*** driver routines ***/ |
92 | #define CS_HI GPIO1_OUT |= 0x00000004 | ||
93 | #define CLK_LO GPIO_OUT &= ~0x10000000 | ||
94 | #define CLK_HI GPIO_OUT |= 0x10000000 | ||
95 | #define DATA_LO GPIO1_OUT &= ~0x00040000 | ||
96 | #define DATA_HI GPIO1_OUT |= 0x00040000 | ||
97 | #define RS_LO GPIO_OUT &= ~0x00010000 | ||
98 | #define RS_HI GPIO_OUT |= 0x00010000 | ||
99 | |||
100 | /* delay loop */ | ||
101 | #define DELAY do { int _x; for(_x=0;_x<3;_x++);} while (0) | ||
102 | 117 | ||
103 | #ifndef SIMULATOR | 118 | #ifndef SIMULATOR |
104 | void lcd_remote_backlight_on(void) | 119 | void lcd_remote_backlight_on(void) |
@@ -115,8 +130,8 @@ void lcd_remote_write_command(int cmd) | |||
115 | { | 130 | { |
116 | int i; | 131 | int i; |
117 | 132 | ||
118 | CS_LO; | ||
119 | RS_LO; | 133 | RS_LO; |
134 | CS_LO; | ||
120 | 135 | ||
121 | for (i = 0; i < 8; i++) | 136 | for (i = 0; i < 8; i++) |
122 | { | 137 | { |
@@ -140,8 +155,8 @@ void lcd_remote_write_data(const unsigned char* p_bytes, int count) | |||
140 | int i, j; | 155 | int i, j; |
141 | int data; | 156 | int data; |
142 | 157 | ||
143 | CS_LO; | ||
144 | RS_HI; | 158 | RS_HI; |
159 | CS_LO; | ||
145 | 160 | ||
146 | for (i = 0; i < count; i++) | 161 | for (i = 0; i < count; i++) |
147 | { | 162 | { |
@@ -202,24 +217,16 @@ void lcd_remote_write_command_ex(int cmd, int data) | |||
202 | 217 | ||
203 | CS_HI; | 218 | CS_HI; |
204 | } | 219 | } |
220 | #endif /* !SIMULATOR */ | ||
205 | 221 | ||
206 | #define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0 | 222 | /*** hardware configuration ***/ |
207 | #define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1 | ||
208 | #define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0 | ||
209 | #define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8 | ||
210 | #define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae | ||
211 | #define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4 | ||
212 | #define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6 | ||
213 | #define LCD_REMOTE_CNTL_NOP 0xe3 | ||
214 | #define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b | ||
215 | #define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20 | ||
216 | #define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2 | ||
217 | #define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81 | ||
218 | #define LCD_REMOTE_CNTL_INIT_LINE 0x40 | ||
219 | #define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0 | ||
220 | 223 | ||
221 | #define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */ | 224 | int lcd_remote_default_contrast(void) |
222 | #define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */ | 225 | { |
226 | return 32; | ||
227 | } | ||
228 | |||
229 | #ifndef SIMULATOR | ||
223 | 230 | ||
224 | void lcd_remote_powersave(bool on) | 231 | void lcd_remote_powersave(bool on) |
225 | { | 232 | { |
@@ -268,161 +275,31 @@ void lcd_remote_set_flip(bool yesno) | |||
268 | } | 275 | } |
269 | } | 276 | } |
270 | 277 | ||
271 | int lcd_remote_default_contrast(void) | 278 | /* Rolls up the lcd display by the specified amount of lines. |
272 | { | 279 | * Lines that are rolled out over the top of the screen are |
273 | return 32; | 280 | * rolled in from the bottom again. This is a hardware |
274 | } | 281 | * remapping only and all operations on the lcd are affected. |
275 | 282 | * -> | |
276 | #endif | 283 | * @param int lines - The number of lines that are rolled. |
277 | 284 | * The value must be 0 <= pixels < LCD_REMOTE_HEIGHT. */ | |
278 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int nx, int ny, bool clear) __attribute__ ((section (".icode"))); | 285 | void lcd_remote_roll(int lines) |
279 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int nx, int ny, bool clear) | ||
280 | { | ||
281 | const unsigned char *src_col; | ||
282 | unsigned char *dst, *dst_col; | ||
283 | unsigned int data, mask1, mask2, mask3, mask4; | ||
284 | int stride, shift; | ||
285 | |||
286 | if (((unsigned) x >= LCD_REMOTE_WIDTH) || ((unsigned) y >= LCD_REMOTE_HEIGHT)) | ||
287 | { | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | stride = nx; /* otherwise right-clipping will destroy the image */ | ||
292 | |||
293 | if (((unsigned) (x + nx)) >= LCD_REMOTE_WIDTH) | ||
294 | { | ||
295 | nx = LCD_REMOTE_WIDTH - x; | ||
296 | } | ||
297 | |||
298 | if (((unsigned) (y + ny)) >= LCD_REMOTE_HEIGHT) | ||
299 | { | ||
300 | ny = LCD_REMOTE_HEIGHT - y; | ||
301 | } | ||
302 | |||
303 | dst = &lcd_remote_framebuffer[y >> 3][x]; | ||
304 | shift = y & 7; | ||
305 | |||
306 | if (!shift && clear) /* shortcut for byte aligned match with clear */ | ||
307 | { | ||
308 | while (ny >= 8) /* all full rows */ | ||
309 | { | ||
310 | memcpy(dst, src, nx); | ||
311 | src += stride; | ||
312 | dst += LCD_REMOTE_WIDTH; | ||
313 | ny -= 8; | ||
314 | } | ||
315 | if (ny == 0) /* nothing left to do? */ | ||
316 | { | ||
317 | return; | ||
318 | } | ||
319 | /* last partial row to do by default routine */ | ||
320 | } | ||
321 | |||
322 | ny += shift; | ||
323 | |||
324 | /* Calculate bit masks */ | ||
325 | mask4 = ~(0xfe << ((ny-1) & 7)); /* data mask for last partial row */ | ||
326 | |||
327 | if (clear) | ||
328 | { | ||
329 | mask1 = ~(0xff << shift); /* clearing of first partial row */ | ||
330 | mask2 = 0; /* clearing of intermediate (full) rows */ | ||
331 | mask3 = ~mask4; /* clearing of last partial row */ | ||
332 | if (ny <= 8) | ||
333 | { | ||
334 | mask3 |= mask1; | ||
335 | } | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | mask1 = mask2 = mask3 = 0xff; | ||
340 | } | ||
341 | |||
342 | /* Loop for each column */ | ||
343 | for (x = 0; x < nx; x++) | ||
344 | { | ||
345 | src_col = src++; | ||
346 | dst_col = dst++; | ||
347 | data = 0; | ||
348 | y = 0; | ||
349 | |||
350 | if (ny > 8) | ||
351 | { | ||
352 | /* First partial row */ | ||
353 | data = *src_col << shift; | ||
354 | *dst_col = (*dst_col & mask1) | data; | ||
355 | src_col += stride; | ||
356 | dst_col += LCD_REMOTE_WIDTH; | ||
357 | data >>= 8; | ||
358 | |||
359 | /* Intermediate rows */ | ||
360 | for (y = 8; y < ny-8; y += 8) | ||
361 | { | ||
362 | data |= *src_col << shift; | ||
363 | *dst_col = (*dst_col & mask2) | data; | ||
364 | src_col += stride; | ||
365 | dst_col += LCD_REMOTE_WIDTH; | ||
366 | data >>= 8; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | /* Last partial row */ | ||
371 | if (y + shift < ny) | ||
372 | { | ||
373 | data |= *src_col << shift; | ||
374 | } | ||
375 | |||
376 | *dst_col = (*dst_col & mask3) | (data & mask4); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | void lcd_remote_drawrect(int x, int y, int nx, int ny) | ||
381 | { | 286 | { |
382 | int i; | 287 | char data[2]; |
383 | |||
384 | if (x > LCD_REMOTE_WIDTH) | ||
385 | { | ||
386 | return; | ||
387 | } | ||
388 | 288 | ||
389 | if (y > LCD_REMOTE_HEIGHT) | 289 | cached_roll = lines; |
390 | { | ||
391 | return; | ||
392 | } | ||
393 | 290 | ||
394 | if (x + nx > LCD_REMOTE_WIDTH) | 291 | if (remote_initialized) |
395 | { | 292 | { |
396 | nx = LCD_REMOTE_WIDTH - x; | 293 | lines &= LCD_REMOTE_HEIGHT-1; |
397 | } | 294 | data[0] = lines & 0xff; |
295 | data[1] = lines >> 8; | ||
398 | 296 | ||
399 | if (y + ny > LCD_REMOTE_HEIGHT) | 297 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line |
400 | { | 298 | lcd_remote_write_data(data, 2); |
401 | ny = LCD_REMOTE_HEIGHT - y; | ||
402 | } | ||
403 | |||
404 | /* vertical lines */ | ||
405 | for (i = 0; i < ny; i++) | ||
406 | { | ||
407 | REMOTE_DRAW_PIXEL(x, (y + i)); | ||
408 | REMOTE_DRAW_PIXEL((x + nx - 1), (y + i)); | ||
409 | } | ||
410 | |||
411 | /* horizontal lines */ | ||
412 | for (i = 0; i < nx; i++) | ||
413 | { | ||
414 | REMOTE_DRAW_PIXEL((x + i),y); | ||
415 | REMOTE_DRAW_PIXEL((x + i),(y + ny - 1)); | ||
416 | } | 299 | } |
417 | } | 300 | } |
418 | 301 | ||
419 | void lcd_remote_clear_display(void) | 302 | /* The actual LCD init */ |
420 | { | ||
421 | memset(lcd_remote_framebuffer, 0, sizeof lcd_remote_framebuffer); | ||
422 | } | ||
423 | |||
424 | #ifndef SIMULATOR | ||
425 | |||
426 | static void remote_lcd_init(void) | 303 | static void remote_lcd_init(void) |
427 | { | 304 | { |
428 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0); | 305 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0); |
@@ -451,6 +328,7 @@ static void remote_lcd_init(void) | |||
451 | lcd_remote_roll(cached_roll); | 328 | lcd_remote_roll(cached_roll); |
452 | } | 329 | } |
453 | 330 | ||
331 | /* Monitor remote hotswap */ | ||
454 | static void remote_tick(void) | 332 | static void remote_tick(void) |
455 | { | 333 | { |
456 | bool current_status; | 334 | bool current_status; |
@@ -485,6 +363,7 @@ static void remote_tick(void) | |||
485 | } | 363 | } |
486 | } | 364 | } |
487 | 365 | ||
366 | /* Initialise ports and kick off monitor */ | ||
488 | void lcd_remote_init(void) | 367 | void lcd_remote_init(void) |
489 | { | 368 | { |
490 | GPIO_FUNCTION |= 0x10010800; /* GPIO11: Backlight | 369 | GPIO_FUNCTION |= 0x10010800; /* GPIO11: Backlight |
@@ -503,13 +382,12 @@ void lcd_remote_init(void) | |||
503 | sizeof(scroll_stack), scroll_name); | 382 | sizeof(scroll_stack), scroll_name); |
504 | } | 383 | } |
505 | 384 | ||
385 | /*** update functions ***/ | ||
506 | 386 | ||
507 | /* | 387 | /* Update the display. |
508 | * Update the display. | 388 | This must be called after all other LCD functions that change the display. */ |
509 | * This must be called after all other LCD functions that change the display. | 389 | void lcd_remote_update(void) __attribute__ ((section (".icode"))); |
510 | */ | 390 | void lcd_remote_update(void) |
511 | void lcd_remote_update (void) __attribute__ ((section (".icode"))); | ||
512 | void lcd_remote_update (void) | ||
513 | { | 391 | { |
514 | int y; | 392 | int y; |
515 | 393 | ||
@@ -526,12 +404,9 @@ void lcd_remote_update (void) | |||
526 | } | 404 | } |
527 | } | 405 | } |
528 | 406 | ||
529 | /* | 407 | /* Update a fraction of the display. */ |
530 | * Update a fraction of the display. | 408 | void lcd_remote_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); |
531 | */ | 409 | void lcd_remote_update_rect(int x_start, int y, int width, int height) |
532 | void lcd_remote_update_rect (int, int, int, int) __attribute__ ((section (".icode"))); | ||
533 | void lcd_remote_update_rect (int x_start, int y, | ||
534 | int width, int height) | ||
535 | { | 410 | { |
536 | int ymax; | 411 | int ymax; |
537 | 412 | ||
@@ -560,35 +435,9 @@ void lcd_remote_update_rect (int x_start, int y, | |||
560 | lcd_remote_write_data(&lcd_remote_framebuffer[y][x_start], width); | 435 | lcd_remote_write_data(&lcd_remote_framebuffer[y][x_start], width); |
561 | } | 436 | } |
562 | } | 437 | } |
438 | #endif /* !SIMULATOR */ | ||
563 | 439 | ||
564 | /** | 440 | /*** parameter handling ***/ |
565 | * Rolls up the lcd display by the specified amount of lines. | ||
566 | * Lines that are rolled out over the top of the screen are | ||
567 | * rolled in from the bottom again. This is a hardware | ||
568 | * remapping only and all operations on the lcd are affected. | ||
569 | * -> | ||
570 | * @param int lines - The number of lines that are rolled. | ||
571 | * The value must be 0 <= pixels < LCD_REMOTE_HEIGHT. | ||
572 | */ | ||
573 | void lcd_remote_roll(int lines) | ||
574 | { | ||
575 | char data[2]; | ||
576 | |||
577 | cached_roll = lines; | ||
578 | |||
579 | if (remote_initialized) | ||
580 | { | ||
581 | lines &= LCD_REMOTE_HEIGHT-1; | ||
582 | data[0] = lines & 0xff; | ||
583 | data[1] = lines >> 8; | ||
584 | |||
585 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line | ||
586 | lcd_remote_write_data(data, 2); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | #endif | ||
591 | |||
592 | 441 | ||
593 | void lcd_remote_setmargins(int x, int y) | 442 | void lcd_remote_setmargins(int x, int y) |
594 | { | 443 | { |
@@ -617,146 +466,32 @@ int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) | |||
617 | return font_getstringsize(str, w, h, curfont); | 466 | return font_getstringsize(str, w, h, curfont); |
618 | } | 467 | } |
619 | 468 | ||
620 | /* put a string at a given char position */ | 469 | /*** drawing functions ***/ |
621 | void lcd_remote_puts(int x, int y, const unsigned char *str) | ||
622 | { | ||
623 | lcd_remote_puts_style(x, y, str, STYLE_DEFAULT); | ||
624 | } | ||
625 | |||
626 | void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style) | ||
627 | { | ||
628 | int xpos,ypos,w,h; | ||
629 | |||
630 | /* make sure scrolling is turned off on the line we are updating */ | ||
631 | //scrolling_lines &= ~(1 << y); | ||
632 | |||
633 | if(!str || !str[0]) | ||
634 | return; | ||
635 | |||
636 | lcd_remote_getstringsize(str, &w, &h); | ||
637 | xpos = xmargin + x*w / strlen(str); | ||
638 | ypos = ymargin + y*h; | ||
639 | lcd_remote_putsxy(xpos, ypos, str); | ||
640 | lcd_remote_clearrect(xpos + w, ypos, LCD_REMOTE_WIDTH - (xpos + w), h); | ||
641 | if (style & STYLE_INVERT) | ||
642 | lcd_remote_invertrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, h); | ||
643 | |||
644 | } | ||
645 | |||
646 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | ||
647 | static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
648 | { | ||
649 | int ch; | ||
650 | struct font* pf = font_get(curfont); | ||
651 | |||
652 | while ((ch = *str++) != '\0' && x < LCD_REMOTE_WIDTH) | ||
653 | { | ||
654 | int gwidth, width; | ||
655 | |||
656 | /* check input range */ | ||
657 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
658 | ch = pf->defaultchar; | ||
659 | ch -= pf->firstchar; | ||
660 | |||
661 | /* get proportional width and glyph bits */ | ||
662 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | ||
663 | width = MIN (gwidth, LCD_REMOTE_WIDTH - x); | ||
664 | |||
665 | if (ofs != 0) | ||
666 | { | ||
667 | if (ofs > width) | ||
668 | { | ||
669 | ofs -= width; | ||
670 | continue; | ||
671 | } | ||
672 | width -= ofs; | ||
673 | } | ||
674 | |||
675 | if (width > 0) | ||
676 | { | ||
677 | unsigned int i; | ||
678 | const unsigned char* bits = pf->bits + | ||
679 | (pf->offset ? pf->offset[ch] | ||
680 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
681 | |||
682 | if (ofs != 0) | ||
683 | { | ||
684 | for (i = 0; i < pf->height; i += 8) | ||
685 | { | ||
686 | lcd_remote_bitmap (bits + ofs, x, y + i, width, | ||
687 | MIN(8, pf->height - i), true); | ||
688 | bits += gwidth; | ||
689 | } | ||
690 | } | ||
691 | else | ||
692 | lcd_remote_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
693 | pf->height, true); | ||
694 | x += width; | ||
695 | } | ||
696 | ofs = 0; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | /* put a string at a given pixel position */ | ||
701 | void lcd_remote_putsxy(int x, int y, const unsigned char *str) | ||
702 | { | ||
703 | lcd_remote_putsxyofs(x, y, 0, str); | ||
704 | } | ||
705 | |||
706 | 470 | ||
707 | /* | 471 | void lcd_remote_clear_display(void) |
708 | * Clear a rectangular area at (x, y), size (nx, ny) | ||
709 | */ | ||
710 | void lcd_remote_clearrect (int x, int y, int nx, int ny) | ||
711 | { | 472 | { |
712 | int i; | 473 | memset(lcd_remote_framebuffer, 0, sizeof lcd_remote_framebuffer); |
713 | for (i = 0; i < nx; i++) | ||
714 | lcd_remote_bitmap (zeros, x+i, y, 1, ny, true); | ||
715 | } | 474 | } |
716 | 475 | ||
717 | /* | 476 | /* Set a single pixel */ |
718 | * Fill a rectangular area at (x, y), size (nx, ny) | 477 | void lcd_remote_drawpixel(int x, int y) |
719 | */ | ||
720 | void lcd_remote_fillrect (int x, int y, int nx, int ny) | ||
721 | { | 478 | { |
722 | int i; | 479 | REMOTE_DRAW_PIXEL(x,y); |
723 | for (i = 0; i < nx; i++) | ||
724 | lcd_remote_bitmap (ones, x+i, y, 1, ny, true); | ||
725 | } | 480 | } |
726 | 481 | ||
727 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | 482 | /* Clear a single pixel */ |
728 | void lcd_remote_invertrect (int x, int y, int nx, int ny) | 483 | void lcd_remote_clearpixel(int x, int y) |
729 | { | 484 | { |
730 | int i, j; | 485 | REMOTE_CLEAR_PIXEL(x,y); |
731 | |||
732 | if (x > LCD_REMOTE_WIDTH) | ||
733 | return; | ||
734 | if (y > LCD_REMOTE_HEIGHT) | ||
735 | return; | ||
736 | |||
737 | if (x + nx > LCD_REMOTE_WIDTH) | ||
738 | nx = LCD_REMOTE_WIDTH - x; | ||
739 | if (y + ny > LCD_REMOTE_HEIGHT) | ||
740 | ny = LCD_REMOTE_HEIGHT - y; | ||
741 | |||
742 | for (i = 0; i < nx; i++) | ||
743 | for (j = 0; j < ny; j++) | ||
744 | REMOTE_INVERT_PIXEL((x + i), (y + j)); | ||
745 | } | 486 | } |
746 | 487 | ||
747 | /* Reverse the invert setting of the scrolling line (if any) at given char | 488 | /* Invert a single pixel */ |
748 | position. Setting will go into affect next time line scrolls. */ | 489 | void lcd_remote_invertpixel(int x, int y) |
749 | void lcd_remote_invertscroll(int x, int y) | ||
750 | { | 490 | { |
751 | struct scrollinfo* s; | 491 | REMOTE_INVERT_PIXEL(x,y); |
752 | |||
753 | (void)x; | ||
754 | |||
755 | s = &scroll[y]; | ||
756 | s->invert = !s->invert; | ||
757 | } | 492 | } |
758 | 493 | ||
759 | void lcd_remote_drawline( int x1, int y1, int x2, int y2 ) | 494 | void lcd_remote_drawline(int x1, int y1, int x2, int y2) |
760 | { | 495 | { |
761 | int numpixels; | 496 | int numpixels; |
762 | int i; | 497 | int i; |
@@ -826,7 +561,7 @@ void lcd_remote_drawline( int x1, int y1, int x2, int y2 ) | |||
826 | } | 561 | } |
827 | } | 562 | } |
828 | 563 | ||
829 | void lcd_remote_clearline( int x1, int y1, int x2, int y2 ) | 564 | void lcd_remote_clearline(int x1, int y1, int x2, int y2) |
830 | { | 565 | { |
831 | int numpixels; | 566 | int numpixels; |
832 | int i; | 567 | int i; |
@@ -896,28 +631,310 @@ void lcd_remote_clearline( int x1, int y1, int x2, int y2 ) | |||
896 | } | 631 | } |
897 | } | 632 | } |
898 | 633 | ||
899 | /* | 634 | void lcd_remote_drawrect(int x, int y, int nx, int ny) |
900 | * Set a single pixel | ||
901 | */ | ||
902 | void lcd_remote_drawpixel(int x, int y) | ||
903 | { | 635 | { |
904 | REMOTE_DRAW_PIXEL(x,y); | 636 | int i; |
637 | |||
638 | if (x > LCD_REMOTE_WIDTH) | ||
639 | { | ||
640 | return; | ||
641 | } | ||
642 | |||
643 | if (y > LCD_REMOTE_HEIGHT) | ||
644 | { | ||
645 | return; | ||
646 | } | ||
647 | |||
648 | if (x + nx > LCD_REMOTE_WIDTH) | ||
649 | { | ||
650 | nx = LCD_REMOTE_WIDTH - x; | ||
651 | } | ||
652 | |||
653 | if (y + ny > LCD_REMOTE_HEIGHT) | ||
654 | { | ||
655 | ny = LCD_REMOTE_HEIGHT - y; | ||
656 | } | ||
657 | |||
658 | /* vertical lines */ | ||
659 | for (i = 0; i < ny; i++) | ||
660 | { | ||
661 | REMOTE_DRAW_PIXEL(x, (y + i)); | ||
662 | REMOTE_DRAW_PIXEL((x + nx - 1), (y + i)); | ||
663 | } | ||
664 | |||
665 | /* horizontal lines */ | ||
666 | for (i = 0; i < nx; i++) | ||
667 | { | ||
668 | REMOTE_DRAW_PIXEL((x + i),y); | ||
669 | REMOTE_DRAW_PIXEL((x + i),(y + ny - 1)); | ||
670 | } | ||
905 | } | 671 | } |
906 | 672 | ||
907 | /* | 673 | /* Clear a rectangular area at (x, y), size (nx, ny) */ |
908 | * Clear a single pixel | 674 | void lcd_remote_clearrect(int x, int y, int nx, int ny) |
909 | */ | ||
910 | void lcd_remote_clearpixel(int x, int y) | ||
911 | { | 675 | { |
912 | REMOTE_CLEAR_PIXEL(x,y); | 676 | int i; |
677 | for (i = 0; i < nx; i++) | ||
678 | lcd_remote_bitmap(zeros, x+i, y, 1, ny, true); | ||
913 | } | 679 | } |
914 | 680 | ||
915 | /* | 681 | /* Fill a rectangular area at (x, y), size (nx, ny) */ |
916 | * Invert a single pixel | 682 | void lcd_remote_fillrect(int x, int y, int nx, int ny) |
917 | */ | ||
918 | void lcd_remote_invertpixel(int x, int y) | ||
919 | { | 683 | { |
920 | REMOTE_INVERT_PIXEL(x,y); | 684 | int i; |
685 | for (i = 0; i < nx; i++) | ||
686 | lcd_remote_bitmap(ones, x+i, y, 1, ny, true); | ||
687 | } | ||
688 | |||
689 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | ||
690 | void lcd_remote_invertrect(int x, int y, int nx, int ny) | ||
691 | { | ||
692 | int i, j; | ||
693 | |||
694 | if (x > LCD_REMOTE_WIDTH) | ||
695 | return; | ||
696 | if (y > LCD_REMOTE_HEIGHT) | ||
697 | return; | ||
698 | |||
699 | if (x + nx > LCD_REMOTE_WIDTH) | ||
700 | nx = LCD_REMOTE_WIDTH - x; | ||
701 | if (y + ny > LCD_REMOTE_HEIGHT) | ||
702 | ny = LCD_REMOTE_HEIGHT - y; | ||
703 | |||
704 | for (i = 0; i < nx; i++) | ||
705 | for (j = 0; j < ny; j++) | ||
706 | REMOTE_INVERT_PIXEL((x + i), (y + j)); | ||
707 | } | ||
708 | |||
709 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | ||
710 | bool clear) __attribute__ ((section (".icode"))); | ||
711 | void lcd_remote_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | ||
712 | bool clear) | ||
713 | { | ||
714 | const unsigned char *src_col; | ||
715 | unsigned char *dst, *dst_col; | ||
716 | unsigned int data, mask1, mask2, mask3, mask4; | ||
717 | int stride, shift; | ||
718 | |||
719 | if (((unsigned) x >= LCD_REMOTE_WIDTH) || ((unsigned) y >= LCD_REMOTE_HEIGHT)) | ||
720 | { | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | stride = nx; /* otherwise right-clipping will destroy the image */ | ||
725 | |||
726 | if (((unsigned) (x + nx)) >= LCD_REMOTE_WIDTH) | ||
727 | { | ||
728 | nx = LCD_REMOTE_WIDTH - x; | ||
729 | } | ||
730 | |||
731 | if (((unsigned) (y + ny)) >= LCD_REMOTE_HEIGHT) | ||
732 | { | ||
733 | ny = LCD_REMOTE_HEIGHT - y; | ||
734 | } | ||
735 | |||
736 | dst = &lcd_remote_framebuffer[y >> 3][x]; | ||
737 | shift = y & 7; | ||
738 | |||
739 | if (!shift && clear) /* shortcut for byte aligned match with clear */ | ||
740 | { | ||
741 | while (ny >= 8) /* all full rows */ | ||
742 | { | ||
743 | memcpy(dst, src, nx); | ||
744 | src += stride; | ||
745 | dst += LCD_REMOTE_WIDTH; | ||
746 | ny -= 8; | ||
747 | } | ||
748 | if (ny == 0) /* nothing left to do? */ | ||
749 | { | ||
750 | return; | ||
751 | } | ||
752 | /* last partial row to do by default routine */ | ||
753 | } | ||
754 | |||
755 | ny += shift; | ||
756 | |||
757 | /* Calculate bit masks */ | ||
758 | mask4 = ~(0xfe << ((ny-1) & 7)); /* data mask for last partial row */ | ||
759 | |||
760 | if (clear) | ||
761 | { | ||
762 | mask1 = ~(0xff << shift); /* clearing of first partial row */ | ||
763 | mask2 = 0; /* clearing of intermediate (full) rows */ | ||
764 | mask3 = ~mask4; /* clearing of last partial row */ | ||
765 | if (ny <= 8) | ||
766 | { | ||
767 | mask3 |= mask1; | ||
768 | } | ||
769 | } | ||
770 | else | ||
771 | { | ||
772 | mask1 = mask2 = mask3 = 0xff; | ||
773 | } | ||
774 | |||
775 | /* Loop for each column */ | ||
776 | for (x = 0; x < nx; x++) | ||
777 | { | ||
778 | src_col = src++; | ||
779 | dst_col = dst++; | ||
780 | data = 0; | ||
781 | y = 0; | ||
782 | |||
783 | if (ny > 8) | ||
784 | { | ||
785 | /* First partial row */ | ||
786 | data = *src_col << shift; | ||
787 | *dst_col = (*dst_col & mask1) | data; | ||
788 | src_col += stride; | ||
789 | dst_col += LCD_REMOTE_WIDTH; | ||
790 | data >>= 8; | ||
791 | |||
792 | /* Intermediate rows */ | ||
793 | for (y = 8; y < ny-8; y += 8) | ||
794 | { | ||
795 | data |= *src_col << shift; | ||
796 | *dst_col = (*dst_col & mask2) | data; | ||
797 | src_col += stride; | ||
798 | dst_col += LCD_REMOTE_WIDTH; | ||
799 | data >>= 8; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | /* Last partial row */ | ||
804 | if (y + shift < ny) | ||
805 | { | ||
806 | data |= *src_col << shift; | ||
807 | } | ||
808 | |||
809 | *dst_col = (*dst_col & mask3) | (data & mask4); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | ||
814 | static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
815 | { | ||
816 | int ch; | ||
817 | struct font* pf = font_get(curfont); | ||
818 | |||
819 | while ((ch = *str++) != '\0' && x < LCD_REMOTE_WIDTH) | ||
820 | { | ||
821 | int gwidth, width; | ||
822 | |||
823 | /* check input range */ | ||
824 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
825 | ch = pf->defaultchar; | ||
826 | ch -= pf->firstchar; | ||
827 | |||
828 | /* get proportional width and glyph bits */ | ||
829 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | ||
830 | width = MIN (gwidth, LCD_REMOTE_WIDTH - x); | ||
831 | |||
832 | if (ofs != 0) | ||
833 | { | ||
834 | if (ofs > width) | ||
835 | { | ||
836 | ofs -= width; | ||
837 | continue; | ||
838 | } | ||
839 | width -= ofs; | ||
840 | } | ||
841 | |||
842 | if (width > 0) | ||
843 | { | ||
844 | unsigned int i; | ||
845 | const unsigned char* bits = pf->bits + | ||
846 | (pf->offset ? pf->offset[ch] | ||
847 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
848 | |||
849 | if (ofs != 0) | ||
850 | { | ||
851 | for (i = 0; i < pf->height; i += 8) | ||
852 | { | ||
853 | lcd_remote_bitmap (bits + ofs, x, y + i, width, | ||
854 | MIN(8, pf->height - i), true); | ||
855 | bits += gwidth; | ||
856 | } | ||
857 | } | ||
858 | else | ||
859 | lcd_remote_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
860 | pf->height, true); | ||
861 | x += width; | ||
862 | } | ||
863 | ofs = 0; | ||
864 | } | ||
865 | } | ||
866 | |||
867 | /* put a string at a given pixel position */ | ||
868 | void lcd_remote_putsxy(int x, int y, const unsigned char *str) | ||
869 | { | ||
870 | lcd_remote_putsxyofs(x, y, 0, str); | ||
871 | } | ||
872 | |||
873 | /*** line oriented text output ***/ | ||
874 | |||
875 | /* put a string at a given char position */ | ||
876 | void lcd_remote_puts(int x, int y, const unsigned char *str) | ||
877 | { | ||
878 | lcd_remote_puts_style(x, y, str, STYLE_DEFAULT); | ||
879 | } | ||
880 | |||
881 | void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style) | ||
882 | { | ||
883 | int xpos,ypos,w,h; | ||
884 | |||
885 | /* make sure scrolling is turned off on the line we are updating */ | ||
886 | //scrolling_lines &= ~(1 << y); | ||
887 | |||
888 | if(!str || !str[0]) | ||
889 | return; | ||
890 | |||
891 | lcd_remote_getstringsize(str, &w, &h); | ||
892 | xpos = xmargin + x*w / strlen(str); | ||
893 | ypos = ymargin + y*h; | ||
894 | lcd_remote_putsxy(xpos, ypos, str); | ||
895 | lcd_remote_clearrect(xpos + w, ypos, LCD_REMOTE_WIDTH - (xpos + w), h); | ||
896 | if (style & STYLE_INVERT) | ||
897 | lcd_remote_invertrect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, h); | ||
898 | |||
899 | } | ||
900 | |||
901 | /*** scrolling ***/ | ||
902 | |||
903 | /* Reverse the invert setting of the scrolling line (if any) at given char | ||
904 | position. Setting will go into affect next time line scrolls. */ | ||
905 | void lcd_remote_invertscroll(int x, int y) | ||
906 | { | ||
907 | struct scrollinfo* s; | ||
908 | |||
909 | (void)x; | ||
910 | |||
911 | s = &scroll[y]; | ||
912 | s->invert = !s->invert; | ||
913 | } | ||
914 | |||
915 | void lcd_remote_stop_scroll(void) | ||
916 | { | ||
917 | scrolling_lines=0; | ||
918 | } | ||
919 | |||
920 | void lcd_remote_scroll_speed(int speed) | ||
921 | { | ||
922 | scroll_ticks = scroll_tick_table[speed]; | ||
923 | } | ||
924 | |||
925 | void lcd_remote_scroll_step(int step) | ||
926 | { | ||
927 | scroll_step = step; | ||
928 | } | ||
929 | |||
930 | void lcd_remote_scroll_delay(int ms) | ||
931 | { | ||
932 | scroll_delay = ms / (HZ / 10); | ||
933 | } | ||
934 | |||
935 | void lcd_remote_bidir_scroll(int percent) | ||
936 | { | ||
937 | bidir_limit = percent; | ||
921 | } | 938 | } |
922 | 939 | ||
923 | void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) | 940 | void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) |
@@ -982,37 +999,6 @@ void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int | |||
982 | scrolling_lines &= ~(1<<y); | 999 | scrolling_lines &= ~(1<<y); |
983 | } | 1000 | } |
984 | 1001 | ||
985 | void lcd_remote_stop_scroll(void) | ||
986 | { | ||
987 | scrolling_lines=0; | ||
988 | } | ||
989 | |||
990 | static const char scroll_tick_table[16] = { | ||
991 | /* Hz values: | ||
992 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
993 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
994 | }; | ||
995 | |||
996 | void lcd_remote_scroll_speed(int speed) | ||
997 | { | ||
998 | scroll_ticks = scroll_tick_table[speed]; | ||
999 | } | ||
1000 | |||
1001 | void lcd_remote_scroll_step(int step) | ||
1002 | { | ||
1003 | scroll_step = step; | ||
1004 | } | ||
1005 | |||
1006 | void lcd_remote_scroll_delay(int ms) | ||
1007 | { | ||
1008 | scroll_delay = ms / (HZ / 10); | ||
1009 | } | ||
1010 | |||
1011 | void lcd_remote_bidir_scroll(int percent) | ||
1012 | { | ||
1013 | bidir_limit = percent; | ||
1014 | } | ||
1015 | |||
1016 | #ifndef SIMULATOR | 1002 | #ifndef SIMULATOR |
1017 | static void scroll_thread(void) | 1003 | static void scroll_thread(void) |
1018 | { | 1004 | { |
diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c index d88070b7eb..af3782c0b3 100644 --- a/firmware/drivers/lcd-h100.c +++ b/firmware/drivers/lcd-h100.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 "cpu.h" | 21 | #include "cpu.h" |
24 | #include "lcd.h" | 22 | #include "lcd.h" |
25 | #include "kernel.h" | 23 | #include "kernel.h" |
@@ -34,56 +32,40 @@ | |||
34 | /*** definitions ***/ | 32 | /*** definitions ***/ |
35 | 33 | ||
36 | /* LCD command codes */ | 34 | /* LCD command codes */ |
37 | #define LCD_CNTL_POWER_CONTROL 0x25 | 35 | #define LCD_CNTL_POWER_CONTROL 0x25 |
38 | #define LCD_CNTL_VOLTAGE_SELECT 0x2b | 36 | #define LCD_CNTL_VOLTAGE_SELECT 0x2b |
39 | #define LCD_CNTL_LINE_INVERT_DRIVE 0x36 | 37 | #define LCD_CNTL_LINE_INVERT_DRIVE 0x36 |
40 | #define LCD_CNTL_GRAY_SCALE_PATTERN 0x39 | 38 | #define LCD_CNTL_GRAY_SCALE_PATTERN 0x39 |
41 | #define LCD_CNTL_TEMP_GRADIENT_SELECT 0x4e | 39 | #define LCD_CNTL_TEMP_GRADIENT_SELECT 0x4e |
42 | #define LCD_CNTL_OSC_FREQUENCY 0x5f | 40 | #define LCD_CNTL_OSC_FREQUENCY 0x5f |
43 | #define LCD_CNTL_ON_OFF 0xae | 41 | #define LCD_CNTL_ON_OFF 0xae |
44 | #define LCD_CNTL_OSC_ON_OFF 0xab | 42 | #define LCD_CNTL_OSC_ON_OFF 0xab |
45 | #define LCD_CNTL_OFF_MODE 0xbe | 43 | #define LCD_CNTL_OFF_MODE 0xbe |
46 | #define LCD_CNTL_REVERSE 0xa6 | 44 | #define LCD_CNTL_REVERSE 0xa6 |
47 | #define LCD_CNTL_ALL_LIGHTING 0xa4 | 45 | #define LCD_CNTL_ALL_LIGHTING 0xa4 |
48 | #define LCD_CNTL_COMMON_OUTPUT_STATUS 0xc4 | 46 | #define LCD_CNTL_COMMON_OUTPUT_STATUS 0xc4 |
49 | #define LCD_CNTL_COLUMN_ADDRESS_DIR 0xa0 | 47 | #define LCD_CNTL_COLUMN_ADDRESS_DIR 0xa0 |
50 | #define LCD_CNTL_NLINE_ON_OFF 0xe4 | 48 | #define LCD_CNTL_NLINE_ON_OFF 0xe4 |
51 | #define LCD_CNTL_DISPLAY_MODE 0x66 | 49 | #define LCD_CNTL_DISPLAY_MODE 0x66 |
52 | #define LCD_CNTL_DUTY_SET 0x6d | 50 | #define LCD_CNTL_DUTY_SET 0x6d |
53 | #define LCD_CNTL_ELECTRONIC_VOLUME 0x81 | 51 | #define LCD_CNTL_ELECTRONIC_VOLUME 0x81 |
54 | #define LCD_CNTL_DATA_INPUT_DIR 0x84 | 52 | #define LCD_CNTL_DATA_INPUT_DIR 0x84 |
55 | #define LCD_CNTL_DISPLAY_START_LINE 0x8a | 53 | #define LCD_CNTL_DISPLAY_START_LINE 0x8a |
56 | 54 | ||
57 | #define LCD_CNTL_PAGE 0xb1 | 55 | #define LCD_CNTL_PAGE 0xb1 |
58 | #define LCD_CNTL_COLUMN 0x13 | 56 | #define LCD_CNTL_COLUMN 0x13 |
59 | #define LCD_CNTL_DATA_WRITE 0x1d | 57 | #define LCD_CNTL_DATA_WRITE 0x1d |
60 | |||
61 | #define SCROLL_SPACING 3 | ||
62 | 58 | ||
63 | #define SCROLLABLE_LINES 26 | 59 | #define SCROLLABLE_LINES 26 |
64 | 60 | ||
65 | struct scrollinfo { | 61 | /*** globals ***/ |
66 | char line[MAX_PATH + LCD_WIDTH/2 + SCROLL_SPACING + 2]; | ||
67 | int len; /* length of line in chars */ | ||
68 | int width; /* length of line in pixels */ | ||
69 | int offset; | ||
70 | int startx; | ||
71 | bool backward; /* scroll presently forward or backward? */ | ||
72 | bool bidir; | ||
73 | bool invert; /* invert the scrolled text */ | ||
74 | long start_tick; | ||
75 | }; | ||
76 | 62 | ||
77 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 63 | unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH] |
64 | #ifndef SIMULATOR | ||
65 | __attribute__ ((section(".idata"))) | ||
66 | #endif | ||
67 | ; | ||
78 | 68 | ||
79 | static void scroll_thread(void); | ||
80 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | ||
81 | static const char scroll_name[] = "scroll"; | ||
82 | static char scroll_ticks = 12; /* # of ticks between updates*/ | ||
83 | static int scroll_delay = HZ/2; /* ticks delay before start */ | ||
84 | static char scroll_step = 6; /* pixels per scroll step */ | ||
85 | static int bidir_limit = 50; /* percent */ | ||
86 | static struct scrollinfo scroll[SCROLLABLE_LINES]; | ||
87 | static int xmargin = 0; | 69 | static int xmargin = 0; |
88 | static int ymargin = 0; | 70 | static int ymargin = 0; |
89 | static int curfont = FONT_SYSFIXED; | 71 | static int curfont = FONT_SYSFIXED; |
@@ -91,14 +73,8 @@ static int curfont = FONT_SYSFIXED; | |||
91 | static int xoffset = 0; /* needed for flip */ | 73 | static int xoffset = 0; /* needed for flip */ |
92 | #endif | 74 | #endif |
93 | 75 | ||
94 | unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH] | 76 | /* All zeros and ones bitmaps for area filling */ |
95 | #ifndef SIMULATOR | 77 | static const unsigned char zeros[16] = { |
96 | __attribute__ ((section(".idata"))) | ||
97 | #endif | ||
98 | ; | ||
99 | |||
100 | /* All zeros and ones bitmaps for area filling */ | ||
101 | static const unsigned char zeros[16] = { | ||
102 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 78 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
103 | }; | 79 | }; |
104 | static const unsigned char ones[16] = { | 80 | static const unsigned char ones[16] = { |
@@ -106,11 +82,85 @@ static const unsigned char ones[16] = { | |||
106 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 82 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
107 | }; | 83 | }; |
108 | 84 | ||
85 | /* scrolling */ | ||
86 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | ||
87 | static void scroll_thread(void); | ||
88 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | ||
89 | static const char scroll_name[] = "scroll"; | ||
90 | static char scroll_ticks = 12; /* # of ticks between updates*/ | ||
91 | static int scroll_delay = HZ/2; /* ticks delay before start */ | ||
92 | static char scroll_step = 6; /* pixels per scroll step */ | ||
93 | static int bidir_limit = 50; /* percent */ | ||
94 | static struct scrollinfo scroll[SCROLLABLE_LINES]; | ||
95 | |||
96 | static const char scroll_tick_table[16] = { | ||
97 | /* Hz values: | ||
98 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
99 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
100 | }; | ||
101 | |||
102 | /*** driver code is in lcd.S ***/ | ||
103 | |||
104 | /*** hardware configuration ***/ | ||
105 | |||
109 | int lcd_default_contrast(void) | 106 | int lcd_default_contrast(void) |
110 | { | 107 | { |
111 | return 28; | 108 | return 28; |
112 | } | 109 | } |
113 | 110 | ||
111 | #ifndef SIMULATOR | ||
112 | |||
113 | void lcd_set_contrast(int val) | ||
114 | { | ||
115 | lcd_write_command_ex(LCD_CNTL_ELECTRONIC_VOLUME, val, -1); | ||
116 | } | ||
117 | |||
118 | void lcd_set_invert_display(bool yesno) | ||
119 | { | ||
120 | lcd_write_command(LCD_CNTL_REVERSE | (yesno?1:0)); | ||
121 | } | ||
122 | |||
123 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
124 | void lcd_set_flip(bool yesno) | ||
125 | { | ||
126 | if (yesno) | ||
127 | { | ||
128 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 1); | ||
129 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 0); | ||
130 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 0); | ||
131 | xoffset = 160 - LCD_WIDTH; /* 160 colums minus the 160 we have */ | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); | ||
136 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); | ||
137 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); | ||
138 | xoffset = 0; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* Rolls up the lcd display by the specified amount of lines. | ||
143 | * Lines that are rolled out over the top of the screen are | ||
144 | * rolled in from the bottom again. This is a hardware | ||
145 | * remapping only and all operations on the lcd are affected. | ||
146 | * -> | ||
147 | * @param int lines - The number of lines that are rolled. | ||
148 | * The value must be 0 <= pixels < LCD_HEIGHT. */ | ||
149 | void lcd_roll(int lines) | ||
150 | { | ||
151 | char data[2]; | ||
152 | |||
153 | lines &= LCD_HEIGHT-1; | ||
154 | data[0] = lines & 0xff; | ||
155 | data[1] = lines >> 8; | ||
156 | |||
157 | lcd_write_command(LCD_CNTL_DISPLAY_START_LINE); | ||
158 | lcd_write_data(data, 2); | ||
159 | } | ||
160 | |||
161 | #endif /* !SIMULATOR */ | ||
162 | |||
163 | /* LCD init */ | ||
114 | #ifdef SIMULATOR | 164 | #ifdef SIMULATOR |
115 | 165 | ||
116 | void lcd_init(void) | 166 | void lcd_init(void) |
@@ -118,13 +168,9 @@ void lcd_init(void) | |||
118 | create_thread(scroll_thread, scroll_stack, | 168 | create_thread(scroll_thread, scroll_stack, |
119 | sizeof(scroll_stack), scroll_name); | 169 | sizeof(scroll_stack), scroll_name); |
120 | } | 170 | } |
121 | |||
122 | #else | 171 | #else |
123 | 172 | ||
124 | /* | 173 | void lcd_init(void) |
125 | * Initialize LCD | ||
126 | */ | ||
127 | void lcd_init (void) | ||
128 | { | 174 | { |
129 | /* GPO35 is the LCD A0 pin | 175 | /* GPO35 is the LCD A0 pin |
130 | GPO46 is LCD RESET */ | 176 | GPO46 is LCD RESET */ |
@@ -170,11 +216,12 @@ void lcd_init (void) | |||
170 | sizeof(scroll_stack), scroll_name); | 216 | sizeof(scroll_stack), scroll_name); |
171 | } | 217 | } |
172 | 218 | ||
219 | /*** update functions ***/ | ||
173 | 220 | ||
174 | /* Performance function that works with an external buffer | 221 | /* Performance function that works with an external buffer |
175 | note that y and height are in 8-pixel units! */ | 222 | note that y and height are in 8-pixel units! */ |
176 | void lcd_blit (const unsigned char* p_data, int x, int y, int width, | 223 | void lcd_blit(const unsigned char* p_data, int x, int y, int width, |
177 | int height, int stride) | 224 | int height, int stride) |
178 | { | 225 | { |
179 | /* Copy display bitmap to hardware */ | 226 | /* Copy display bitmap to hardware */ |
180 | while (height--) | 227 | while (height--) |
@@ -189,12 +236,10 @@ void lcd_blit (const unsigned char* p_data, int x, int y, int width, | |||
189 | } | 236 | } |
190 | 237 | ||
191 | 238 | ||
192 | /* | 239 | /* Update the display. |
193 | * Update the display. | 240 | This must be called after all other LCD functions that change the display. */ |
194 | * This must be called after all other LCD functions that change the display. | 241 | void lcd_update(void) __attribute__ ((section (".icode"))); |
195 | */ | 242 | void lcd_update(void) |
196 | void lcd_update (void) __attribute__ ((section (".icode"))); | ||
197 | void lcd_update (void) | ||
198 | { | 243 | { |
199 | int y; | 244 | int y; |
200 | 245 | ||
@@ -209,12 +254,9 @@ void lcd_update (void) | |||
209 | } | 254 | } |
210 | } | 255 | } |
211 | 256 | ||
212 | /* | 257 | /* Update a fraction of the display. */ |
213 | * Update a fraction of the display. | 258 | void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); |
214 | */ | 259 | void lcd_update_rect(int x_start, int y, int width, int height) |
215 | void lcd_update_rect (int, int, int, int) __attribute__ ((section (".icode"))); | ||
216 | void lcd_update_rect (int x_start, int y, | ||
217 | int width, int height) | ||
218 | { | 260 | { |
219 | int ymax; | 261 | int ymax; |
220 | 262 | ||
@@ -239,64 +281,9 @@ void lcd_update_rect (int x_start, int y, | |||
239 | lcd_write_data (&lcd_framebuffer[y][x_start], width); | 281 | lcd_write_data (&lcd_framebuffer[y][x_start], width); |
240 | } | 282 | } |
241 | } | 283 | } |
284 | #endif /* !SIMULATOR */ | ||
242 | 285 | ||
243 | void lcd_set_contrast(int val) | 286 | /*** parameter handling ***/ |
244 | { | ||
245 | lcd_write_command_ex(LCD_CNTL_ELECTRONIC_VOLUME, val, -1); | ||
246 | } | ||
247 | |||
248 | void lcd_set_invert_display(bool yesno) | ||
249 | { | ||
250 | lcd_write_command(LCD_CNTL_REVERSE | (yesno?1:0)); | ||
251 | } | ||
252 | |||
253 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
254 | void lcd_set_flip(bool yesno) | ||
255 | { | ||
256 | if (yesno) | ||
257 | { | ||
258 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 1); | ||
259 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 0); | ||
260 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 0); | ||
261 | xoffset = 160 - LCD_WIDTH; /* 160 colums minus the 160 we have */ | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); | ||
266 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); | ||
267 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); | ||
268 | xoffset = 0; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * Rolls up the lcd display by the specified amount of lines. | ||
274 | * Lines that are rolled out over the top of the screen are | ||
275 | * rolled in from the bottom again. This is a hardware | ||
276 | * remapping only and all operations on the lcd are affected. | ||
277 | * -> | ||
278 | * @param int lines - The number of lines that are rolled. | ||
279 | * The value must be 0 <= pixels < LCD_HEIGHT. | ||
280 | */ | ||
281 | void lcd_roll(int lines) | ||
282 | { | ||
283 | char data[2]; | ||
284 | |||
285 | lines &= LCD_HEIGHT-1; | ||
286 | data[0] = lines & 0xff; | ||
287 | data[1] = lines >> 8; | ||
288 | |||
289 | lcd_write_command(LCD_CNTL_DISPLAY_START_LINE); | ||
290 | lcd_write_data(data, 2); | ||
291 | } | ||
292 | |||
293 | #endif /* SIMULATOR */ | ||
294 | |||
295 | void lcd_clear_display (void) | ||
296 | { | ||
297 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | ||
298 | scrolling_lines = 0; | ||
299 | } | ||
300 | 287 | ||
301 | void lcd_setmargins(int x, int y) | 288 | void lcd_setmargins(int x, int y) |
302 | { | 289 | { |
@@ -324,111 +311,237 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
324 | return font_getstringsize(str, w, h, curfont); | 311 | return font_getstringsize(str, w, h, curfont); |
325 | } | 312 | } |
326 | 313 | ||
327 | /* put a string at a given char position */ | 314 | /*** drawing functions ***/ |
328 | void lcd_puts(int x, int y, const unsigned char *str) | 315 | |
316 | void lcd_clear_display(void) | ||
329 | { | 317 | { |
330 | lcd_puts_style(x, y, str, STYLE_DEFAULT); | 318 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); |
319 | scrolling_lines = 0; | ||
331 | } | 320 | } |
332 | 321 | ||
333 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | 322 | /* Set a single pixel */ |
323 | void lcd_drawpixel(int x, int y) | ||
334 | { | 324 | { |
335 | int xpos,ypos,w,h; | 325 | DRAW_PIXEL(x,y); |
326 | } | ||
336 | 327 | ||
337 | #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS) | 328 | /* Clear a single pixel */ |
338 | /* We make the simulator truncate the string if it reaches the right edge, | 329 | void lcd_clearpixel(int x, int y) |
339 | as otherwise it'll wrap. The real target doesn't wrap. */ | 330 | { |
331 | CLEAR_PIXEL(x,y); | ||
332 | } | ||
333 | |||
334 | /* Invert a single pixel */ | ||
335 | void lcd_invertpixel(int x, int y) | ||
336 | { | ||
337 | INVERT_PIXEL(x,y); | ||
338 | } | ||
339 | |||
340 | void lcd_drawline(int x1, int y1, int x2, int y2) | ||
341 | { | ||
342 | int numpixels; | ||
343 | int i; | ||
344 | int deltax, deltay; | ||
345 | int d, dinc1, dinc2; | ||
346 | int x, xinc1, xinc2; | ||
347 | int y, yinc1, yinc2; | ||
340 | 348 | ||
341 | char buffer[12]; | 349 | deltax = abs(x2 - x1); |
342 | if(strlen(str)+x > 11 ) { | 350 | deltay = abs(y2 - y1); |
343 | strncpy(buffer, str, sizeof buffer); | 351 | |
344 | buffer[11-x]=0; | 352 | if(deltax >= deltay) |
345 | str = buffer; | 353 | { |
354 | numpixels = deltax; | ||
355 | d = 2 * deltay - deltax; | ||
356 | dinc1 = deltay * 2; | ||
357 | dinc2 = (deltay - deltax) * 2; | ||
358 | xinc1 = 1; | ||
359 | xinc2 = 1; | ||
360 | yinc1 = 0; | ||
361 | yinc2 = 1; | ||
346 | } | 362 | } |
347 | xmargin = 0; | 363 | else |
348 | ymargin = 8; | 364 | { |
349 | #endif | 365 | numpixels = deltay; |
366 | d = 2 * deltax - deltay; | ||
367 | dinc1 = deltax * 2; | ||
368 | dinc2 = (deltax - deltay) * 2; | ||
369 | xinc1 = 0; | ||
370 | xinc2 = 1; | ||
371 | yinc1 = 1; | ||
372 | yinc2 = 1; | ||
373 | } | ||
374 | numpixels++; /* include endpoints */ | ||
350 | 375 | ||
351 | /* make sure scrolling is turned off on the line we are updating */ | 376 | if(x1 > x2) |
352 | scrolling_lines &= ~(1 << y); | 377 | { |
378 | xinc1 = -xinc1; | ||
379 | xinc2 = -xinc2; | ||
380 | } | ||
353 | 381 | ||
354 | if(!str || !str[0]) | 382 | if(y1 > y2) |
355 | return; | 383 | { |
384 | yinc1 = -yinc1; | ||
385 | yinc2 = -yinc2; | ||
386 | } | ||
356 | 387 | ||
357 | lcd_getstringsize(str, &w, &h); | 388 | x = x1; |
358 | xpos = xmargin + x*w / strlen(str); | 389 | y = y1; |
359 | ypos = ymargin + y*h; | ||
360 | lcd_putsxy(xpos, ypos, str); | ||
361 | lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | ||
362 | if (style & STYLE_INVERT) | ||
363 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, h); | ||
364 | 390 | ||
365 | #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS) | 391 | for(i=0; i<numpixels; i++) |
366 | lcd_update(); | 392 | { |
367 | #endif | 393 | DRAW_PIXEL(x,y); |
394 | |||
395 | if(d < 0) | ||
396 | { | ||
397 | d += dinc1; | ||
398 | x += xinc1; | ||
399 | y += yinc1; | ||
400 | } | ||
401 | else | ||
402 | { | ||
403 | d += dinc2; | ||
404 | x += xinc2; | ||
405 | y += yinc2; | ||
406 | } | ||
407 | } | ||
368 | } | 408 | } |
369 | 409 | ||
370 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 410 | void lcd_clearline(int x1, int y1, int x2, int y2) |
371 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
372 | { | 411 | { |
373 | int ch; | 412 | int numpixels; |
374 | struct font* pf = font_get(curfont); | 413 | int i; |
414 | int deltax, deltay; | ||
415 | int d, dinc1, dinc2; | ||
416 | int x, xinc1, xinc2; | ||
417 | int y, yinc1, yinc2; | ||
375 | 418 | ||
376 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) | 419 | deltax = abs(x2 - x1); |
420 | deltay = abs(y2 - y1); | ||
421 | |||
422 | if(deltax >= deltay) | ||
377 | { | 423 | { |
378 | int gwidth, width; | 424 | numpixels = deltax; |
425 | d = 2 * deltay - deltax; | ||
426 | dinc1 = deltay * 2; | ||
427 | dinc2 = (deltay - deltax) * 2; | ||
428 | xinc1 = 1; | ||
429 | xinc2 = 1; | ||
430 | yinc1 = 0; | ||
431 | yinc2 = 1; | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | numpixels = deltay; | ||
436 | d = 2 * deltax - deltay; | ||
437 | dinc1 = deltax * 2; | ||
438 | dinc2 = (deltax - deltay) * 2; | ||
439 | xinc1 = 0; | ||
440 | xinc2 = 1; | ||
441 | yinc1 = 1; | ||
442 | yinc2 = 1; | ||
443 | } | ||
444 | numpixels++; /* include endpoints */ | ||
379 | 445 | ||
380 | /* check input range */ | 446 | if(x1 > x2) |
381 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | 447 | { |
382 | ch = pf->defaultchar; | 448 | xinc1 = -xinc1; |
383 | ch -= pf->firstchar; | 449 | xinc2 = -xinc2; |
450 | } | ||
384 | 451 | ||
385 | /* get proportional width and glyph bits */ | 452 | if(y1 > y2) |
386 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | 453 | { |
387 | width = MIN (gwidth, LCD_WIDTH - x); | 454 | yinc1 = -yinc1; |
455 | yinc2 = -yinc2; | ||
456 | } | ||
388 | 457 | ||
389 | if (ofs != 0) | 458 | x = x1; |
459 | y = y1; | ||
460 | |||
461 | for(i=0; i<numpixels; i++) | ||
462 | { | ||
463 | CLEAR_PIXEL(x,y); | ||
464 | |||
465 | if(d < 0) | ||
390 | { | 466 | { |
391 | if (ofs > width) | 467 | d += dinc1; |
392 | { | 468 | x += xinc1; |
393 | ofs -= width; | 469 | y += yinc1; |
394 | continue; | ||
395 | } | ||
396 | width -= ofs; | ||
397 | } | 470 | } |
398 | 471 | else | |
399 | if (width > 0) | ||
400 | { | 472 | { |
401 | unsigned int i; | 473 | d += dinc2; |
402 | const unsigned char* bits = pf->bits + | 474 | x += xinc2; |
403 | (pf->offset ? pf->offset[ch] | 475 | y += yinc2; |
404 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
405 | |||
406 | if (ofs != 0) | ||
407 | { | ||
408 | for (i = 0; i < pf->height; i += 8) | ||
409 | { | ||
410 | lcd_bitmap (bits + ofs, x, y + i, width, | ||
411 | MIN(8, pf->height - i), true); | ||
412 | bits += gwidth; | ||
413 | } | ||
414 | } | ||
415 | else | ||
416 | lcd_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
417 | pf->height, true); | ||
418 | x += width; | ||
419 | } | 476 | } |
420 | ofs = 0; | ||
421 | } | 477 | } |
422 | } | 478 | } |
423 | 479 | ||
424 | /* put a string at a given pixel position */ | 480 | /* Draw a rectangle with upper left corner at (x, y) and size (nx, ny) */ |
425 | void lcd_putsxy(int x, int y, const unsigned char *str) | 481 | void lcd_drawrect(int x, int y, int nx, int ny) |
426 | { | 482 | { |
427 | lcd_putsxyofs(x, y, 0, str); | 483 | int i; |
484 | |||
485 | if (x > LCD_WIDTH) | ||
486 | return; | ||
487 | if (y > LCD_HEIGHT) | ||
488 | return; | ||
489 | |||
490 | if (x + nx > LCD_WIDTH) | ||
491 | nx = LCD_WIDTH - x; | ||
492 | if (y + ny > LCD_HEIGHT) | ||
493 | ny = LCD_HEIGHT - y; | ||
494 | |||
495 | /* vertical lines */ | ||
496 | for (i = 0; i < ny; i++) { | ||
497 | DRAW_PIXEL(x, (y + i)); | ||
498 | DRAW_PIXEL((x + nx - 1), (y + i)); | ||
499 | } | ||
500 | |||
501 | /* horizontal lines */ | ||
502 | for (i = 0; i < nx; i++) { | ||
503 | DRAW_PIXEL((x + i),y); | ||
504 | DRAW_PIXEL((x + i),(y + ny - 1)); | ||
505 | } | ||
428 | } | 506 | } |
429 | 507 | ||
430 | /* | 508 | /* Clear a rectangular area at (x, y), size (nx, ny) */ |
431 | * About Rockbox' internal bitmap format: | 509 | void lcd_clearrect(int x, int y, int nx, int ny) |
510 | { | ||
511 | int i; | ||
512 | for (i = 0; i < nx; i++) | ||
513 | lcd_bitmap (zeros, x+i, y, 1, ny, true); | ||
514 | } | ||
515 | |||
516 | /* Fill a rectangular area at (x, y), size (nx, ny) */ | ||
517 | void lcd_fillrect(int x, int y, int nx, int ny) | ||
518 | { | ||
519 | int i; | ||
520 | for (i = 0; i < nx; i++) | ||
521 | lcd_bitmap (ones, x+i, y, 1, ny, true); | ||
522 | } | ||
523 | |||
524 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | ||
525 | void lcd_invertrect(int x, int y, int nx, int ny) | ||
526 | { | ||
527 | int i, j; | ||
528 | |||
529 | if (x > LCD_WIDTH) | ||
530 | return; | ||
531 | if (y > LCD_HEIGHT) | ||
532 | return; | ||
533 | |||
534 | if (x + nx > LCD_WIDTH) | ||
535 | nx = LCD_WIDTH - x; | ||
536 | if (y + ny > LCD_HEIGHT) | ||
537 | ny = LCD_HEIGHT - y; | ||
538 | |||
539 | for (i = 0; i < nx; i++) | ||
540 | for (j = 0; j < ny; j++) | ||
541 | INVERT_PIXEL((x + i), (y + j)); | ||
542 | } | ||
543 | |||
544 | /* About Rockbox' internal bitmap format: | ||
432 | * | 545 | * |
433 | * A bitmap contains one bit for every pixel that defines if that pixel is | 546 | * A bitmap contains one bit for every pixel that defines if that pixel is |
434 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB | 547 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB |
@@ -437,17 +550,14 @@ void lcd_putsxy(int x, int y, const unsigned char *str) | |||
437 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | 550 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows |
438 | * 0..7, the second row defines pixel row 8..15 etc. | 551 | * 0..7, the second row defines pixel row 8..15 etc. |
439 | * | 552 | * |
440 | * This is the same as the internal lcd hw format. | 553 | * This is the same as the internal lcd hw format. */ |
441 | */ | 554 | |
442 | 555 | /* Draw a bitmap at (x, y), size (nx, ny) | |
443 | /* | 556 | if 'clear' is true, clear destination area first */ |
444 | * Draw a bitmap at (x, y), size (nx, ny) | 557 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, |
445 | * if 'clear' is true, clear destination area first | 558 | bool clear) __attribute__ ((section (".icode"))); |
446 | */ | 559 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, |
447 | void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | 560 | bool clear) |
448 | bool clear) __attribute__ ((section (".icode"))); | ||
449 | void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | ||
450 | bool clear) | ||
451 | { | 561 | { |
452 | const unsigned char *src_col; | 562 | const unsigned char *src_col; |
453 | unsigned char *dst, *dst_col; | 563 | unsigned char *dst, *dst_col; |
@@ -531,77 +641,95 @@ void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | |||
531 | } | 641 | } |
532 | } | 642 | } |
533 | 643 | ||
534 | /* | 644 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
535 | * Draw a rectangle with upper left corner at (x, y) | 645 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) |
536 | * and size (nx, ny) | ||
537 | */ | ||
538 | void lcd_drawrect (int x, int y, int nx, int ny) | ||
539 | { | 646 | { |
540 | int i; | 647 | int ch; |
648 | struct font* pf = font_get(curfont); | ||
541 | 649 | ||
542 | if (x > LCD_WIDTH) | 650 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) |
543 | return; | 651 | { |
544 | if (y > LCD_HEIGHT) | 652 | int gwidth, width; |
545 | return; | ||
546 | 653 | ||
547 | if (x + nx > LCD_WIDTH) | 654 | /* check input range */ |
548 | nx = LCD_WIDTH - x; | 655 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) |
549 | if (y + ny > LCD_HEIGHT) | 656 | ch = pf->defaultchar; |
550 | ny = LCD_HEIGHT - y; | 657 | ch -= pf->firstchar; |
551 | 658 | ||
552 | /* vertical lines */ | 659 | /* get proportional width and glyph bits */ |
553 | for (i = 0; i < ny; i++) { | 660 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; |
554 | DRAW_PIXEL(x, (y + i)); | 661 | width = MIN (gwidth, LCD_WIDTH - x); |
555 | DRAW_PIXEL((x + nx - 1), (y + i)); | ||
556 | } | ||
557 | 662 | ||
558 | /* horizontal lines */ | 663 | if (ofs != 0) |
559 | for (i = 0; i < nx; i++) { | 664 | { |
560 | DRAW_PIXEL((x + i),y); | 665 | if (ofs > width) |
561 | DRAW_PIXEL((x + i),(y + ny - 1)); | 666 | { |
667 | ofs -= width; | ||
668 | continue; | ||
669 | } | ||
670 | width -= ofs; | ||
671 | } | ||
672 | |||
673 | if (width > 0) | ||
674 | { | ||
675 | unsigned int i; | ||
676 | const unsigned char* bits = pf->bits + | ||
677 | (pf->offset ? pf->offset[ch] | ||
678 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
679 | |||
680 | if (ofs != 0) | ||
681 | { | ||
682 | for (i = 0; i < pf->height; i += 8) | ||
683 | { | ||
684 | lcd_bitmap (bits + ofs, x, y + i, width, | ||
685 | MIN(8, pf->height - i), true); | ||
686 | bits += gwidth; | ||
687 | } | ||
688 | } | ||
689 | else | ||
690 | lcd_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
691 | pf->height, true); | ||
692 | x += width; | ||
693 | } | ||
694 | ofs = 0; | ||
562 | } | 695 | } |
563 | } | 696 | } |
564 | 697 | ||
565 | /* | 698 | /* put a string at a given pixel position */ |
566 | * Clear a rectangular area at (x, y), size (nx, ny) | 699 | void lcd_putsxy(int x, int y, const unsigned char *str) |
567 | */ | ||
568 | void lcd_clearrect (int x, int y, int nx, int ny) | ||
569 | { | 700 | { |
570 | int i; | 701 | lcd_putsxyofs(x, y, 0, str); |
571 | for (i = 0; i < nx; i++) | ||
572 | lcd_bitmap (zeros, x+i, y, 1, ny, true); | ||
573 | } | 702 | } |
574 | 703 | ||
575 | /* | 704 | /*** line oriented text output ***/ |
576 | * Fill a rectangular area at (x, y), size (nx, ny) | ||
577 | */ | ||
578 | void lcd_fillrect (int x, int y, int nx, int ny) | ||
579 | { | ||
580 | int i; | ||
581 | for (i = 0; i < nx; i++) | ||
582 | lcd_bitmap (ones, x+i, y, 1, ny, true); | ||
583 | } | ||
584 | 705 | ||
585 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | 706 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) |
586 | void lcd_invertrect (int x, int y, int nx, int ny) | ||
587 | { | 707 | { |
588 | int i, j; | 708 | int xpos,ypos,w,h; |
589 | 709 | ||
590 | if (x > LCD_WIDTH) | 710 | /* make sure scrolling is turned off on the line we are updating */ |
591 | return; | 711 | scrolling_lines &= ~(1 << y); |
592 | if (y > LCD_HEIGHT) | 712 | |
713 | if(!str || !str[0]) | ||
593 | return; | 714 | return; |
594 | 715 | ||
595 | if (x + nx > LCD_WIDTH) | 716 | lcd_getstringsize(str, &w, &h); |
596 | nx = LCD_WIDTH - x; | 717 | xpos = xmargin + x*w / strlen(str); |
597 | if (y + ny > LCD_HEIGHT) | 718 | ypos = ymargin + y*h; |
598 | ny = LCD_HEIGHT - y; | 719 | lcd_putsxy(xpos, ypos, str); |
720 | lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | ||
721 | if (style & STYLE_INVERT) | ||
722 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, h); | ||
723 | } | ||
599 | 724 | ||
600 | for (i = 0; i < nx; i++) | 725 | /* put a string at a given char position */ |
601 | for (j = 0; j < ny; j++) | 726 | void lcd_puts(int x, int y, const unsigned char *str) |
602 | INVERT_PIXEL((x + i), (y + j)); | 727 | { |
728 | lcd_puts_style(x, y, str, STYLE_DEFAULT); | ||
603 | } | 729 | } |
604 | 730 | ||
731 | /*** scrolling ***/ | ||
732 | |||
605 | /* Reverse the invert setting of the scrolling line (if any) at given char | 733 | /* Reverse the invert setting of the scrolling line (if any) at given char |
606 | position. Setting will go into affect next time line scrolls. */ | 734 | position. Setting will go into affect next time line scrolls. */ |
607 | void lcd_invertscroll(int x, int y) | 735 | void lcd_invertscroll(int x, int y) |
@@ -614,168 +742,29 @@ void lcd_invertscroll(int x, int y) | |||
614 | s->invert = !s->invert; | 742 | s->invert = !s->invert; |
615 | } | 743 | } |
616 | 744 | ||
617 | void lcd_drawline( int x1, int y1, int x2, int y2 ) | 745 | void lcd_stop_scroll(void) |
618 | { | 746 | { |
619 | int numpixels; | 747 | scrolling_lines=0; |
620 | int i; | ||
621 | int deltax, deltay; | ||
622 | int d, dinc1, dinc2; | ||
623 | int x, xinc1, xinc2; | ||
624 | int y, yinc1, yinc2; | ||
625 | |||
626 | deltax = abs(x2 - x1); | ||
627 | deltay = abs(y2 - y1); | ||
628 | |||
629 | if(deltax >= deltay) | ||
630 | { | ||
631 | numpixels = deltax; | ||
632 | d = 2 * deltay - deltax; | ||
633 | dinc1 = deltay * 2; | ||
634 | dinc2 = (deltay - deltax) * 2; | ||
635 | xinc1 = 1; | ||
636 | xinc2 = 1; | ||
637 | yinc1 = 0; | ||
638 | yinc2 = 1; | ||
639 | } | ||
640 | else | ||
641 | { | ||
642 | numpixels = deltay; | ||
643 | d = 2 * deltax - deltay; | ||
644 | dinc1 = deltax * 2; | ||
645 | dinc2 = (deltax - deltay) * 2; | ||
646 | xinc1 = 0; | ||
647 | xinc2 = 1; | ||
648 | yinc1 = 1; | ||
649 | yinc2 = 1; | ||
650 | } | ||
651 | numpixels++; /* include endpoints */ | ||
652 | |||
653 | if(x1 > x2) | ||
654 | { | ||
655 | xinc1 = -xinc1; | ||
656 | xinc2 = -xinc2; | ||
657 | } | ||
658 | |||
659 | if(y1 > y2) | ||
660 | { | ||
661 | yinc1 = -yinc1; | ||
662 | yinc2 = -yinc2; | ||
663 | } | ||
664 | |||
665 | x = x1; | ||
666 | y = y1; | ||
667 | |||
668 | for(i=0; i<numpixels; i++) | ||
669 | { | ||
670 | DRAW_PIXEL(x,y); | ||
671 | |||
672 | if(d < 0) | ||
673 | { | ||
674 | d += dinc1; | ||
675 | x += xinc1; | ||
676 | y += yinc1; | ||
677 | } | ||
678 | else | ||
679 | { | ||
680 | d += dinc2; | ||
681 | x += xinc2; | ||
682 | y += yinc2; | ||
683 | } | ||
684 | } | ||
685 | } | 748 | } |
686 | 749 | ||
687 | void lcd_clearline( int x1, int y1, int x2, int y2 ) | 750 | void lcd_scroll_speed(int speed) |
688 | { | 751 | { |
689 | int numpixels; | 752 | scroll_ticks = scroll_tick_table[speed]; |
690 | int i; | ||
691 | int deltax, deltay; | ||
692 | int d, dinc1, dinc2; | ||
693 | int x, xinc1, xinc2; | ||
694 | int y, yinc1, yinc2; | ||
695 | |||
696 | deltax = abs(x2 - x1); | ||
697 | deltay = abs(y2 - y1); | ||
698 | |||
699 | if(deltax >= deltay) | ||
700 | { | ||
701 | numpixels = deltax; | ||
702 | d = 2 * deltay - deltax; | ||
703 | dinc1 = deltay * 2; | ||
704 | dinc2 = (deltay - deltax) * 2; | ||
705 | xinc1 = 1; | ||
706 | xinc2 = 1; | ||
707 | yinc1 = 0; | ||
708 | yinc2 = 1; | ||
709 | } | ||
710 | else | ||
711 | { | ||
712 | numpixels = deltay; | ||
713 | d = 2 * deltax - deltay; | ||
714 | dinc1 = deltax * 2; | ||
715 | dinc2 = (deltax - deltay) * 2; | ||
716 | xinc1 = 0; | ||
717 | xinc2 = 1; | ||
718 | yinc1 = 1; | ||
719 | yinc2 = 1; | ||
720 | } | ||
721 | numpixels++; /* include endpoints */ | ||
722 | |||
723 | if(x1 > x2) | ||
724 | { | ||
725 | xinc1 = -xinc1; | ||
726 | xinc2 = -xinc2; | ||
727 | } | ||
728 | |||
729 | if(y1 > y2) | ||
730 | { | ||
731 | yinc1 = -yinc1; | ||
732 | yinc2 = -yinc2; | ||
733 | } | ||
734 | |||
735 | x = x1; | ||
736 | y = y1; | ||
737 | |||
738 | for(i=0; i<numpixels; i++) | ||
739 | { | ||
740 | CLEAR_PIXEL(x,y); | ||
741 | |||
742 | if(d < 0) | ||
743 | { | ||
744 | d += dinc1; | ||
745 | x += xinc1; | ||
746 | y += yinc1; | ||
747 | } | ||
748 | else | ||
749 | { | ||
750 | d += dinc2; | ||
751 | x += xinc2; | ||
752 | y += yinc2; | ||
753 | } | ||
754 | } | ||
755 | } | 753 | } |
756 | 754 | ||
757 | /* | 755 | void lcd_scroll_step(int step) |
758 | * Set a single pixel | ||
759 | */ | ||
760 | void lcd_drawpixel(int x, int y) | ||
761 | { | 756 | { |
762 | DRAW_PIXEL(x,y); | 757 | scroll_step = step; |
763 | } | 758 | } |
764 | 759 | ||
765 | /* | 760 | void lcd_scroll_delay(int ms) |
766 | * Clear a single pixel | ||
767 | */ | ||
768 | void lcd_clearpixel(int x, int y) | ||
769 | { | 761 | { |
770 | CLEAR_PIXEL(x,y); | 762 | scroll_delay = ms / (HZ / 10); |
771 | } | 763 | } |
772 | 764 | ||
773 | /* | 765 | void lcd_bidir_scroll(int percent) |
774 | * Invert a single pixel | ||
775 | */ | ||
776 | void lcd_invertpixel(int x, int y) | ||
777 | { | 766 | { |
778 | INVERT_PIXEL(x,y); | 767 | bidir_limit = percent; |
779 | } | 768 | } |
780 | 769 | ||
781 | void lcd_puts_scroll(int x, int y, const unsigned char *string) | 770 | void lcd_puts_scroll(int x, int y, const unsigned char *string) |
@@ -840,36 +829,6 @@ void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) | |||
840 | scrolling_lines &= ~(1<<y); | 829 | scrolling_lines &= ~(1<<y); |
841 | } | 830 | } |
842 | 831 | ||
843 | void lcd_stop_scroll(void) | ||
844 | { | ||
845 | scrolling_lines=0; | ||
846 | } | ||
847 | |||
848 | static const char scroll_tick_table[16] = { | ||
849 | /* Hz values: | ||
850 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
851 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
852 | }; | ||
853 | |||
854 | void lcd_scroll_speed(int speed) | ||
855 | { | ||
856 | scroll_ticks = scroll_tick_table[speed]; | ||
857 | } | ||
858 | |||
859 | void lcd_scroll_step(int step) | ||
860 | { | ||
861 | scroll_step = step; | ||
862 | } | ||
863 | |||
864 | void lcd_scroll_delay(int ms) | ||
865 | { | ||
866 | scroll_delay = ms / (HZ / 10); | ||
867 | } | ||
868 | |||
869 | void lcd_bidir_scroll(int percent) | ||
870 | { | ||
871 | bidir_limit = percent; | ||
872 | } | ||
873 | static void scroll_thread(void) | 832 | static void scroll_thread(void) |
874 | { | 833 | { |
875 | struct font* pf; | 834 | struct font* pf; |
@@ -932,4 +891,3 @@ static void scroll_thread(void) | |||
932 | } | 891 | } |
933 | } | 892 | } |
934 | 893 | ||
935 | #endif | ||
diff --git a/firmware/drivers/lcd-player.c b/firmware/drivers/lcd-player.c index c1657aa915..f0fbbc03ee 100644 --- a/firmware/drivers/lcd-player.c +++ b/firmware/drivers/lcd-player.c | |||
@@ -64,20 +64,6 @@ extern unsigned char extended_font_player[NO_EXTENDED_LCD_CHARS][8]; | |||
64 | 64 | ||
65 | /*** generic code ***/ | 65 | /*** generic code ***/ |
66 | 66 | ||
67 | struct scrollinfo { | ||
68 | int mode; | ||
69 | char text[MAX_PATH]; | ||
70 | int textlen; | ||
71 | int offset; | ||
72 | int turn_offset; | ||
73 | int startx; | ||
74 | int starty; | ||
75 | long scroll_start_tick; | ||
76 | int direction; /* +1 for right or -1 for left*/ | ||
77 | int jump_scroll; | ||
78 | int jump_scroll_steps; | ||
79 | }; | ||
80 | |||
81 | #define MAX_CURSOR_CHARS 8 | 67 | #define MAX_CURSOR_CHARS 8 |
82 | struct cursorinfo { | 68 | struct cursorinfo { |
83 | int len; | 69 | int len; |
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 | ||
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index 88b185ca93..58133fc7ce 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2005 by Richard S. La Charité | 10 | * Copyright (C) 2005 by Richard S. La Charité |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 12 | * All files in this archive are subject to the GNU General Public License. |
13 | * See the file COPYING in the source tree root for full license agreement. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -25,74 +25,61 @@ | |||
25 | #include "config.h" | 25 | #include "config.h" |
26 | 26 | ||
27 | #ifdef HAVE_REMOTE_LCD | 27 | #ifdef HAVE_REMOTE_LCD |
28 | |||
28 | #define REMOTE_DRAW_PIXEL(x,y) lcd_remote_framebuffer[(y)/8][(x)] |= (1<<((y)&7)) | 29 | #define REMOTE_DRAW_PIXEL(x,y) lcd_remote_framebuffer[(y)/8][(x)] |= (1<<((y)&7)) |
29 | #define REMOTE_CLEAR_PIXEL(x,y) lcd_remote_framebuffer[(y)/8][(x)] &= ~(1<<((y)&7)) | 30 | #define REMOTE_CLEAR_PIXEL(x,y) lcd_remote_framebuffer[(y)/8][(x)] &= ~(1<<((y)&7)) |
30 | #define REMOTE_INVERT_PIXEL(x,y) lcd_remote_framebuffer[(y)/8][(x)] ^= (1<<((y)&7)) | 31 | #define REMOTE_INVERT_PIXEL(x,y) lcd_remote_framebuffer[(y)/8][(x)] ^= (1<<((y)&7)) |
31 | 32 | ||
32 | #define STYLE_DEFAULT 0 | 33 | #define STYLE_DEFAULT 0 |
33 | #define STYLE_INVERT 1 | 34 | #define STYLE_INVERT 1 |
34 | 35 | ||
35 | extern void lcd_remote_init(void); | 36 | extern void lcd_remote_init(void); |
36 | extern void lcd_remote_clear_display(void); | ||
37 | extern void lcd_remote_backlight_on(void); | 37 | extern void lcd_remote_backlight_on(void); |
38 | extern void lcd_remote_backlight_off(void); | 38 | extern void lcd_remote_backlight_off(void); |
39 | extern void lcd_remote_stop_scroll(void); | ||
40 | extern void lcd_remote_scroll_speed( int speed ); | ||
41 | extern void lcd_remote_scroll_delay( int ms ); | ||
42 | extern void lcd_remote_set_contrast(int val); | ||
43 | extern int lcd_remote_default_contrast(void); | 39 | extern int lcd_remote_default_contrast(void); |
44 | extern void lcd_remote_update(void); | 40 | extern void lcd_remote_set_contrast(int val); |
45 | extern void lcd_remote_update_rect (int x_start, int y, | 41 | |
46 | int width, int height); | 42 | extern void lcd_remote_clear_display(void); |
47 | |||
48 | extern void lcd_remote_puts(int x, int y, const unsigned char *string); | 43 | extern void lcd_remote_puts(int x, int y, const unsigned char *string); |
49 | extern void lcd_remote_puts_style(int x, int y, const unsigned char *string, | 44 | extern void lcd_remote_puts_style(int x, int y, const unsigned char *string, |
50 | int style); | 45 | int style); |
51 | 46 | extern void lcd_remote_putc(int x, int y, unsigned short ch); | |
52 | extern void lcd_remote_puts_scroll(int x, int y, const unsigned char* string ); | 47 | extern void lcd_remote_stop_scroll(void); |
48 | extern void lcd_remote_scroll_speed(int speed); | ||
49 | extern void lcd_remote_scroll_delay(int ms); | ||
50 | extern void lcd_remote_puts_scroll(int x, int y, const unsigned char* string); | ||
53 | extern void lcd_remote_puts_scroll_style(int x, int y, const unsigned char* string, | 51 | extern void lcd_remote_puts_scroll_style(int x, int y, const unsigned char* string, |
54 | int style); | 52 | int style); |
55 | 53 | ||
56 | extern void lcd_remote_putc(int x, int y, unsigned short ch); | 54 | extern void lcd_remote_update(void); |
55 | extern void lcd_remote_update_rect int x_start, int y, int width, int height); | ||
57 | 56 | ||
57 | /* Memory copy of display bitmap */ | ||
58 | extern unsigned char lcd_remote_framebuffer[LCD_REMOTE_HEIGHT/8][LCD_REMOTE_WIDTH]; | ||
59 | |||
60 | extern void lcd_remote_set_invert_display(bool yesno); | ||
61 | extern void lcd_remote_set_flip(bool yesno); | ||
62 | extern void lcd_remote_roll(int pixels); | ||
58 | extern void lcd_remote_setmargins(int xmargin, int ymargin); | 63 | extern void lcd_remote_setmargins(int xmargin, int ymargin); |
59 | extern int lcd_remote_getxmargin(void); | 64 | extern int lcd_remote_getxmargin(void); |
60 | extern int lcd_remote_getymargin(void); | 65 | extern int lcd_remote_getymargin(void); |
61 | 66 | extern void lcd_remote_setfont(int font); | |
62 | /* | 67 | extern int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h); |
63 | * Memory copy of display bitmap | ||
64 | */ | ||
65 | extern unsigned char lcd_remote_framebuffer[LCD_REMOTE_HEIGHT/8][LCD_REMOTE_WIDTH]; | ||
66 | |||
67 | extern void lcd_remote_bitmap (const unsigned char *src, int x, int y, | ||
68 | int nx, int ny, bool clear); | ||
69 | extern void lcd_remote_clearrect (int x, int y, int nx, int ny); | ||
70 | extern void lcd_remote_fillrect (int x, int y, int nx, int ny); | ||
71 | extern void lcd_remote_invertrect (int x, int y, int nx, int ny); | ||
72 | extern void lcd_remote_drawrect (int x, int y, int nx, int ny); | ||
73 | extern void lcd_remote_invertrect (int x, int y, int nx, int ny); | ||
74 | //extern void lcd_invertscroll(int x, int y); | ||
75 | extern void lcd_remote_drawline( int x1, int y1, int x2, int y2 ); | ||
76 | extern void lcd_remote_clearline( int x1, int y1, int x2, int y2 ); | ||
77 | extern void lcd_remote_drawpixel(int x, int y); | 68 | extern void lcd_remote_drawpixel(int x, int y); |
78 | extern void lcd_remote_clearpixel(int x, int y); | 69 | extern void lcd_remote_clearpixel(int x, int y); |
79 | extern void lcd_remote_invertpixel(int x, int y); | 70 | extern void lcd_remote_invertpixel(int x, int y); |
80 | extern void lcd_remote_roll(int pixels); | 71 | extern void lcd_remote_drawline(int x1, int y1, int x2, int y2); |
81 | extern void lcd_remote_set_invert_display(bool yesno); | 72 | extern void lcd_remote_clearline(int x1, int y1, int x2, int y2); |
82 | extern void lcd_remote_set_flip(bool yesno); | 73 | extern void lcd_remote_drawrect(int x, int y, int nx, int ny); |
74 | extern void lcd_remote_clearrect(int x, int y, int nx, int ny); | ||
75 | extern void lcd_remote_fillrect(int x, int y, int nx, int ny); | ||
76 | extern void lcd_remote_invertrect(int x, int y, int nx, int ny); | ||
77 | extern void lcd_remote_bitmap(const unsigned char *src, int x, int y, | ||
78 | int nx, int ny, bool clear); | ||
79 | extern void lcd_remote_putsxy(int x, int y, const unsigned char *string); | ||
80 | extern void lcd_remote_invertscroll(int x, int y); | ||
83 | extern void lcd_remote_bidir_scroll(int threshold); | 81 | extern void lcd_remote_bidir_scroll(int threshold); |
84 | extern void lcd_remote_scroll_step(int pixels); | 82 | extern void lcd_remote_scroll_step(int pixels); |
85 | extern void lcd_remote_setfont(int font); | ||
86 | extern void lcd_remote_putsxy(int x, int y, const unsigned char *string); | ||
87 | extern int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h); | ||
88 | |||
89 | |||
90 | |||
91 | |||
92 | |||
93 | |||
94 | |||
95 | |||
96 | 83 | ||
97 | #endif | 84 | #endif |
98 | #endif | 85 | #endif |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 08a02a8303..8c05fb984f 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -29,35 +29,38 @@ | |||
29 | 29 | ||
30 | #ifdef SIMULATOR | 30 | #ifdef SIMULATOR |
31 | #define lcd_icon(x,y) sim_lcd_icon(x,y) | 31 | #define lcd_icon(x,y) sim_lcd_icon(x,y) |
32 | #define MAX_PATH 260 | ||
33 | #else | ||
34 | #include "file.h" /* for MAX_PATH; FIXME: Why does this not work for sims? */ | ||
32 | #endif | 35 | #endif |
33 | 36 | ||
34 | /* common functions */ | 37 | /* common functions */ |
38 | extern void lcd_write_command(int byte); | ||
39 | extern void lcd_write_command_ex(int cmd, int data1, int data2); | ||
40 | extern void lcd_write_data(const unsigned char* p_bytes, int count); | ||
35 | extern void lcd_init(void); | 41 | extern void lcd_init(void); |
36 | extern void lcd_clear_display(void); | ||
37 | extern void lcd_backlight(bool on); | 42 | extern void lcd_backlight(bool on); |
43 | extern int lcd_default_contrast(void); | ||
44 | extern void lcd_set_contrast(int val); | ||
45 | |||
46 | extern void lcd_clear_display(void); | ||
38 | extern void lcd_puts(int x, int y, const unsigned char *string); | 47 | extern void lcd_puts(int x, int y, const unsigned char *string); |
39 | extern void lcd_puts_style(int x, int y, const unsigned char *string, int style); | 48 | extern void lcd_puts_style(int x, int y, const unsigned char *string, int style); |
40 | extern void lcd_putc(int x, int y, unsigned short ch); | 49 | extern void lcd_putc(int x, int y, unsigned short ch); |
41 | 50 | extern void lcd_stop_scroll(void); | |
42 | extern void lcd_puts_scroll(int x, int y, const unsigned char* string ); | 51 | extern void lcd_scroll_speed(int speed); |
52 | extern void lcd_scroll_delay(int ms); | ||
53 | extern void lcd_puts_scroll(int x, int y, const unsigned char* string); | ||
43 | extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, | 54 | extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, |
44 | int style); | 55 | int style); |
45 | extern void lcd_icon(int icon, bool enable); | 56 | extern void lcd_icon(int icon, bool enable); |
46 | extern void lcd_stop_scroll(void); | ||
47 | extern void lcd_scroll_speed( int speed ); | ||
48 | extern void lcd_scroll_delay( int ms ); | ||
49 | extern void lcd_set_contrast(int val); | ||
50 | extern void lcd_write_command( int byte ); | ||
51 | extern void lcd_write_command_ex( int cmd, int data1, int data2); | ||
52 | extern void lcd_write_data( const unsigned char* p_bytes, int count ); | ||
53 | extern int lcd_default_contrast(void); | ||
54 | 57 | ||
55 | #if defined(SIMULATOR) || defined(HAVE_LCD_BITMAP) | 58 | #if defined(SIMULATOR) || defined(HAVE_LCD_BITMAP) |
56 | extern void lcd_update(void); | ||
57 | /* performance function */ | 59 | /* performance function */ |
58 | extern void lcd_blit (const unsigned char* p_data, int x, int y, int width, | 60 | extern void lcd_blit(const unsigned char* p_data, int x, int y, int width, |
59 | int height, int stride); | 61 | int height, int stride); |
60 | 62 | ||
63 | extern void lcd_update(void); | ||
61 | /* update a fraction of the screen */ | 64 | /* update a fraction of the screen */ |
62 | extern void lcd_update_rect(int x, int y, int width, int height); | 65 | extern void lcd_update_rect(int x, int y, int width, int height); |
63 | 66 | ||
@@ -97,56 +100,84 @@ enum | |||
97 | ICON_PARAM | 100 | ICON_PARAM |
98 | }; | 101 | }; |
99 | 102 | ||
100 | extern void lcd_define_hw_pattern (int which,const char *pattern,int length); | 103 | extern void lcd_double_height(bool on); |
101 | extern void lcd_define_pattern (int which,const char *pattern); | 104 | extern void lcd_define_hw_pattern(int which,const char *pattern,int length); |
102 | extern void lcd_double_height (bool on); | 105 | extern void lcd_define_pattern(int which,const char *pattern); |
103 | #define JUMP_SCROLL_ALWAYS 5 | ||
104 | extern void lcd_jump_scroll (int mode); /* 0=off, 1=once, ..., ALWAYS */ | ||
105 | extern void lcd_jump_scroll_delay( int ms ); | ||
106 | unsigned char lcd_get_locked_pattern(void); | 106 | unsigned char lcd_get_locked_pattern(void); |
107 | void lcd_unlock_pattern(unsigned char pat); | 107 | void lcd_unlock_pattern(unsigned char pat); |
108 | extern void lcd_bidir_scroll(int threshold); | ||
109 | void lcd_put_cursor(int x, int y, char cursor_char); | 108 | void lcd_put_cursor(int x, int y, char cursor_char); |
110 | void lcd_remove_cursor(void); | 109 | void lcd_remove_cursor(void); |
110 | extern void lcd_bidir_scroll(int threshold); | ||
111 | #define JUMP_SCROLL_ALWAYS 5 | ||
112 | extern void lcd_jump_scroll(int mode); /* 0=off, 1=once, ..., ALWAYS */ | ||
113 | extern void lcd_jump_scroll_delay(int ms); | ||
111 | #endif | 114 | #endif |
112 | 115 | ||
113 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) | 116 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) |
114 | #if defined(HAVE_LCD_CHARCELLS) && defined(SIMULATOR) | ||
115 | #endif | ||
116 | 117 | ||
117 | #define DRAW_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] |= (1<<((y)&7)) | 118 | #define DRAW_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] |= (1<<((y)&7)) |
118 | #define CLEAR_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] &= ~(1<<((y)&7)) | 119 | #define CLEAR_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] &= ~(1<<((y)&7)) |
119 | #define INVERT_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] ^= (1<<((y)&7)) | 120 | #define INVERT_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] ^= (1<<((y)&7)) |
120 | 121 | ||
121 | /* | 122 | /* Memory copy of display bitmap */ |
122 | * Memory copy of display bitmap | ||
123 | */ | ||
124 | extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; | 123 | extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; |
125 | 124 | ||
125 | extern void lcd_set_invert_display(bool yesno); | ||
126 | extern void lcd_set_flip(bool yesno); | ||
127 | extern void lcd_roll(int pixels); | ||
126 | extern void lcd_setmargins(int xmargin, int ymargin); | 128 | extern void lcd_setmargins(int xmargin, int ymargin); |
127 | extern int lcd_getxmargin(void); | 129 | extern int lcd_getxmargin(void); |
128 | extern int lcd_getymargin(void); | 130 | extern int lcd_getymargin(void); |
129 | extern void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | 131 | extern void lcd_setfont(int font); |
130 | bool clear); | 132 | extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); |
131 | extern void lcd_clearrect (int x, int y, int nx, int ny); | ||
132 | extern void lcd_fillrect (int x, int y, int nx, int ny); | ||
133 | extern void lcd_drawrect (int x, int y, int nx, int ny); | ||
134 | extern void lcd_invertrect (int x, int y, int nx, int ny); | ||
135 | extern void lcd_invertscroll(int x, int y); | ||
136 | extern void lcd_drawline( int x1, int y1, int x2, int y2 ); | ||
137 | extern void lcd_clearline( int x1, int y1, int x2, int y2 ); | ||
138 | extern void lcd_drawpixel(int x, int y); | 133 | extern void lcd_drawpixel(int x, int y); |
139 | extern void lcd_clearpixel(int x, int y); | 134 | extern void lcd_clearpixel(int x, int y); |
140 | extern void lcd_invertpixel(int x, int y); | 135 | extern void lcd_invertpixel(int x, int y); |
141 | extern void lcd_roll(int pixels); | 136 | extern void lcd_drawline(int x1, int y1, int x2, int y2); |
142 | extern void lcd_set_invert_display(bool yesno); | 137 | extern void lcd_clearline(int x1, int y1, int x2, int y2); |
143 | extern void lcd_set_flip(bool yesno); | 138 | extern void lcd_drawrect(int x, int y, int nx, int ny); |
139 | extern void lcd_clearrect(int x, int y, int nx, int ny); | ||
140 | extern void lcd_fillrect(int x, int y, int nx, int ny); | ||
141 | extern void lcd_invertrect(int x, int y, int nx, int ny); | ||
142 | extern void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | ||
143 | bool clear); | ||
144 | extern void lcd_putsxy(int x, int y, const unsigned char *string); | ||
145 | extern void lcd_invertscroll(int x, int y); | ||
144 | extern void lcd_bidir_scroll(int threshold); | 146 | extern void lcd_bidir_scroll(int threshold); |
145 | extern void lcd_scroll_step(int pixels); | 147 | extern void lcd_scroll_step(int pixels); |
146 | extern void lcd_setfont(int font); | ||
147 | extern void lcd_putsxy(int x, int y, const unsigned char *string); | ||
148 | extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); | ||
149 | 148 | ||
150 | #endif /* CHARCELLS / BITMAP */ | 149 | #endif /* CHARCELLS / BITMAP */ |
151 | 150 | ||
151 | /* internal usage, but in multiple drivers */ | ||
152 | #ifdef HAVE_LCD_BITMAP | ||
153 | #define SCROLL_SPACING 3 | ||
154 | |||
155 | struct scrollinfo { | ||
156 | char line[MAX_PATH + LCD_WIDTH/2 + SCROLL_SPACING + 2]; | ||
157 | int len; /* length of line in chars */ | ||
158 | int width; /* length of line in pixels */ | ||
159 | int offset; | ||
160 | int startx; | ||
161 | bool backward; /* scroll presently forward or backward? */ | ||
162 | bool bidir; | ||
163 | bool invert; /* invert the scrolled text */ | ||
164 | long start_tick; | ||
165 | }; | ||
166 | #else /* !HAVE_LCD_BITMAP */ | ||
167 | |||
168 | struct scrollinfo { | ||
169 | int mode; | ||
170 | char text[MAX_PATH]; | ||
171 | int textlen; | ||
172 | int offset; | ||
173 | int turn_offset; | ||
174 | int startx; | ||
175 | int starty; | ||
176 | long scroll_start_tick; | ||
177 | int direction; /* +1 for right or -1 for left*/ | ||
178 | int jump_scroll; | ||
179 | int jump_scroll_steps; | ||
180 | }; | ||
181 | #endif | ||
182 | |||
152 | #endif /* __LCD_H__ */ | 183 | #endif /* __LCD_H__ */ |