diff options
Diffstat (limited to 'firmware/drivers/lcd-h100.c')
-rw-r--r-- | firmware/drivers/lcd-h100.c | 858 |
1 files changed, 408 insertions, 450 deletions
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 | ||