blob: d01ec3447f2e8b6512d9f492e43de60f99a09487 [file] [log] [blame]
Björn Stenberg86f9a842002-09-23 11:17:52 +00001/***************************************************************************
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"
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000020#include "hwcompat.h"
Björn Stenberg86f9a842002-09-23 11:17:52 +000021
22#ifdef HAVE_LCD_CHARCELLS
23
24#include "lcd.h"
25#include "kernel.h"
26#include "thread.h"
27#include <string.h>
28#include <stdlib.h>
29#include "file.h"
30#include "debug.h"
31#include "system.h"
32#include "font.h"
Kjell Ericsondd7f2942003-01-10 09:58:04 +000033#include "lcd-player-charset.h"
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +000034#include "rbunicode.h"
Björn Stenberg86f9a842002-09-23 11:17:52 +000035
Björn Stenberg86f9a842002-09-23 11:17:52 +000036/*** definitions ***/
37
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000038#define OLD_LCD_CONTRAST_SET ((char)0xA8)
39#define OLD_LCD_CRAM ((char)0xB0) /* Characters */
40#define OLD_LCD_PRAM ((char)0x80) /* Patterns */
41#define OLD_LCD_IRAM ((char)0xE0) /* Icons */
42
43#define NEW_LCD_CONTRAST_SET ((char)0x50)
44#define NEW_LCD_CRAM ((char)0x80) /* Characters */
45#define NEW_LCD_PRAM ((char)0xC0) /* Patterns */
46#define NEW_LCD_IRAM ((char)0x40) /* Icons */
Jens Arnold2e290d62004-11-11 01:11:06 +000047#define NEW_LCD_FUNCTION_SET ((char)0x10)
48#define NEW_LCD_POWER_SAVE_MODE_OSC_CONTROL_SET ((char)0x0c)
49#define NEW_LCD_POWER_CONTROL_REGISTER_SET ((char)0x20)
50#define NEW_LCD_DISPLAY_CONTROL_SET ((char)0x28)
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000051
Jens Arnold2e290d62004-11-11 01:11:06 +000052#define LCD_CURSOR(x,y) ((char)(lcd_cram+((y)*16+(x))))
53#define LCD_ICON(i) ((char)(lcd_iram+i))
Björn Stenberg86f9a842002-09-23 11:17:52 +000054
Markus Braunbc254fe2002-10-21 13:14:25 +000055#define SCROLLABLE_LINES 2
56
57#define SCROLL_MODE_OFF 0
58#define SCROLL_MODE_PAUSE 1
59#define SCROLL_MODE_RUN 2
60
Kjell Ericsondd7f2942003-01-10 09:58:04 +000061extern unsigned short new_lcd_rocklatin1_to_xlcd[];
62extern unsigned short old_lcd_rocklatin1_to_xlcd[];
Jens Arnold9478cc62004-08-03 19:22:56 +000063extern const unsigned char lcd_player_extended_lcd_to_rocklatin1[];
Kjell Ericsondd7f2942003-01-10 09:58:04 +000064extern unsigned char extended_font_player[NO_EXTENDED_LCD_CHARS][8];
65
Björn Stenberg86f9a842002-09-23 11:17:52 +000066/*** generic code ***/
67
Kjell Ericson565505a2003-01-27 14:37:03 +000068#define MAX_CURSOR_CHARS 8
69struct cursorinfo {
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +000070 int len;
71 char text[MAX_CURSOR_CHARS];
72 int textpos;
73 int y_pos;
74 int x_pos;
75 int divider;
76 int downcount;
Kjell Ericson565505a2003-01-27 14:37:03 +000077} cursor;
78
Björn Stenberg86f9a842002-09-23 11:17:52 +000079static void scroll_thread(void);
80static char scroll_stack[DEFAULT_STACK_SIZE];
Jens Arnold2b0694c2004-08-03 05:58:46 +000081static const char scroll_name[] = "scroll";
Jens Arnold05af2802005-07-28 08:36:24 +000082static int scroll_ticks = 12; /* # of ticks between updates */
Kjell Ericsondc88e232003-01-10 12:23:36 +000083static int scroll_delay = HZ/2; /* delay before starting scroll */
Kjell Ericson6143eeb2003-05-27 12:54:11 +000084static int jump_scroll_delay = HZ/4; /* delay between jump scroll jumps */
Jens Arnold05af2802005-07-28 08:36:24 +000085static int scroll_spacing = 3; /* spaces between end and start of text */
Mats Lidell4c7f70f2003-01-14 10:45:57 +000086static int bidir_limit = 50; /* percent */
Kjell Ericson6143eeb2003-05-27 12:54:11 +000087static int jump_scroll = 0; /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
Björn Stenberg86f9a842002-09-23 11:17:52 +000088
Markus Braunbc254fe2002-10-21 13:14:25 +000089static struct scrollinfo scroll[SCROLLABLE_LINES];
Björn Stenberg86f9a842002-09-23 11:17:52 +000090
Kjell Ericsondd7f2942003-01-10 09:58:04 +000091static char extended_chars_mapped[NO_EXTENDED_LCD_CHARS];
92static char extended_pattern_content[8]; /* Which char is mapped in pattern */
93static char extended_pattern_usage[8]; /* Counting number of times used */
94static char pattern_size; /* Last pattern, 3 for old LCD, 7 for new LCD */
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000095
96static bool new_lcd;
97
Daniel Stenberg006b2c12003-12-12 13:23:33 +000098unsigned short *lcd_ascii;
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000099static char lcd_contrast_set;
100static char lcd_cram;
101static char lcd_pram;
102static char lcd_iram;
103
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000104unsigned short buffer_xlcd[11][2];
105unsigned short buffer_lcd_mirror[11][2];
106
107#ifdef SIMULATOR
108unsigned char hardware_buffer_lcd[11][2];
Jens Arnold1aa9cda2004-04-21 11:00:51 +0000109#else
110static unsigned char lcd_data_byte; /* global write buffer */
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000111#endif
Jens Arnold1aa9cda2004-04-21 11:00:51 +0000112
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000113#define NO_CHAR -1
114
115static void lcd_free_pat(int map_ch)
116{
117 int x, y;
Jens Arnold38e8a112004-04-21 09:39:29 +0000118 unsigned char substitute_char;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000119
120 int pat;
121 pat=extended_chars_mapped[map_ch];
122 if (pat!=NO_CHAR) {
123
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000124 substitute_char=lcd_player_extended_lcd_to_rocklatin1[map_ch];
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000125
Daniel Stenberg006b2c12003-12-12 13:23:33 +0000126 /* TODO: use a define for the screen width! */
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000127 for (x=0; x<11; x++) {
Daniel Stenberg006b2c12003-12-12 13:23:33 +0000128 /* TODO: use a define for the screen height! */
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000129 for (y=0; y<2; y++) {
130 if (map_ch==lcd_ascii[buffer_xlcd[x][y]]-512) {
131 buffer_xlcd[x][y]=substitute_char;
132 buffer_lcd_mirror[x][y]=substitute_char;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000133#ifdef SIMULATOR
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000134 hardware_buffer_lcd[x][y]=substitute_char;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000135#else
Jens Arnold38e8a112004-04-21 09:39:29 +0000136 lcd_write_command(LCD_CURSOR(x, y));
137 lcd_write_data(&substitute_char, 1);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000138#endif
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000139 }
140 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000141 }
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000142 extended_chars_mapped[map_ch]=NO_CHAR;
143 extended_pattern_content[pat]=NO_CHAR;
144 extended_pattern_usage[pat]=0;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000145 }
146#ifdef SIMULATOR
147 lcd_update();
148#endif
149}
150
151static int lcd_get_free_pat(int ch)
152{
153 int pat;
154 int last_pat=0;
155 static int last_used_pat=0;
156 int loop;
157
Mats Lidell1a4fd1f2003-01-13 13:09:54 +0000158 pat=last_used_pat;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000159 for (loop=0; loop<=pattern_size; loop++) {
160 pat=(pat+1)&pattern_size; /* Keep 'pat' within limits */
161 if (extended_pattern_usage[pat]==0) {
162 int map_ch=extended_pattern_content[pat];
163 if (map_ch != NO_CHAR) {
164 extended_chars_mapped[map_ch]=NO_CHAR;
165 extended_pattern_content[pat]=NO_CHAR;
166 }
Mats Lidell1a4fd1f2003-01-13 13:09:54 +0000167 last_used_pat=pat;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000168 return pat;
169 }
170 if (extended_pattern_content[pat]>extended_pattern_content[last_pat])
171 last_pat=pat;
172 }
173 if (ch<32) { /* Prioritized char */
174 /* Remove last_pat */
175 lcd_free_pat(extended_pattern_content[last_pat]);
176 last_used_pat=last_pat;
177 return last_pat;
178 }
179 return NO_CHAR;
180
181}
182
Kjell Ericsona33d6b22003-01-10 10:12:17 +0000183void xlcd_update(void)
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000184{
185 int x, y;
186 for (x=0; x<11; x++) {
187 for (y=0; y<2; y++) {
188 unsigned short ch=buffer_xlcd[x][y];
189 unsigned char hw_ch=0xff;
190 if (ch==buffer_lcd_mirror[x][y])
191 continue; /* No need to redraw */
192 buffer_lcd_mirror[x][y]=ch;
193 if (ch>=256 && ch<512) {
194 hw_ch=ch-256;
195 } else {
196 int map_ch=lcd_ascii[ch];
197 if (map_ch<512) {
198 hw_ch=map_ch;
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000199 }
200 else {
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000201 map_ch=map_ch-512;
202 if (extended_chars_mapped[map_ch]!=NO_CHAR) {
203 hw_ch=extended_chars_mapped[map_ch];
204 extended_pattern_usage[hw_ch]++;
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000205 }
206 else {
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000207 int pat;
208 pat=lcd_get_free_pat(map_ch);
209 if (pat<0) {
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000210 DEBUGF("Substitute for %02x (map 0x%02x)"
211 " is used.\n", ch, map_ch);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000212 /* Find substitute char */
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000213 map_ch=
214 lcd_player_extended_lcd_to_rocklatin1[map_ch];
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000215 hw_ch=lcd_ascii[map_ch];
216 } else {
217#ifdef DEBUG
218 if (extended_pattern_usage[pat]!=0) {
Kjell Ericson36393252003-01-10 10:13:48 +0000219 DEBUGF("***Pattern %d is not zero!\n", pat);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000220 }
221#endif
222 extended_chars_mapped[map_ch]=pat;
223 extended_pattern_content[pat]=map_ch;
224 extended_pattern_usage[pat]=1;
225 lcd_define_hw_pattern(pat*8,
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000226 extended_font_player[map_ch],
227 8);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000228 hw_ch=pat;
229 }
230 }
231 }
232 }
233#ifdef SIMULATOR
234 hardware_buffer_lcd[x][y]=hw_ch;
235#else
Jens Arnold38e8a112004-04-21 09:39:29 +0000236 lcd_write_command(LCD_CURSOR(x,y));
237 lcd_write_data(&hw_ch, 1);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000238#endif
239 }
240 }
241 lcd_update();
242}
243
244bool lcdx_putc(int x, int y, unsigned short ch)
245{
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000246 int lcd_char;
247 if (buffer_xlcd[x][y]==ch)
248 return false; /* Same char, ignore any update */
249 lcd_char=lcd_ascii[buffer_xlcd[x][y]];
250 if (lcd_char>=512) {
251 /* The removed char is a defined pattern, count down the reference. */
252 extended_pattern_usage[(int)extended_chars_mapped[lcd_char-512]]--;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000253#ifdef DEBUG
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000254 if (extended_pattern_usage[(int)extended_chars_mapped[lcd_char]]<0) {
255 DEBUGF("**** Mapped char %02x is less than 0!\n", lcd_char);
256 }
257#endif
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000258 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000259
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000260 buffer_xlcd[x][y]=ch;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000261
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000262 lcd_char=lcd_ascii[ch];
263 if (lcd_char>=256)
264 return true; /* Caller shall call xlcd_update() when done */
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000265
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000266 buffer_lcd_mirror[x][y]=lcd_char;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000267#ifdef SIMULATOR
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000268 hardware_buffer_lcd[x][y]=lcd_char;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000269#else
Jens Arnold38e8a112004-04-21 09:39:29 +0000270 lcd_data_byte = (unsigned char) lcd_char;
271 lcd_write_command(LCD_CURSOR(x, y));
272 lcd_write_data(&lcd_data_byte, 1);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000273#endif
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000274 return false;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000275}
276
Björn Stenberg067262d2003-07-09 23:07:49 +0000277int lcd_default_contrast(void)
278{
279 return 30;
280}
281
Björn Stenberg86f9a842002-09-23 11:17:52 +0000282void lcd_clear_display(void)
283{
284 int i;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000285 bool update=false;
286 DEBUGF("lcd_clear_display()\n");
Kjell Ericson75361e52003-01-14 13:51:09 +0000287 lcd_stop_scroll();
Kjell Ericson565505a2003-01-27 14:37:03 +0000288 cursor.len=0; /* Stop cursor */
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000289 for (i=0;i<22;i++)
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000290 update|=lcdx_putc(i%11, i/11, ' ');
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000291 if (update)
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000292 xlcd_update();
Björn Stenberg86f9a842002-09-23 11:17:52 +0000293}
294
Jens Arnold1413f0c2004-08-01 22:11:08 +0000295static void lcd_puts_cont_scroll(int x, int y, const unsigned char *string)
Björn Stenberg86f9a842002-09-23 11:17:52 +0000296{
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000297 bool update=false;
Kjell Ericson7f9d7132003-01-22 12:16:14 +0000298 DEBUGF("lcd_puts_cont_scroll(%d, %d, \"", x, y);
Kjell Ericsond618fb02003-01-21 14:25:24 +0000299
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000300 for (; *string && x<11; x++)
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000301 {
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000302#ifdef DEBUGF
303 if (*string>=32 && *string<128)
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000304 {
305 DEBUGF("%c", *string);
306 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000307 else
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000308 {
309 DEBUGF("(0x%02x)", *string);
310 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000311#endif
312 /* We should check if char is over 256 */
313 update|=lcdx_putc(x, y, *(unsigned char*)string++);
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000314 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000315 DEBUGF("\")\n");
316
Björn Stenberg86f9a842002-09-23 11:17:52 +0000317 for (; x<11; x++)
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000318 update|=lcdx_putc(x, y, ' ');
319 if (update)
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000320 xlcd_update();
Linus Nielsen Feltzing80ebaab2004-07-20 11:43:44 +0000321#ifdef SIMULATOR
322 lcd_update();
323#endif
Björn Stenberg86f9a842002-09-23 11:17:52 +0000324}
Jens Arnold1413f0c2004-08-01 22:11:08 +0000325void lcd_puts(int x, int y, const unsigned char *string)
Kjell Ericsond618fb02003-01-21 14:25:24 +0000326{
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000327 int i=0;
328 unsigned short ucs;
329 const unsigned char *utf8 = string;
330 unsigned char tmp[12];
331
332 while (*utf8 && i<11) {
333 utf8 = utf8decode(utf8, &ucs);
334 if (ucs < 256)
335 tmp[i++] = ucs;
336 else
337 tmp[i++] = '?';
338 }
339
340 tmp[i] = 0;
341
Kjell Ericson7f9d7132003-01-22 12:16:14 +0000342 DEBUGF("lcd_puts(%d, %d) -> ", x, y);
Kjell Ericsond618fb02003-01-21 14:25:24 +0000343 scroll[y].mode=SCROLL_MODE_OFF;
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000344 return lcd_puts_cont_scroll(x, y, tmp);
Kjell Ericsond618fb02003-01-21 14:25:24 +0000345}
Björn Stenberg86f9a842002-09-23 11:17:52 +0000346
Kjell Ericson565505a2003-01-27 14:37:03 +0000347void lcd_put_cursor(int x, int y, char cursor_char)
348{
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000349 if (cursor.len == 0) {
350 cursor.text[0]=buffer_xlcd[x][y];
351 cursor.text[1]=cursor_char;
352 cursor.len=2;
353 cursor.textpos=0;
354 cursor.y_pos=y;
355 cursor.x_pos=x;
356 cursor.downcount=0;
357 cursor.divider=4;
358 }
Kjell Ericson9d40f7e2003-01-29 11:48:35 +0000359}
360
361void lcd_remove_cursor(void)
362{
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000363 if (cursor.len!=0) {
364 bool up;
365 cursor.len=0;
366 up = lcdx_putc(cursor.x_pos, cursor.y_pos, cursor.text[0]);
367#ifdef SIMULATOR
Daniel Stenberg7b9edd62003-01-29 17:34:28 +0000368 if(up)
369 lcd_update();
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000370#endif
371 }
Kjell Ericson565505a2003-01-27 14:37:03 +0000372}
373
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000374void lcd_putc(int x, int y, unsigned short ch)
Björn Stenberg86f9a842002-09-23 11:17:52 +0000375{
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000376 bool update;
377 DEBUGF("lcd_putc(%d, %d, %d '0x%02x')\n", x, y, ch, ch);
378 if (x<0 || y<0) {
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000379 return;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000380 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000381 update=lcdx_putc(x, y, ch);
382
383 if (update)
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000384 xlcd_update();
Björn Stenberg86f9a842002-09-23 11:17:52 +0000385}
386
Kjell Ericsona33d6b22003-01-10 10:12:17 +0000387unsigned char lcd_get_locked_pattern(void)
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000388{
389 unsigned char pat=1;
390 while (pat<LAST_RESERVED_CHAR) {
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000391 if (lcd_ascii[pat]==RESERVED_CHAR) {
392 lcd_ascii[pat]=0x200+pat;
393 return pat;
394 }
395 pat++;
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000396 }
397 return 0;
398}
399
400void lcd_unlock_pattern(unsigned char pat)
401{
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000402 lcd_ascii[pat]=RESERVED_CHAR;
403 lcd_free_pat(pat);
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000404}
405
Jens Arnold0ceaa5e2004-08-17 01:45:48 +0000406void lcd_define_pattern(int pat, const char *pattern)
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000407{
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000408 int i;
409 for (i=0; i<7; i++) {
410 extended_font_player[pat][i]=pattern[i];
411 }
412 if (extended_chars_mapped[pat]!=NO_CHAR) {
413 lcd_define_hw_pattern(extended_chars_mapped[pat]*8, pattern, 7);
414 }
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000415}
416
417#ifndef SIMULATOR
Jens Arnold0ceaa5e2004-08-17 01:45:48 +0000418void lcd_define_hw_pattern (int which,const char *pattern,int length)
Björn Stenberg86f9a842002-09-23 11:17:52 +0000419{
Jens Arnold38e8a112004-04-21 09:39:29 +0000420 lcd_write_command(lcd_pram | which);
421 lcd_write_data(pattern, length);
Björn Stenberg86f9a842002-09-23 11:17:52 +0000422}
423
424void lcd_double_height(bool on)
425{
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +0000426 if(new_lcd)
Jens Arnold38e8a112004-04-21 09:39:29 +0000427 lcd_write_command(on?9:8);
Björn Stenberg86f9a842002-09-23 11:17:52 +0000428}
429
Jens Arnold2b0694c2004-08-03 05:58:46 +0000430static const char icon_pos[] =
Björn Stenberg86f9a842002-09-23 11:17:52 +0000431{
432 0, 0, 0, 0, /* Battery */
433 2, /* USB */
434 3, /* Play */
435 4, /* Record */
436 5, /* Pause */
437 5, /* Audio */
438 6, /* Repeat */
439 7, /* 1 */
440 9, /* Volume */
441 9, /* Volume 1 */
442 9, /* Volume 2 */
443 10, /* Volume 3 */
444 10, /* Volume 4 */
445 10, /* Volume 5 */
446 10, /* Param */
447};
448
Jens Arnold2b0694c2004-08-03 05:58:46 +0000449static const char icon_mask[] =
Björn Stenberg86f9a842002-09-23 11:17:52 +0000450{
451 0x02, 0x08, 0x04, 0x10, /* Battery */
452 0x04, /* USB */
453 0x10, /* Play */
454 0x10, /* Record */
455 0x02, /* Pause */
456 0x10, /* Audio */
457 0x02, /* Repeat */
458 0x01, /* 1 */
459 0x04, /* Volume */
460 0x02, /* Volume 1 */
461 0x01, /* Volume 2 */
462 0x08, /* Volume 3 */
463 0x04, /* Volume 4 */
464 0x01, /* Volume 5 */
465 0x10, /* Param */
466};
467
468void lcd_icon(int icon, bool enable)
469{
470 static unsigned char icon_mirror[11] = {0};
471 int pos, mask;
472
473 pos = icon_pos[icon];
474 mask = icon_mask[icon];
475
Jens Arnold38e8a112004-04-21 09:39:29 +0000476 lcd_write_command(LCD_ICON(pos));
Björn Stenberg86f9a842002-09-23 11:17:52 +0000477
478 if(enable)
479 icon_mirror[pos] |= mask;
480 else
481 icon_mirror[pos] &= ~mask;
482
Jens Arnold38e8a112004-04-21 09:39:29 +0000483 lcd_write_data(&icon_mirror[pos], 1);
Björn Stenberg86f9a842002-09-23 11:17:52 +0000484}
485
Mats Lidell8ca78b62002-10-18 09:24:23 +0000486void lcd_set_contrast(int val)
487{
Jens Arnold38e8a112004-04-21 09:39:29 +0000488 lcd_data_byte = (unsigned char) (31 - val);
489 lcd_write_command(lcd_contrast_set);
490 lcd_write_data(&lcd_data_byte, 1);
Mats Lidell8ca78b62002-10-18 09:24:23 +0000491}
492#endif /* SIMULATOR */
493
Björn Stenberg86f9a842002-09-23 11:17:52 +0000494void lcd_init (void)
495{
Jens Arnold2e290d62004-11-11 01:11:06 +0000496 unsigned char data_vector[64];
Jens Arnold1710e382004-11-11 01:36:37 +0000497
498 (void)data_vector;
Jens Arnold2e290d62004-11-11 01:11:06 +0000499
Jens Arnoldd4e53972004-11-22 21:20:54 +0000500 new_lcd = is_new_player();
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000501 memset(extended_chars_mapped, NO_CHAR, sizeof(extended_chars_mapped));
502 memset(extended_pattern_content, NO_CHAR,sizeof(extended_pattern_content));
503 memset(extended_pattern_usage, 0, sizeof(extended_pattern_usage));
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +0000504
505 if(new_lcd) {
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000506 lcd_ascii = new_lcd_rocklatin1_to_xlcd;
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +0000507 lcd_contrast_set = NEW_LCD_CONTRAST_SET;
508 lcd_cram = NEW_LCD_CRAM;
509 lcd_pram = NEW_LCD_PRAM;
510 lcd_iram = NEW_LCD_IRAM;
Daniel Stenberg006b2c12003-12-12 13:23:33 +0000511 pattern_size=7; /* Last pattern, 7 for new LCD */
Jens Arnold2e290d62004-11-11 01:11:06 +0000512
Jens Arnold1710e382004-11-11 01:36:37 +0000513#ifndef SIMULATOR
Jens Arnold2e290d62004-11-11 01:11:06 +0000514 /* LCD init for cold start */
515 PBCR2 &= 0xff00; /* Set PB0..PB3 to GPIO */
516 or_b(0x0f, &PBIORL); /* ... output */
517 or_b(0x0f, &PBDRL); /* ... and high */
518
519 lcd_write_command(NEW_LCD_FUNCTION_SET + 1); /* CGRAM selected */
520 lcd_write_command(NEW_LCD_CONTRAST_SET);
521 lcd_data_byte = 0x08;
522 lcd_write_data(&lcd_data_byte, 1);
523 lcd_write_command(NEW_LCD_POWER_SAVE_MODE_OSC_CONTROL_SET + 2);
524 /* oscillator on */
525 lcd_write_command(NEW_LCD_POWER_CONTROL_REGISTER_SET + 7);
526 /* opamp buffer + voltage booster on*/
527
528 memset(data_vector, 0x20, 64);
529 lcd_write_command(NEW_LCD_CRAM); /* Set DDRAM address */
530 lcd_write_data(data_vector, 64); /* all spaces */
531
532 memset(data_vector, 0, 64);
533 lcd_write_command(NEW_LCD_PRAM); /* Set CGRAM address */
534 lcd_write_data(data_vector, 64); /* zero out */
535 lcd_write_command(NEW_LCD_IRAM); /* Set ICONRAM address */
536 lcd_write_data(data_vector, 16); /* zero out */
537
538 lcd_write_command(NEW_LCD_DISPLAY_CONTROL_SET + 1); /* display on */
Jens Arnold1710e382004-11-11 01:36:37 +0000539#endif /* !SIMULATOR */
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000540 }
541 else {
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000542 lcd_ascii = old_lcd_rocklatin1_to_xlcd;
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +0000543 lcd_contrast_set = OLD_LCD_CONTRAST_SET;
544 lcd_cram = OLD_LCD_CRAM;
545 lcd_pram = OLD_LCD_PRAM;
546 lcd_iram = OLD_LCD_IRAM;
Daniel Stenberg006b2c12003-12-12 13:23:33 +0000547 pattern_size=3; /* Last pattern, 3 for old LCD */
Jens Arnold1710e382004-11-11 01:36:37 +0000548
549#ifndef SIMULATOR
Jens Arnold2e290d62004-11-11 01:11:06 +0000550#if 1
551 /* LCD init for cold start */
552 PBCR2 &= 0xff00; /* Set PB0..PB3 to GPIO */
553 or_b(0x0f, &PBIORL); /* ... output */
554 or_b(0x0f, &PBDRL); /* ... and high */
555
556 lcd_write_command(0x61);
557 lcd_write_command(0x42);
558 lcd_write_command(0x57);
559
560 memset(data_vector, 0x24, 13);
561 lcd_write_command(OLD_LCD_CRAM); /* Set DDRAM address */
562 lcd_write_data(data_vector, 13); /* all spaces */
563 lcd_write_command(OLD_LCD_CRAM + 0x10);
564 lcd_write_data(data_vector, 13);
565 lcd_write_command(OLD_LCD_CRAM + 0x20);
566 lcd_write_data(data_vector, 13);
567
568 memset(data_vector, 0, 32);
569 lcd_write_command(OLD_LCD_PRAM); /* Set CGRAM address */
570 lcd_write_data(data_vector, 32); /* zero out */
571 lcd_write_command(OLD_LCD_IRAM); /* Set ICONRAM address */
572 lcd_write_data(data_vector, 13); /* zero out */
573 lcd_write_command(OLD_LCD_IRAM + 0x10);
574 lcd_write_data(data_vector, 13);
575
576 lcd_write_command(0x31);
577#else
578 /* archos look-alike code, left here for reference. As soon as the
579 * rockbox version is confirmed working, this will go away */
580 {
581 int i;
582
583 PBCR2 &= 0xc000;
584 PBIOR |= 0x000f;
585 PBDR |= 0x0002;
586 PBDR |= 0x0001;
587 PBDR |= 0x0004;
588 PBDR |= 0x0008;
589
590 for (i=0; i<200; i++) asm volatile ("nop"); /* wait 100 us */
591
592 PBDR &= 0xfffd; /* CS low (assert) */
593
594 for (i=0; i<100; i++) asm volatile ("nop"); /* wait 50 us */
595
596 lcd_write_command(0x61);
597 lcd_write_command(0x42);
598 lcd_write_command(0x57);
599
600 memset(data_vector, 0x24, 13);
601 lcd_write_command(0xb0); /* Set DDRAM address */
602 lcd_write_data(data_vector, 13); /* all spaces */
603 lcd_write_command(0xc0);
604 lcd_write_data(data_vector, 13);
605 lcd_write_command(0xd0);
606 lcd_write_data(data_vector, 13);
607
608 memset(data_vector, 0, 32);
609 lcd_write_command(0x80); /* Set CGRAM address */
610 lcd_write_data(data_vector, 32); /* zero out */
611 lcd_write_command(0xe0); /* Set ICONRAM address */
612 lcd_write_data(data_vector, 13); /* zero out */
613 lcd_write_command(0xf0);
614 lcd_write_data(data_vector, 13);
615
616 for (i=0; i<300000; i++) asm volatile ("nop"); /* wait 150 ms */
617
618 lcd_write_command(0x31);
619 lcd_write_command(0xa8); /* Set contrast control */
620 lcd_data_byte = 0;
621 lcd_write_data(&lcd_data_byte, 1); /* 0 */
622 }
623#endif
Jens Arnold1710e382004-11-11 01:36:37 +0000624#endif /* !SIMULATOR */
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +0000625 }
626
Björn Stenberg067262d2003-07-09 23:07:49 +0000627 lcd_set_contrast(lcd_default_contrast());
628
Björn Stenberg86f9a842002-09-23 11:17:52 +0000629 create_thread(scroll_thread, scroll_stack,
630 sizeof(scroll_stack), scroll_name);
631}
632
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000633void lcd_jump_scroll (int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
Kjell Ericson53f156a2003-05-22 06:42:14 +0000634{
635 jump_scroll=mode;
636}
637
Mats Lidell4c7f70f2003-01-14 10:45:57 +0000638void lcd_bidir_scroll(int percent)
639{
640 bidir_limit = percent;
641}
642
Jens Arnoldc76c5682004-08-16 23:37:23 +0000643void lcd_puts_scroll(int x, int y, const unsigned char* string )
Björn Stenberg86f9a842002-09-23 11:17:52 +0000644{
Markus Braunbc254fe2002-10-21 13:14:25 +0000645 struct scrollinfo* s;
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000646 int i=0;
647 unsigned short ucs;
648 const unsigned char *utf8 = string;
649 unsigned char tmp[utf8length(string)+1];
650
651 while (*utf8) {
652 utf8 = utf8decode(utf8, &ucs);
653 if (ucs < 256)
654 tmp[i++] = ucs;
655 else
656 tmp[i++] = '?';
657 }
658
659 tmp[i] = 0;
660
Markus Braunbc254fe2002-10-21 13:14:25 +0000661
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000662 DEBUGF("lcd_puts_scroll(%d, %d, %s)\n", x, y, string);
Markus Braunbc254fe2002-10-21 13:14:25 +0000663
Kjell Ericsondd7f2942003-01-10 09:58:04 +0000664 s = &scroll[y];
Markus Braunbc254fe2002-10-21 13:14:25 +0000665
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000666 lcd_puts_cont_scroll(x,y,tmp);
667 s->textlen = strlen(tmp);
Björn Stenberg86f9a842002-09-23 11:17:52 +0000668
Kjell Ericson54c8c712003-01-10 13:22:07 +0000669 if ( s->textlen > 11-x ) {
Markus Braunbc254fe2002-10-21 13:14:25 +0000670 s->mode = SCROLL_MODE_RUN;
Kjell Ericsondc88e232003-01-10 12:23:36 +0000671 s->scroll_start_tick = current_tick + scroll_delay;
Kjell Ericson54c8c712003-01-10 13:22:07 +0000672 s->offset=0;
Björn Stenberg86f9a842002-09-23 11:17:52 +0000673 s->startx=x;
674 s->starty=y;
Kjell Ericson54c8c712003-01-10 13:22:07 +0000675 s->direction=+1;
Kjell Ericson53f156a2003-05-22 06:42:14 +0000676 s->jump_scroll=0;
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000677 s->jump_scroll_steps=0;
Jens Arnold566eae22004-10-15 20:30:29 +0000678 if (jump_scroll && jump_scroll_delay<scroll_ticks*(s->textlen-11+x)) {
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000679 s->jump_scroll_steps=11-x;
680 s->jump_scroll=jump_scroll;
681 }
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000682 strncpy(s->text,tmp,sizeof s->text);
Kjell Ericson54c8c712003-01-10 13:22:07 +0000683 s->turn_offset=-1;
Mats Lidell4c7f70f2003-01-14 10:45:57 +0000684 if (bidir_limit && (s->textlen < ((11-x)*(100+bidir_limit))/100)) {
Kjell Ericsonb1130732003-01-10 14:48:53 +0000685 s->turn_offset=s->textlen+x-11;
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000686 }
687 else {
688 for (i=0; i<scroll_spacing &&
689 s->textlen<(int)sizeof(s->text); i++) {
Kjell Ericsonac984ed2003-01-10 14:45:15 +0000690 s->text[s->textlen++]=' ';
691 }
Kjell Ericson54c8c712003-01-10 13:22:07 +0000692 }
693 if (s->textlen<(int)sizeof(s->text))
694 s->text[s->textlen]=' ';
Björn Stenberg86f9a842002-09-23 11:17:52 +0000695 s->text[sizeof s->text - 1] = 0;
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000696 }
697 else
Kjell Ericsondc88e232003-01-10 12:23:36 +0000698 s->mode = SCROLL_MODE_OFF;
Björn Stenberg86f9a842002-09-23 11:17:52 +0000699}
700
Björn Stenberg86f9a842002-09-23 11:17:52 +0000701void lcd_stop_scroll(void)
702{
Markus Braunbc254fe2002-10-21 13:14:25 +0000703 struct scrollinfo* s;
704 int index;
Björn Stenberg86f9a842002-09-23 11:17:52 +0000705
Markus Braunbc254fe2002-10-21 13:14:25 +0000706 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
707 s = &scroll[index];
708 if ( s->mode == SCROLL_MODE_RUN ||
709 s->mode == SCROLL_MODE_PAUSE ) {
710 /* restore scrolled row */
711 lcd_puts(s->startx, s->starty, s->text);
Markus Braunbc254fe2002-10-21 13:14:25 +0000712 }
Björn Stenberg86f9a842002-09-23 11:17:52 +0000713 }
Markus Braunbc254fe2002-10-21 13:14:25 +0000714
715 lcd_update();
716}
717
Jens Arnold566eae22004-10-15 20:30:29 +0000718static const char scroll_tick_table[16] = {
719 /* Hz values:
720 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
721 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
722};
723
Björn Stenberg86f9a842002-09-23 11:17:52 +0000724void lcd_scroll_speed(int speed)
725{
Jens Arnold566eae22004-10-15 20:30:29 +0000726 scroll_ticks = scroll_tick_table[speed];
Björn Stenberg86f9a842002-09-23 11:17:52 +0000727}
728
Björn Stenberga2e98c12002-12-12 15:20:37 +0000729void lcd_scroll_delay(int ms)
730{
731 scroll_delay = ms / (HZ / 10);
Kjell Ericsondc88e232003-01-10 12:23:36 +0000732 DEBUGF("scroll_delay=%d (ms=%d, HZ=%d)\n", scroll_delay, ms, HZ);
Björn Stenberga2e98c12002-12-12 15:20:37 +0000733}
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000734
735void lcd_jump_scroll_delay(int ms)
736{
737 jump_scroll_delay = ms / (HZ / 10);
738 DEBUGF("jump_scroll_delay=%d (ms=%d, HZ=%d)\n", jump_scroll_delay, ms, HZ);
739}
740
Björn Stenberg86f9a842002-09-23 11:17:52 +0000741static void scroll_thread(void)
742{
Markus Braunbc254fe2002-10-21 13:14:25 +0000743 struct scrollinfo* s;
744 int index;
Kjell Ericson54c8c712003-01-10 13:22:07 +0000745 int i, o;
Markus Braunbc254fe2002-10-21 13:14:25 +0000746 bool update;
747
748 /* initialize scroll struct array */
749 for (index = 0; index < SCROLLABLE_LINES; index++) {
750 scroll[index].mode = SCROLL_MODE_OFF;
751 }
752
Björn Stenberg86f9a842002-09-23 11:17:52 +0000753 while ( 1 ) {
Markus Braunbc254fe2002-10-21 13:14:25 +0000754
755 update = false;
756
Kjell Ericsondc88e232003-01-10 12:23:36 +0000757 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
Kjell Ericson54c8c712003-01-10 13:22:07 +0000758 s = &scroll[index];
759 if ( s->mode == SCROLL_MODE_RUN ) {
760 if ( TIME_AFTER(current_tick, s->scroll_start_tick) ) {
761 char buffer[12];
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000762 int jumping_scroll=s->jump_scroll;
Markus Braunbc254fe2002-10-21 13:14:25 +0000763 update = true;
Kjell Ericson53f156a2003-05-22 06:42:14 +0000764 if (s->jump_scroll) {
Mats Lidell37982492003-08-18 05:27:13 +0000765
766 /* Find new position to start jump scroll by
767 * finding last white space within
768 * jump_scroll_steps */
769 int i;
770 o = s->offset = s->offset + s->jump_scroll_steps;
771 for (i = 0; i < s->jump_scroll_steps; i++, o--) {
772 if (o < s->textlen &&
773 ((0x20 <= s->text[o] && s->text[o] <= 0x2f) || s->text[o] == '_'))
774 {
775 s->offset = o;
776 break;
777 }
778 }
779
Kjell Ericson53f156a2003-05-22 06:42:14 +0000780 s->scroll_start_tick = current_tick +
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000781 jump_scroll_delay;
Kjell Ericson53f156a2003-05-22 06:42:14 +0000782 /* Eat space */
783 while (s->offset < s->textlen &&
Mats Lidell37982492003-08-18 05:27:13 +0000784 ((0x20 <= s->text[s->offset] && s->text[s->offset] <= 0x2f) ||
785 s->text[s->offset] == '_')) {
Kjell Ericson53f156a2003-05-22 06:42:14 +0000786 s->offset++;
Kjell Ericson54c8c712003-01-10 13:22:07 +0000787 }
Kjell Ericson53f156a2003-05-22 06:42:14 +0000788 if (s->offset >= s->textlen) {
789 s->offset=0;
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000790 s->scroll_start_tick = current_tick +
791 scroll_delay;
792 if (s->jump_scroll != JUMP_SCROLL_ALWAYS) {
793 s->jump_scroll--;
Kjell Ericson53f156a2003-05-22 06:42:14 +0000794 s->direction=1;
795 }
796 }
797 } else {
798 if ( s->offset < s->textlen-1 ) {
799 s->offset+=s->direction;
800 if (s->offset==0) {
801 s->direction=+1;
802 s->scroll_start_tick = current_tick +
803 scroll_delay;
804 } else {
805 if (s->offset == s->turn_offset) {
806 s->direction=-1;
807 s->scroll_start_tick = current_tick +
808 scroll_delay;
809 }
810 }
811 }
812 else {
813 s->offset = 0;
814 }
Markus Braunbc254fe2002-10-21 13:14:25 +0000815 }
Kjell Ericson54c8c712003-01-10 13:22:07 +0000816
817 i=0;
818 o=s->offset;
819 while (i<11) {
820 buffer[i++]=s->text[o++];
Mats Lidell37982492003-08-18 05:27:13 +0000821 if (o==s->textlen /* || (jump_scroll && buffer[i-1] == ' ') */)
Kjell Ericson54c8c712003-01-10 13:22:07 +0000822 break;
823 }
824 o=0;
Kjell Ericson6143eeb2003-05-27 12:54:11 +0000825 if (s->turn_offset == -1 && !jumping_scroll) {
Kjell Ericson53f156a2003-05-22 06:42:14 +0000826 while (i<11) {
827 buffer[i++]=s->text[o++];
828 }
829 } else {
830 while (i<11) {
831 buffer[i++]=' ';
832 }
Kjell Ericson54c8c712003-01-10 13:22:07 +0000833 }
834 buffer[11]=0;
Kjell Ericson53f156a2003-05-22 06:42:14 +0000835
Kjell Ericson7f9d7132003-01-22 12:16:14 +0000836 lcd_puts_cont_scroll(s->startx, s->starty, buffer);
Markus Braunbc254fe2002-10-21 13:14:25 +0000837 }
Björn Stenberg86f9a842002-09-23 11:17:52 +0000838 }
Kjell Ericson565505a2003-01-27 14:37:03 +0000839 if (cursor.len>0) {
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000840 if (cursor.downcount--<0) {
841 cursor.downcount=cursor.divider;
842 cursor.textpos++;
843 if (cursor.textpos>=cursor.len)
844 cursor.textpos=0;
Jens Arnoldba4df322005-05-08 13:03:57 +0000845#ifdef SIMULATOR
846 lcdx_putc(cursor.x_pos, cursor.y_pos,
847 cursor.text[cursor.textpos]);
848 update=true;
849#else
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000850 update|=lcdx_putc(cursor.x_pos, cursor.y_pos,
851 cursor.text[cursor.textpos]);
Jens Arnoldba4df322005-05-08 13:03:57 +0000852#endif
Daniel Stenberg0c4a35f2003-01-29 17:31:55 +0000853 }
Kjell Ericson565505a2003-01-27 14:37:03 +0000854 }
Markus Braunbc254fe2002-10-21 13:14:25 +0000855 if (update) {
856 lcd_update();
857 }
Björn Stenberg86f9a842002-09-23 11:17:52 +0000858 }
Markus Braunbc254fe2002-10-21 13:14:25 +0000859
Jens Arnold566eae22004-10-15 20:30:29 +0000860 sleep(scroll_ticks);
Björn Stenberg86f9a842002-09-23 11:17:52 +0000861 }
862}
863
864#endif /* HAVE_LCD_CHARCELLS */