diff options
Diffstat (limited to 'uisimulator')
-rw-r--r-- | uisimulator/common/lcd-playersim.c | 684 |
1 files changed, 684 insertions, 0 deletions
diff --git a/uisimulator/common/lcd-playersim.c b/uisimulator/common/lcd-playersim.c new file mode 100644 index 0000000000..3405247a68 --- /dev/null +++ b/uisimulator/common/lcd-playersim.c | |||
@@ -0,0 +1,684 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | |||
21 | #ifdef HAVE_LCD_BITMAP | ||
22 | |||
23 | #include "lcd.h" | ||
24 | #include "kernel.h" | ||
25 | #include "thread.h" | ||
26 | #include <string.h> | ||
27 | #include <stdlib.h> | ||
28 | #include "file.h" | ||
29 | #include "debug.h" | ||
30 | #include "system.h" | ||
31 | #include "font.h" | ||
32 | |||
33 | /*** definitions ***/ | ||
34 | |||
35 | #define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) | ||
36 | #define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) | ||
37 | #define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20) | ||
38 | #define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28) | ||
39 | #define LCD_SET_DISPLAY_START_LINE ((char)0x40) | ||
40 | #define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81) | ||
41 | #define LCD_SET_SEGMENT_REMAP ((char)0xA0) | ||
42 | #define LCD_SET_LCD_BIAS ((char)0xA2) | ||
43 | #define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4) | ||
44 | #define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5) | ||
45 | #define LCD_SET_NORMAL_DISPLAY ((char)0xA6) | ||
46 | #define LCD_SET_REVERSE_DISPLAY ((char)0xA7) | ||
47 | #define LCD_SET_INDICATOR_OFF ((char)0xAC) | ||
48 | #define LCD_SET_INDICATOR_ON ((char)0xAD) | ||
49 | #define LCD_SET_DISPLAY_OFF ((char)0xAE) | ||
50 | #define LCD_SET_DISPLAY_ON ((char)0xAF) | ||
51 | #define LCD_SET_PAGE_ADDRESS ((char)0xB0) | ||
52 | #define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0) | ||
53 | #define LCD_SET_DISPLAY_OFFSET ((char)0xD3) | ||
54 | #define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0) | ||
55 | #define LCD_SOFTWARE_RESET ((char)0xE2) | ||
56 | #define LCD_NOP ((char)0xE3) | ||
57 | #define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE) | ||
58 | |||
59 | /* LCD command codes */ | ||
60 | #define LCD_CNTL_RESET 0xe2 // Software reset | ||
61 | #define LCD_CNTL_POWER 0x2f // Power control | ||
62 | #define LCD_CNTL_CONTRAST 0x81 // Contrast | ||
63 | #define LCD_CNTL_OUTSCAN 0xc8 // Output scan direction | ||
64 | #define LCD_CNTL_SEGREMAP 0xa1 // Segment remap | ||
65 | #define LCD_CNTL_DISPON 0xaf // Display on | ||
66 | |||
67 | #define LCD_CNTL_PAGE 0xb0 // Page address | ||
68 | #define LCD_CNTL_HIGHCOL 0x10 // Upper column address | ||
69 | #define LCD_CNTL_LOWCOL 0x00 // Lower column address | ||
70 | |||
71 | #define SCROLL_SPACING 3 | ||
72 | |||
73 | struct scrollinfo { | ||
74 | char line[MAX_PATH + LCD_WIDTH/2 + SCROLL_SPACING + 2]; | ||
75 | int len; /* length of line in chars */ | ||
76 | int width; /* length of line in pixels */ | ||
77 | int offset; | ||
78 | int startx; | ||
79 | int starty; | ||
80 | }; | ||
81 | |||
82 | static void scroll_thread(void); | ||
83 | static char scroll_stack[DEFAULT_STACK_SIZE]; | ||
84 | static char scroll_name[] = "scroll"; | ||
85 | static char scroll_speed = 8; /* updates per second */ | ||
86 | static char scroll_step = 6; /* pixels per scroll step */ | ||
87 | static struct scrollinfo scroll; /* only one scroll line at the moment */ | ||
88 | static int scroll_count = 0; | ||
89 | static int xmargin = 0; | ||
90 | static int ymargin = 0; | ||
91 | static int curfont = FONT_SYSFIXED; | ||
92 | |||
93 | #ifdef SIMULATOR | ||
94 | unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; | ||
95 | #else | ||
96 | static unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; | ||
97 | #endif | ||
98 | |||
99 | /* All zeros and ones bitmaps for area filling */ | ||
100 | static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
101 | static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, | ||
102 | 0xff, 0xff, 0xff, 0xff}; | ||
103 | |||
104 | void lcd_init(void) | ||
105 | { | ||
106 | create_thread(scroll_thread, scroll_stack, | ||
107 | sizeof(scroll_stack), scroll_name); | ||
108 | } | ||
109 | void lcd_clear_display (void) | ||
110 | { | ||
111 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | ||
112 | } | ||
113 | |||
114 | void lcd_setmargins(int x, int y) | ||
115 | { | ||
116 | xmargin = x; | ||
117 | ymargin = y; | ||
118 | } | ||
119 | |||
120 | int lcd_getxmargin(void) | ||
121 | { | ||
122 | return xmargin; | ||
123 | } | ||
124 | |||
125 | int lcd_getymargin(void) | ||
126 | { | ||
127 | return ymargin; | ||
128 | } | ||
129 | |||
130 | void lcd_setfont(int newfont) | ||
131 | { | ||
132 | curfont = newfont; | ||
133 | } | ||
134 | |||
135 | int lcd_getstringsize(unsigned char *str, int *w, int *h) | ||
136 | { | ||
137 | struct font* pf = font_get(curfont); | ||
138 | int ch; | ||
139 | int width = 0; | ||
140 | |||
141 | while((ch = *str++)) { | ||
142 | /* check input range*/ | ||
143 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
144 | ch = pf->defaultchar; | ||
145 | ch -= pf->firstchar; | ||
146 | |||
147 | /* get proportional width and glyph bits*/ | ||
148 | width += pf->width? pf->width[ch]: pf->maxwidth; | ||
149 | } | ||
150 | if ( w ) | ||
151 | *w = width; | ||
152 | if ( h ) | ||
153 | *h = pf->height; | ||
154 | |||
155 | return width; | ||
156 | } | ||
157 | |||
158 | /* put a string at a given char position */ | ||
159 | void lcd_puts(int x, int y, unsigned char *str) | ||
160 | { | ||
161 | int xpos,ypos,w,h; | ||
162 | |||
163 | #if defined(HAVE_LCD_CHARCELLS) | ||
164 | /* We make the simulator truncate the string if it reaches the right edge, | ||
165 | as otherwise it'll wrap. The real target doesn't wrap. */ | ||
166 | |||
167 | char buffer[12]; | ||
168 | if(strlen(str)+x > 11 ) { | ||
169 | strncpy(buffer, str, sizeof buffer); | ||
170 | buffer[11-x]=0; | ||
171 | str = buffer; | ||
172 | } | ||
173 | xmargin = 0; | ||
174 | ymargin = 8; | ||
175 | #endif | ||
176 | |||
177 | if(!str || !str[0]) | ||
178 | return; | ||
179 | |||
180 | lcd_getstringsize(str, &w, &h); | ||
181 | xpos = xmargin + x*w / strlen(str); | ||
182 | ypos = ymargin + y*h; | ||
183 | lcd_putsxy(xpos, ypos, str); | ||
184 | /* lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); */ | ||
185 | |||
186 | #if defined(HAVE_LCD_CHARCELLS) | ||
187 | /* this function is being used when simulating a charcell LCD and | ||
188 | then we update immediately */ | ||
189 | lcd_update(); | ||
190 | #endif | ||
191 | } | ||
192 | |||
193 | extern char* get_lcd_pattern(int width); | ||
194 | |||
195 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | ||
196 | static void lcd_putsxyofs(int x, int y, int ofs, unsigned char *str) | ||
197 | { | ||
198 | int ch; | ||
199 | struct font* pf = font_get(curfont); | ||
200 | |||
201 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) | ||
202 | { | ||
203 | int width; | ||
204 | |||
205 | /* check input range */ | ||
206 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
207 | #ifndef SIMULATOR | ||
208 | ch = pf->defaultchar; | ||
209 | #else | ||
210 | { | ||
211 | if (ch > 8) | ||
212 | ch = pf->defaultchar; | ||
213 | else | ||
214 | { | ||
215 | char* bm = get_lcd_pattern(ch); | ||
216 | width = 6; | ||
217 | lcd_bitmap(bm, x, y, width, 8, true); | ||
218 | x += width; | ||
219 | continue; | ||
220 | } | ||
221 | } | ||
222 | #endif | ||
223 | ch -= pf->firstchar; | ||
224 | |||
225 | /* no partial-height drawing for now... */ | ||
226 | if (y + pf->height > LCD_HEIGHT) | ||
227 | break; | ||
228 | |||
229 | /* get proportional width and glyph bits */ | ||
230 | width = pf->width ? pf->width[ch] : pf->maxwidth; | ||
231 | width = MIN (width, LCD_WIDTH - x); | ||
232 | |||
233 | if (ofs != 0) | ||
234 | { | ||
235 | if (ofs > width) | ||
236 | { | ||
237 | ofs -= width; | ||
238 | continue; | ||
239 | } | ||
240 | width -= ofs; | ||
241 | } | ||
242 | |||
243 | if (width > 0) | ||
244 | { | ||
245 | int rows = (pf->height + 7) / 8; | ||
246 | bitmap_t* bits = pf->bits + | ||
247 | (pf->offset ? pf->offset[ch] : (pf->height * ch)); | ||
248 | lcd_bitmap (((unsigned char*) bits) + ofs*rows, x, y, | ||
249 | width, pf->height, true); | ||
250 | x += width; | ||
251 | } | ||
252 | ofs = 0; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | /* put a string at a given pixel position */ | ||
257 | void lcd_putsxy(int x, int y, unsigned char *str) | ||
258 | { | ||
259 | lcd_putsxyofs(x, y, 0, str); | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * All bitmaps have this format: | ||
264 | * Bits within a byte are arranged veritcally, LSB at top. | ||
265 | * Bytes are stored in column-major format, with byte 0 at top left, | ||
266 | * byte 1 is 2nd from top, etc. Bytes following left-most column | ||
267 | * starts 2nd left column, etc. | ||
268 | * | ||
269 | * Note: The HW takes bitmap bytes in row-major order. | ||
270 | * | ||
271 | * Memory copy of display bitmap | ||
272 | */ | ||
273 | |||
274 | /* | ||
275 | * Draw a bitmap at (x, y), size (nx, ny) | ||
276 | * if 'clear' is true, clear destination area first | ||
277 | */ | ||
278 | void lcd_bitmap (unsigned char *src, int x, int y, int nx, int ny, | ||
279 | bool clear) __attribute__ ((section (".icode"))); | ||
280 | void lcd_bitmap (unsigned char *src, int x, int y, int nx, int ny, | ||
281 | bool clear) | ||
282 | { | ||
283 | unsigned char *dst; | ||
284 | unsigned char *dst2; | ||
285 | unsigned int data, mask, mask2, mask3, mask4; | ||
286 | int shift; | ||
287 | |||
288 | if (((unsigned)x >= LCD_WIDTH) || ((unsigned)y >= LCD_HEIGHT)) | ||
289 | return; | ||
290 | if (((unsigned)(x + nx)) >= LCD_WIDTH) | ||
291 | nx = LCD_WIDTH - x; | ||
292 | if (((unsigned)(y + ny)) >= LCD_HEIGHT) | ||
293 | ny = LCD_HEIGHT - y; | ||
294 | |||
295 | shift = y & 7; | ||
296 | dst2 = &lcd_framebuffer[x][y/8]; | ||
297 | ny += shift; | ||
298 | |||
299 | /* Calculate bit masks */ | ||
300 | mask4 = ~(0xfe << ((ny-1) & 7)); | ||
301 | if (clear) | ||
302 | { | ||
303 | mask = ~(0xff << shift); | ||
304 | mask2 = 0; | ||
305 | mask3 = ~mask4; | ||
306 | if (ny <= 8) | ||
307 | mask3 |= mask; | ||
308 | } | ||
309 | else | ||
310 | mask = mask2 = mask3 = 0xff; | ||
311 | |||
312 | /* Loop for each column */ | ||
313 | for (x = 0; x < nx; x++) | ||
314 | { | ||
315 | dst = dst2; | ||
316 | dst2 += LCD_HEIGHT/8; | ||
317 | data = 0; | ||
318 | y = 0; | ||
319 | |||
320 | if (ny > 8) | ||
321 | { | ||
322 | /* First partial row */ | ||
323 | data = *src++ << shift; | ||
324 | *dst = (*dst & mask) | data; | ||
325 | data >>= 8; | ||
326 | dst++; | ||
327 | |||
328 | /* Intermediate rows */ | ||
329 | for (y = 8; y < ny-8; y += 8) | ||
330 | { | ||
331 | data |= *src++ << shift; | ||
332 | *dst = (*dst & mask2) | data; | ||
333 | data >>= 8; | ||
334 | dst++; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | /* Last partial row */ | ||
339 | if (y + shift < ny) | ||
340 | data |= *src++ << shift; | ||
341 | *dst = (*dst & mask3) | (data & mask4); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * Draw a rectangle with upper left corner at (x, y) | ||
347 | * and size (nx, ny) | ||
348 | */ | ||
349 | void lcd_drawrect (int x, int y, int nx, int ny) | ||
350 | { | ||
351 | int i; | ||
352 | |||
353 | if (x > LCD_WIDTH) | ||
354 | return; | ||
355 | if (y > LCD_HEIGHT) | ||
356 | return; | ||
357 | |||
358 | if (x + nx > LCD_WIDTH) | ||
359 | nx = LCD_WIDTH - x; | ||
360 | if (y + ny > LCD_HEIGHT) | ||
361 | ny = LCD_HEIGHT - y; | ||
362 | |||
363 | /* vertical lines */ | ||
364 | for (i = 0; i < ny; i++) { | ||
365 | DRAW_PIXEL(x, (y + i)); | ||
366 | DRAW_PIXEL((x + nx - 1), (y + i)); | ||
367 | } | ||
368 | |||
369 | /* horizontal lines */ | ||
370 | for (i = 0; i < nx; i++) { | ||
371 | DRAW_PIXEL((x + i),y); | ||
372 | DRAW_PIXEL((x + i),(y + ny - 1)); | ||
373 | } | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * Clear a rectangular area at (x, y), size (nx, ny) | ||
378 | */ | ||
379 | void lcd_clearrect (int x, int y, int nx, int ny) | ||
380 | { | ||
381 | int i; | ||
382 | for (i = 0; i < nx; i++) | ||
383 | lcd_bitmap (zeros, x+i, y, 1, ny, true); | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * Fill a rectangular area at (x, y), size (nx, ny) | ||
388 | */ | ||
389 | void lcd_fillrect (int x, int y, int nx, int ny) | ||
390 | { | ||
391 | int i; | ||
392 | for (i = 0; i < nx; i++) | ||
393 | lcd_bitmap (ones, x+i, y, 1, ny, true); | ||
394 | } | ||
395 | |||
396 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | ||
397 | void lcd_invertrect (int x, int y, int nx, int ny) | ||
398 | { | ||
399 | int i, j; | ||
400 | |||
401 | if (x > LCD_WIDTH) | ||
402 | return; | ||
403 | if (y > LCD_HEIGHT) | ||
404 | return; | ||
405 | |||
406 | if (x + nx > LCD_WIDTH) | ||
407 | nx = LCD_WIDTH - x; | ||
408 | if (y + ny > LCD_HEIGHT) | ||
409 | ny = LCD_HEIGHT - y; | ||
410 | |||
411 | for (i = 0; i < nx; i++) | ||
412 | for (j = 0; j < ny; j++) | ||
413 | INVERT_PIXEL((x + i), (y + j)); | ||
414 | } | ||
415 | |||
416 | void lcd_drawline( int x1, int y1, int x2, int y2 ) | ||
417 | { | ||
418 | int numpixels; | ||
419 | int i; | ||
420 | int deltax, deltay; | ||
421 | int d, dinc1, dinc2; | ||
422 | int x, xinc1, xinc2; | ||
423 | int y, yinc1, yinc2; | ||
424 | |||
425 | deltax = abs(x2 - x1); | ||
426 | deltay = abs(y2 - y1); | ||
427 | |||
428 | if(deltax >= deltay) | ||
429 | { | ||
430 | numpixels = deltax; | ||
431 | d = 2 * deltay - deltax; | ||
432 | dinc1 = deltay * 2; | ||
433 | dinc2 = (deltay - deltax) * 2; | ||
434 | xinc1 = 1; | ||
435 | xinc2 = 1; | ||
436 | yinc1 = 0; | ||
437 | yinc2 = 1; | ||
438 | } | ||
439 | else | ||
440 | { | ||
441 | numpixels = deltay; | ||
442 | d = 2 * deltax - deltay; | ||
443 | dinc1 = deltax * 2; | ||
444 | dinc2 = (deltax - deltay) * 2; | ||
445 | xinc1 = 0; | ||
446 | xinc2 = 1; | ||
447 | yinc1 = 1; | ||
448 | yinc2 = 1; | ||
449 | } | ||
450 | numpixels++; /* include endpoints */ | ||
451 | |||
452 | if(x1 > x2) | ||
453 | { | ||
454 | xinc1 = -xinc1; | ||
455 | xinc2 = -xinc2; | ||
456 | } | ||
457 | |||
458 | if(y1 > y2) | ||
459 | { | ||
460 | yinc1 = -yinc1; | ||
461 | yinc2 = -yinc2; | ||
462 | } | ||
463 | |||
464 | x = x1; | ||
465 | y = y1; | ||
466 | |||
467 | for(i=0; i<numpixels; i++) | ||
468 | { | ||
469 | DRAW_PIXEL(x,y); | ||
470 | |||
471 | if(d < 0) | ||
472 | { | ||
473 | d += dinc1; | ||
474 | x += xinc1; | ||
475 | y += yinc1; | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | d += dinc2; | ||
480 | x += xinc2; | ||
481 | y += yinc2; | ||
482 | } | ||
483 | } | ||
484 | } | ||
485 | |||
486 | void lcd_clearline( int x1, int y1, int x2, int y2 ) | ||
487 | { | ||
488 | int numpixels; | ||
489 | int i; | ||
490 | int deltax, deltay; | ||
491 | int d, dinc1, dinc2; | ||
492 | int x, xinc1, xinc2; | ||
493 | int y, yinc1, yinc2; | ||
494 | |||
495 | deltax = abs(x2 - x1); | ||
496 | deltay = abs(y2 - y1); | ||
497 | |||
498 | if(deltax >= deltay) | ||
499 | { | ||
500 | numpixels = deltax; | ||
501 | d = 2 * deltay - deltax; | ||
502 | dinc1 = deltay * 2; | ||
503 | dinc2 = (deltay - deltax) * 2; | ||
504 | xinc1 = 1; | ||
505 | xinc2 = 1; | ||
506 | yinc1 = 0; | ||
507 | yinc2 = 1; | ||
508 | } | ||
509 | else | ||
510 | { | ||
511 | numpixels = deltay; | ||
512 | d = 2 * deltax - deltay; | ||
513 | dinc1 = deltax * 2; | ||
514 | dinc2 = (deltax - deltay) * 2; | ||
515 | xinc1 = 0; | ||
516 | xinc2 = 1; | ||
517 | yinc1 = 1; | ||
518 | yinc2 = 1; | ||
519 | } | ||
520 | numpixels++; /* include endpoints */ | ||
521 | |||
522 | if(x1 > x2) | ||
523 | { | ||
524 | xinc1 = -xinc1; | ||
525 | xinc2 = -xinc2; | ||
526 | } | ||
527 | |||
528 | if(y1 > y2) | ||
529 | { | ||
530 | yinc1 = -yinc1; | ||
531 | yinc2 = -yinc2; | ||
532 | } | ||
533 | |||
534 | x = x1; | ||
535 | y = y1; | ||
536 | |||
537 | for(i=0; i<numpixels; i++) | ||
538 | { | ||
539 | CLEAR_PIXEL(x,y); | ||
540 | |||
541 | if(d < 0) | ||
542 | { | ||
543 | d += dinc1; | ||
544 | x += xinc1; | ||
545 | y += yinc1; | ||
546 | } | ||
547 | else | ||
548 | { | ||
549 | d += dinc2; | ||
550 | x += xinc2; | ||
551 | y += yinc2; | ||
552 | } | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * Set a single pixel | ||
558 | */ | ||
559 | void lcd_drawpixel(int x, int y) | ||
560 | { | ||
561 | DRAW_PIXEL(x,y); | ||
562 | } | ||
563 | |||
564 | /* | ||
565 | * Clear a single pixel | ||
566 | */ | ||
567 | void lcd_clearpixel(int x, int y) | ||
568 | { | ||
569 | CLEAR_PIXEL(x,y); | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * Invert a single pixel | ||
574 | */ | ||
575 | void lcd_invertpixel(int x, int y) | ||
576 | { | ||
577 | INVERT_PIXEL(x,y); | ||
578 | } | ||
579 | |||
580 | void lcd_puts_scroll(int x, int y, unsigned char* string ) | ||
581 | { | ||
582 | struct scrollinfo* s = &scroll; | ||
583 | int w, h; | ||
584 | |||
585 | lcd_puts(x,y,string); | ||
586 | lcd_getstringsize(string, &w, &h); | ||
587 | |||
588 | if (LCD_WIDTH - x*8 - xmargin < w) | ||
589 | { | ||
590 | /* prepare scroll line */ | ||
591 | char *end; | ||
592 | |||
593 | memset(s->line, 0, sizeof s->line); | ||
594 | strcpy(s->line, string); | ||
595 | strcat(s->line, " "); | ||
596 | /* get new width incl. spaces */ | ||
597 | s->width = lcd_getstringsize(s->line, &w, &h); | ||
598 | |||
599 | for (end = s->line; *end; end++); | ||
600 | strncpy(end, string, LCD_WIDTH/2); | ||
601 | |||
602 | s->len = strlen(string); | ||
603 | s->offset = 0; | ||
604 | s->startx = x; | ||
605 | s->starty = y; | ||
606 | scroll_count = 1; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | |||
611 | void lcd_stop_scroll(void) | ||
612 | { | ||
613 | if ( scroll_count ) { | ||
614 | int w,h; | ||
615 | struct scrollinfo* s = &scroll; | ||
616 | scroll_count = 0; | ||
617 | |||
618 | lcd_getstringsize(s->line, &w, &h); | ||
619 | lcd_clearrect(xmargin + s->startx*w/s->len, | ||
620 | ymargin + s->starty*h, | ||
621 | LCD_WIDTH - xmargin, | ||
622 | h); | ||
623 | |||
624 | /* restore scrolled row */ | ||
625 | lcd_puts(s->startx,s->starty,s->line); | ||
626 | lcd_update(); | ||
627 | } | ||
628 | } | ||
629 | |||
630 | void lcd_scroll_pause(void) | ||
631 | { | ||
632 | scroll_count = 0; | ||
633 | } | ||
634 | |||
635 | void lcd_scroll_resume(void) | ||
636 | { | ||
637 | scroll_count = 1; | ||
638 | } | ||
639 | |||
640 | void lcd_scroll_speed(int speed) | ||
641 | { | ||
642 | scroll_step = speed; | ||
643 | } | ||
644 | |||
645 | static void scroll_thread(void) | ||
646 | { | ||
647 | struct scrollinfo* s = &scroll; | ||
648 | |||
649 | while ( 1 ) { | ||
650 | if ( !scroll_count ) { | ||
651 | yield(); | ||
652 | continue; | ||
653 | } | ||
654 | /* wait 0.5s before starting scroll */ | ||
655 | if ( scroll_count < scroll_speed/2 ) | ||
656 | scroll_count++; | ||
657 | else { | ||
658 | int w, h; | ||
659 | int xpos, ypos; | ||
660 | |||
661 | s->offset += scroll_step; | ||
662 | |||
663 | if (s->offset >= s->width) | ||
664 | s->offset %= s->width; | ||
665 | |||
666 | lcd_getstringsize(s->line, &w, &h); | ||
667 | xpos = xmargin + (s->startx-1) * w / s->len; | ||
668 | ypos = ymargin + s->starty * h; | ||
669 | |||
670 | lcd_clearrect(xpos, ypos, LCD_WIDTH - xmargin, h); | ||
671 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | ||
672 | lcd_update(); | ||
673 | } | ||
674 | sleep(HZ/scroll_speed); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | #endif | ||
679 | |||
680 | /* ----------------------------------------------------------------- | ||
681 | * local variables: | ||
682 | * eval: (load-file "../rockbox-mode.el") | ||
683 | * end: | ||
684 | */ | ||