diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-06-23 16:53:54 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-06-23 16:53:54 +0000 |
commit | 6a556c1740174d76da3f652de2a4ca0777b931c4 (patch) | |
tree | 7fb79cedee84ec829b359a2e8cee0f3c707dbfe5 /firmware/drivers/lcd-h100-remote.c | |
parent | bec1afada554b4624d0ef9b43b3443d1f0583cf3 (diff) | |
download | rockbox-6a556c1740174d76da3f652de2a4ca0777b931c4.tar.gz rockbox-6a556c1740174d76da3f652de2a4ca0777b931c4.zip |
Preparations for implementing the new graphics api: Ordered lcd bitmap driver defines, variables and functions by function groups. Centralised some definitions, code cleanup.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6844 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-h100-remote.c')
-rw-r--r-- | firmware/drivers/lcd-h100-remote.c | 832 |
1 files changed, 409 insertions, 423 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 | { |