summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/lcd-player.c348
-rw-r--r--firmware/drivers/lcd-recorder.c766
-rw-r--r--firmware/drivers/lcd.c1090
-rw-r--r--firmware/drivers/lcd.h1
4 files changed, 1119 insertions, 1086 deletions
diff --git a/firmware/drivers/lcd-player.c b/firmware/drivers/lcd-player.c
new file mode 100644
index 0000000000..f2a034f8da
--- /dev/null
+++ b/firmware/drivers/lcd-player.c
@@ -0,0 +1,348 @@
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_CHARCELLS
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#if defined(SIMULATOR)
34#include "sim_icons.h"
35#endif
36
37/*** definitions ***/
38
39#ifdef HAVE_NEW_CHARCELL_LCD
40# define LCD_CONTRAST_SET ((char)0x50)
41# define LCD_CRAM ((char)0x80) /* Characters */
42# define LCD_PRAM ((char)0xC0) /* Patterns */
43# define LCD_IRAM ((char)0x40) /* Icons */
44#else
45# define LCD_CONTRAST_SET ((char)0xA8)
46# define LCD_CRAM ((char)0xB0) /* Characters */
47# define LCD_PRAM ((char)0x80) /* Patterns */
48# define LCD_IRAM ((char)0xE0) /* Icons */
49#endif
50#define LCD_CURSOR(x,y) ((char)(LCD_CRAM+((y)*16+(x))))
51#define LCD_ICON(i) ((char)(LCD_IRAM+i))
52
53/*** generic code ***/
54
55struct scrollinfo {
56 char text[MAX_PATH];
57 char line[32];
58 int textlen;
59 int offset;
60 int startx;
61 int starty;
62 int space;
63};
64
65static void scroll_thread(void);
66static char scroll_stack[DEFAULT_STACK_SIZE];
67static char scroll_name[] = "scroll";
68static char scroll_speed = 8; /* updates per second */
69static char scroll_spacing = 3; /* spaces between end and start of text */
70
71
72static struct scrollinfo scroll; /* only one scroll line at the moment */
73static int scroll_count = 0;
74
75#ifdef HAVE_NEW_CHARCELL_LCD
76
77static const unsigned char lcd_ascii[] = {
78 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
79 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
80 0x10,0x11,0x05,0x13,0x14,0x15,0x16,0x17,
81 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
82 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
83 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
84 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
85 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
86 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
87 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
88 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
89 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
90 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
91 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
92 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
93 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
94 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
95 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
96 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
97 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
98 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
99 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
100 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
101 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
102 0x41,0x41,0x41,0x41,0x41,0x41,0x20,0x43,
103 0x45,0x45,0x45,0x45,0x49,0x49,0x49,0x49,
104 0x44,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x20,
105 0x20,0x55,0x55,0x55,0x55,0x59,0x20,0x20,
106 0x61,0x61,0x61,0x61,0x61,0x61,0x20,0x63,
107 0x65,0x65,0x65,0x65,0x69,0x69,0x69,0x69,
108 0x6f,0x6e,0x6f,0x6f,0x6f,0x6f,0x6f,0x20,
109 0x20,0x75,0x75,0x75,0x75,0x79,0x20,0x79
110};
111
112#else
113
114static const unsigned char lcd_ascii[] = {
115 0x00,0x01,0x02,0x03,0x00,0x84,0x85,0x89,
116 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117 0xec,0xe3,0xe2,0xe1,0xe0,0xdf,0x15,0x00,
118 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 0x24,0x25,0x26,0x37,0x06,0x29,0x2a,0x2b,
120 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,
121 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,
122 0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,
123 0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,
124 0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,
125 0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,
126 0x5c,0x5d,0x5e,0xa9,0x33,0xce,0x00,0x15,
127 0x00,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
128 0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
129 0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,
130 0x7c,0x7d,0x7e,0x24,0x24,0x24,0x24,0x24,
131 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
132 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
133 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
134 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
135 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
136 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
137 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
138 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
139 0x45,0x45,0x45,0x45,0x45,0x45,0x24,0x47,
140 0x49,0x49,0x49,0x49,0x4d,0x4d,0x4d,0x4d,
141 0x48,0x52,0x53,0x53,0x53,0x53,0x53,0x24,
142 0x24,0x59,0x59,0x59,0x59,0x5d,0x24,0x24,
143 0x65,0x65,0x65,0x65,0x65,0x65,0x24,0x67,
144 0x69,0x69,0x69,0x69,0x6d,0x6d,0x6d,0x6d,
145 0x73,0x72,0x73,0x73,0x73,0x73,0x73,0x24,
146 0x24,0x79,0x79,0x79,0x79,0x7d,0x24,0x7d
147};
148#endif /* HAVE_NEW_CHARCELL_LCD */
149
150void lcd_clear_display(void)
151{
152 int i;
153 lcd_write(true,LCD_CURSOR(0,0));
154 for (i=0;i<32;i++)
155 lcd_write(false,lcd_ascii[' ']);
156}
157
158void lcd_puts(int x, int y, unsigned char *string)
159{
160 int i;
161 lcd_write(true,LCD_CURSOR(x,y));
162 for (i=0; *string && x++<11; i++)
163 lcd_write(false,lcd_ascii[*(unsigned char*)string++]);
164 for (; x<11; x++)
165 lcd_write(false,lcd_ascii[' ']);
166}
167
168void lcd_putc(int x, int y, unsigned char ch)
169{
170 lcd_write(true,LCD_CURSOR(x,y));
171 lcd_write(false,lcd_ascii[ch]);
172}
173
174void lcd_define_pattern (int which,char *pattern,int length)
175{
176 int i;
177 lcd_write(true,LCD_PRAM|which);
178 for (i=0;i<length;i++)
179 lcd_write(false,pattern[i]);
180}
181
182void lcd_double_height(bool on)
183{
184 lcd_write(true,on?9:8);
185}
186
187static char icon_pos[] =
188{
189 0, 0, 0, 0, /* Battery */
190 2, /* USB */
191 3, /* Play */
192 4, /* Record */
193 5, /* Pause */
194 5, /* Audio */
195 6, /* Repeat */
196 7, /* 1 */
197 9, /* Volume */
198 9, /* Volume 1 */
199 9, /* Volume 2 */
200 10, /* Volume 3 */
201 10, /* Volume 4 */
202 10, /* Volume 5 */
203 10, /* Param */
204};
205
206static char icon_mask[] =
207{
208 0x02, 0x08, 0x04, 0x10, /* Battery */
209 0x04, /* USB */
210 0x10, /* Play */
211 0x10, /* Record */
212 0x02, /* Pause */
213 0x10, /* Audio */
214 0x02, /* Repeat */
215 0x01, /* 1 */
216 0x04, /* Volume */
217 0x02, /* Volume 1 */
218 0x01, /* Volume 2 */
219 0x08, /* Volume 3 */
220 0x04, /* Volume 4 */
221 0x01, /* Volume 5 */
222 0x10, /* Param */
223};
224
225void lcd_icon(int icon, bool enable)
226{
227 static unsigned char icon_mirror[11] = {0};
228 int pos, mask;
229
230 pos = icon_pos[icon];
231 mask = icon_mask[icon];
232
233 lcd_write(true, LCD_ICON(pos));
234
235 if(enable)
236 icon_mirror[pos] |= mask;
237 else
238 icon_mirror[pos] &= ~mask;
239
240 lcd_write(false, icon_mirror[pos]);
241}
242
243void lcd_init (void)
244{
245 create_thread(scroll_thread, scroll_stack,
246 sizeof(scroll_stack), scroll_name);
247}
248
249void lcd_set_contrast(int val)
250{
251 lcd_write(true, LCD_CONTRAST_SET);
252 lcd_write(false, 31-val);
253}
254
255void lcd_puts_scroll(int x, int y, unsigned char* string )
256{
257 struct scrollinfo* s = &scroll;
258 s->space = 11 - x;
259
260 lcd_puts(x,y,string);
261 s->textlen = strlen(string);
262
263 if ( s->textlen > s->space ) {
264 s->offset=s->space;
265 s->startx=x;
266 s->starty=y;
267 strncpy(s->text,string,sizeof s->text);
268 s->text[sizeof s->text - 1] = 0;
269 memset(s->line, 0, sizeof s->line);
270 strncpy(s->line,string,
271 s->space > (int)sizeof s->line ?
272 (int)sizeof s->line : s->space );
273 s->line[sizeof s->line - 1] = 0;
274 scroll_count = 1;
275 }
276}
277
278
279void lcd_stop_scroll(void)
280{
281 if ( scroll_count ) {
282 struct scrollinfo* s = &scroll;
283 scroll_count = 0;
284
285 /* restore scrolled row */
286 lcd_puts(s->startx,s->starty,s->text);
287 lcd_update();
288 }
289}
290
291void lcd_scroll_pause(void)
292{
293 scroll_count = 0;
294}
295
296void lcd_scroll_resume(void)
297{
298 scroll_count = 1;
299}
300
301void lcd_scroll_speed(int speed)
302{
303 scroll_speed = speed;
304}
305
306static void scroll_thread(void)
307{
308 struct scrollinfo* s = &scroll;
309
310 while ( 1 ) {
311 if ( !scroll_count ) {
312 yield();
313 continue;
314 }
315 /* wait 0.5s before starting scroll */
316 if ( scroll_count < scroll_speed/2 )
317 scroll_count++;
318 else {
319 int i;
320 for ( i=0; i<s->space-1; i++ )
321 s->line[i] = s->line[i+1];
322
323 if ( s->offset < s->textlen ) {
324 s->line[(int)s->space - 1] = s->text[(int)s->offset];
325 s->offset++;
326 }
327 else {
328 s->line[s->space - 1] = ' ';
329 if ( s->offset < s->textlen + scroll_spacing - 1 )
330 s->offset++;
331 else
332 s->offset = 0;
333 }
334
335 lcd_puts(s->startx,s->starty,s->line);
336 lcd_update();
337 }
338 sleep(HZ/scroll_speed);
339 }
340}
341
342#endif /* HAVE_LCD_CHARCELLS */
343
344/* -----------------------------------------------------------------
345 * local variables:
346 * eval: (load-file "../rockbox-mode.el")
347 * end:
348 */
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c
new file mode 100644
index 0000000000..9f19bb89f0
--- /dev/null
+++ b/firmware/drivers/lcd-recorder.c
@@ -0,0 +1,766 @@
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
71struct scrollinfo {
72 char text[MAX_PATH];
73 char line[32];
74 int textlen;
75 int offset;
76 int startx;
77 int starty;
78 int space;
79};
80
81static void scroll_thread(void);
82static char scroll_stack[DEFAULT_STACK_SIZE];
83static char scroll_name[] = "scroll";
84static char scroll_speed = 8; /* updates per second */
85static char scroll_spacing = 3; /* spaces between end and start of text */
86static struct scrollinfo scroll; /* only one scroll line at the moment */
87static int scroll_count = 0;
88static int xmargin = 0;
89static int ymargin = 0;
90static int curfont = FONT_SYSFIXED;
91
92#ifdef SIMULATOR
93unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
94#else
95static unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
96#endif
97
98/* All zeros and ones bitmaps for area filling */
99static unsigned char zeros[8] = { 0 };
100static unsigned char ones[8] = { 0xff };
101
102#ifdef SIMULATOR
103
104void lcd_init(void)
105{
106 create_thread(scroll_thread, scroll_stack,
107 sizeof(scroll_stack), scroll_name);
108}
109
110#else
111
112/*
113 * Initialize LCD
114 */
115void lcd_init (void)
116{
117 /* Initialize PB0-3 as output pins */
118 PBCR2 &= 0xff00; /* MD = 00 */
119 PBIOR |= 0x000f; /* IOR = 1 */
120
121 lcd_clear_display();
122 lcd_update();
123 create_thread(scroll_thread, scroll_stack,
124 sizeof(scroll_stack), scroll_name);
125}
126
127/*
128 * Update the display.
129 * This must be called after all other LCD functions that change the display.
130 */
131void lcd_update (void) __attribute__ ((section (".icode")));
132void lcd_update (void)
133{
134 int x, y;
135
136 /* Copy display bitmap to hardware */
137 for (y = 0; y < LCD_HEIGHT/8; y++)
138 {
139 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf));
140 lcd_write (true, LCD_CNTL_HIGHCOL);
141 lcd_write (true, LCD_CNTL_LOWCOL);
142
143 for (x = 0; x < LCD_WIDTH; x++)
144 lcd_write (false, lcd_framebuffer[x][y]);
145 }
146}
147
148/*
149 * Update a fraction of the display.
150 */
151void lcd_update_rect (int, int, int, int) __attribute__ ((section (".icode")));
152void lcd_update_rect (int x_start, int y,
153 int width, int height)
154{
155 int ymax;
156 int xmax;
157 int x;
158
159 /* The Y coordinates have to work on even 8 pixel rows */
160 ymax = (y + height)/8;
161 y /= 8;
162
163 xmax = x_start + width;
164
165 if(xmax > LCD_WIDTH)
166 xmax = LCD_WIDTH;
167 if(ymax >= LCD_HEIGHT/8)
168 ymax = LCD_HEIGHT/8-1;
169
170 /* Copy specified rectange bitmap to hardware */
171 for (; y <= ymax; y++)
172 {
173 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf));
174 lcd_write (true, LCD_CNTL_HIGHCOL | ((x_start>>4) & 0xf));
175 lcd_write (true, LCD_CNTL_LOWCOL | (x_start & 0xf));
176
177 for (x = x_start; x < xmax; x++)
178 lcd_write (false, lcd_framebuffer[x][y]);
179 }
180}
181
182void lcd_set_contrast(int val)
183{
184 lcd_write(true, LCD_CNTL_CONTRAST);
185 lcd_write(true, val);
186}
187
188/**
189 * Rolls up the lcd display by the specified amount of lines.
190 * Lines that are rolled out over the top of the screen are
191 * rolled in from the bottom again. This is a hardware
192 * remapping only and all operations on the lcd are affected.
193 * ->
194 * @param int lines - The number of lines that are rolled.
195 * The value must be 0 <= pixels < LCD_HEIGHT.
196 */
197void lcd_roll(int lines)
198{
199 lcd_write(true, LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1)));
200}
201
202#endif /* SIMULATOR */
203
204void lcd_clear_display (void)
205{
206 memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
207}
208
209void lcd_setmargins(int x, int y)
210{
211 xmargin = x;
212 ymargin = y;
213}
214
215int lcd_getxmargin(void)
216{
217 return xmargin;
218}
219
220int lcd_getymargin(void)
221{
222 return ymargin;
223}
224
225void lcd_setfont(int newfont)
226{
227 curfont = newfont;
228}
229
230void lcd_getfontsize(int font, int *width, int *height)
231{
232 struct font* pf = font_get(font);
233
234 *width = pf->maxwidth;
235 *height = pf->height;
236}
237
238int lcd_getstringsize(unsigned char *str, int font, int *w, int *h)
239{
240 struct font* pf = font_get(font);
241 int ch;
242 int width = 0;
243
244 while((ch = *str++)) {
245 /* check input range*/
246 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
247 ch = pf->defaultchar;
248 ch -= pf->firstchar;
249
250 /* get proportional width and glyph bits*/
251 width += pf->width? pf->width[ch]: pf->maxwidth;
252 }
253 *w = width;
254 *h = pf->height;
255
256 return width;
257}
258
259/* put a string at a given char position */
260void lcd_puts(int x, int y, unsigned char *str)
261{
262 int xpos,ypos,w,h;
263
264#if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
265 /* We make the simulator truncate the string if it reaches the right edge,
266 as otherwise it'll wrap. The real target doesn't wrap. */
267
268 char buffer[12];
269 if(strlen(str)+x > 11 ) {
270 strncpy(buffer, str, sizeof buffer);
271 buffer[11-x]=0;
272 str = buffer;
273 }
274 xmargin = 0;
275 ymargin = 8;
276#endif
277
278 if(!str || !str[0])
279 return;
280
281 lcd_getstringsize(str, curfont, &w, &h);
282 xpos = xmargin + x*w / strlen(str);
283 ypos = ymargin + y*h;
284 lcd_putsxy( xpos, ypos, str, curfont);
285 lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h);
286
287#if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
288 /* this function is being used when simulating a charcell LCD and
289 then we update immediately */
290 lcd_update();
291#endif
292}
293
294/* put a string at a given pixel position */
295void lcd_putsxy(int x, int y, unsigned char *str, int font)
296{
297 int ch;
298 struct font* pf = font_get(font);
299
300 while (((ch = *str++) != '\0')) {
301 bitmap_t *bits;
302 int width;
303
304 /* check input range*/
305 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
306 ch = pf->defaultchar;
307 ch -= pf->firstchar;
308
309 /* get proportional width and glyph bits*/
310 width = pf->width ? pf->width[ch] : pf->maxwidth;
311 if (x + width > LCD_WIDTH)
312 break;
313
314 /* no partial-height drawing for now...*/
315 if (y + pf->height > LCD_HEIGHT)
316 break;
317 bits = pf->bits + (pf->offset ? pf->offset[ch] : (pf->height * ch));
318
319 lcd_bitmap((unsigned char *)bits, x, y, width, pf->height, true);
320 x += width;
321 }
322}
323
324/*
325 * All bitmaps have this format:
326 * Bits within a byte are arranged veritcally, LSB at top.
327 * Bytes are stored in column-major format, with byte 0 at top left,
328 * byte 1 is 2nd from top, etc. Bytes following left-most column
329 * starts 2nd left column, etc.
330 *
331 * Note: The HW takes bitmap bytes in row-major order.
332 *
333 * Memory copy of display bitmap
334 */
335
336/*
337 * Draw a bitmap at (x, y), size (nx, ny)
338 * if 'clear' is true, clear destination area first
339 */
340void lcd_bitmap (unsigned char *src, int x, int y, int nx, int ny,
341 bool clear) __attribute__ ((section (".icode")));
342void lcd_bitmap (unsigned char *src, int x, int y, int nx, int ny,
343 bool clear)
344{
345 unsigned char *dst;
346 unsigned char *dst2;
347 unsigned int data, mask, mask2, mask3, mask4;
348 int shift;
349
350 if (((unsigned)x >= LCD_WIDTH) || ((unsigned)y >= LCD_HEIGHT))
351 return;
352 if (((unsigned)(x + nx)) >= LCD_WIDTH)
353 nx = LCD_WIDTH - x;
354 if (((unsigned)(y + ny)) >= LCD_HEIGHT)
355 ny = LCD_HEIGHT - y;
356
357 shift = y & 7;
358 dst2 = &lcd_framebuffer[x][y/8];
359 ny += shift;
360
361 /* Calculate bit masks */
362 mask4 = ~(0xfe << ((ny-1) & 7));
363 if (clear)
364 {
365 mask = ~(0xff << shift);
366 mask2 = 0;
367 mask3 = ~mask4;
368 if (ny <= 8)
369 mask3 |= mask;
370 }
371 else
372 mask = mask2 = mask3 = 0xff;
373
374 /* Loop for each column */
375 for (x = 0; x < nx; x++)
376 {
377 dst = dst2;
378 dst2 += LCD_HEIGHT/8;
379 data = 0;
380 y = 0;
381
382 if (ny > 8)
383 {
384 /* First partial row */
385 data = *src++ << shift;
386 *dst = (*dst & mask) | data;
387 data >>= 8;
388 dst++;
389
390 /* Intermediate rows */
391 for (y = 8; y < ny-8; y += 8)
392 {
393 data |= *src++ << shift;
394 *dst = (*dst & mask2) | data;
395 data >>= 8;
396 dst++;
397 }
398 }
399
400 /* Last partial row */
401 if (y + shift < ny)
402 data |= *src++ << shift;
403 *dst = (*dst & mask3) | (data & mask4);
404 }
405}
406
407/*
408 * Draw a rectangle with upper left corner at (x, y)
409 * and size (nx, ny)
410 */
411void lcd_drawrect (int x, int y, int nx, int ny)
412{
413 int i;
414
415 if (x > LCD_WIDTH)
416 return;
417 if (y > LCD_HEIGHT)
418 return;
419
420 if (x + nx > LCD_WIDTH)
421 nx = LCD_WIDTH - x;
422 if (y + ny > LCD_HEIGHT)
423 ny = LCD_HEIGHT - y;
424
425 /* vertical lines */
426 for (i = 0; i < ny; i++) {
427 DRAW_PIXEL(x, (y + i));
428 DRAW_PIXEL((x + nx - 1), (y + i));
429 }
430
431 /* horizontal lines */
432 for (i = 0; i < nx; i++) {
433 DRAW_PIXEL((x + i),y);
434 DRAW_PIXEL((x + i),(y + ny - 1));
435 }
436}
437
438/*
439 * Clear a rectangular area at (x, y), size (nx, ny)
440 */
441void lcd_clearrect (int x, int y, int nx, int ny)
442{
443 int i;
444 for (i = 0; i < nx; i++)
445 lcd_bitmap (zeros, x+i, y, 1, ny, true);
446}
447
448/*
449 * Fill a rectangular area at (x, y), size (nx, ny)
450 */
451void lcd_fillrect (int x, int y, int nx, int ny)
452{
453 int i;
454 for (i = 0; i < nx; i++)
455 lcd_bitmap (ones, x+i, y, 1, ny, true);
456}
457
458/* Invert a rectangular area at (x, y), size (nx, ny) */
459void lcd_invertrect (int x, int y, int nx, int ny)
460{
461 int i, j;
462
463 if (x > LCD_WIDTH)
464 return;
465 if (y > LCD_HEIGHT)
466 return;
467
468 if (x + nx > LCD_WIDTH)
469 nx = LCD_WIDTH - x;
470 if (y + ny > LCD_HEIGHT)
471 ny = LCD_HEIGHT - y;
472
473 for (i = 0; i < nx; i++)
474 for (j = 0; j < ny; j++)
475 INVERT_PIXEL((x + i), (y + j));
476}
477
478void lcd_drawline( int x1, int y1, int x2, int y2 )
479{
480 int numpixels;
481 int i;
482 int deltax, deltay;
483 int d, dinc1, dinc2;
484 int x, xinc1, xinc2;
485 int y, yinc1, yinc2;
486
487 deltax = abs(x2 - x1);
488 deltay = abs(y2 - y1);
489
490 if(deltax >= deltay)
491 {
492 numpixels = deltax;
493 d = 2 * deltay - deltax;
494 dinc1 = deltay * 2;
495 dinc2 = (deltay - deltax) * 2;
496 xinc1 = 1;
497 xinc2 = 1;
498 yinc1 = 0;
499 yinc2 = 1;
500 }
501 else
502 {
503 numpixels = deltay;
504 d = 2 * deltax - deltay;
505 dinc1 = deltax * 2;
506 dinc2 = (deltax - deltay) * 2;
507 xinc1 = 0;
508 xinc2 = 1;
509 yinc1 = 1;
510 yinc2 = 1;
511 }
512 numpixels++; /* include endpoints */
513
514 if(x1 > x2)
515 {
516 xinc1 = -xinc1;
517 xinc2 = -xinc2;
518 }
519
520 if(y1 > y2)
521 {
522 yinc1 = -yinc1;
523 yinc2 = -yinc2;
524 }
525
526 x = x1;
527 y = y1;
528
529 for(i=0; i<numpixels; i++)
530 {
531 DRAW_PIXEL(x,y);
532
533 if(d < 0)
534 {
535 d += dinc1;
536 x += xinc1;
537 y += yinc1;
538 }
539 else
540 {
541 d += dinc2;
542 x += xinc2;
543 y += yinc2;
544 }
545 }
546}
547
548void lcd_clearline( int x1, int y1, int x2, int y2 )
549{
550 int numpixels;
551 int i;
552 int deltax, deltay;
553 int d, dinc1, dinc2;
554 int x, xinc1, xinc2;
555 int y, yinc1, yinc2;
556
557 deltax = abs(x2 - x1);
558 deltay = abs(y2 - y1);
559
560 if(deltax >= deltay)
561 {
562 numpixels = deltax;
563 d = 2 * deltay - deltax;
564 dinc1 = deltay * 2;
565 dinc2 = (deltay - deltax) * 2;
566 xinc1 = 1;
567 xinc2 = 1;
568 yinc1 = 0;
569 yinc2 = 1;
570 }
571 else
572 {
573 numpixels = deltay;
574 d = 2 * deltax - deltay;
575 dinc1 = deltax * 2;
576 dinc2 = (deltax - deltay) * 2;
577 xinc1 = 0;
578 xinc2 = 1;
579 yinc1 = 1;
580 yinc2 = 1;
581 }
582 numpixels++; /* include endpoints */
583
584 if(x1 > x2)
585 {
586 xinc1 = -xinc1;
587 xinc2 = -xinc2;
588 }
589
590 if(y1 > y2)
591 {
592 yinc1 = -yinc1;
593 yinc2 = -yinc2;
594 }
595
596 x = x1;
597 y = y1;
598
599 for(i=0; i<numpixels; i++)
600 {
601 CLEAR_PIXEL(x,y);
602
603 if(d < 0)
604 {
605 d += dinc1;
606 x += xinc1;
607 y += yinc1;
608 }
609 else
610 {
611 d += dinc2;
612 x += xinc2;
613 y += yinc2;
614 }
615 }
616}
617
618/*
619 * Set a single pixel
620 */
621void lcd_drawpixel(int x, int y)
622{
623 DRAW_PIXEL(x,y);
624}
625
626/*
627 * Clear a single pixel
628 */
629void lcd_clearpixel(int x, int y)
630{
631 CLEAR_PIXEL(x,y);
632}
633
634/*
635 * Invert a single pixel
636 */
637void lcd_invertpixel(int x, int y)
638{
639 INVERT_PIXEL(x,y);
640}
641
642void lcd_puts_scroll(int x, int y, unsigned char* string )
643{
644 struct scrollinfo* s = &scroll;
645 unsigned char ch[2];
646 int w, h;
647 int width, height;
648 lcd_getfontsize(curfont, &width, &height);
649
650 ch[1] = 0; /* zero terminate */
651 ch[0] = string[0];
652 width = 0;
653 s->space = 0;
654 while ( ch[0] &&
655 (width + lcd_getstringsize(ch, curfont, &w, &h) <
656 (LCD_WIDTH - x*8))) {
657 width += w;
658 s->space++;
659 ch[0]=string[s->space];
660 }
661
662 lcd_puts(x,y,string);
663 s->textlen = strlen(string);
664
665 s->space += 2;
666 lcd_getstringsize(string,curfont,&w,&h);
667 if ( w > LCD_WIDTH - xmargin ) {
668 s->offset=s->space;
669 s->startx=x;
670 s->starty=y;
671 strncpy(s->text,string,sizeof s->text);
672 s->text[sizeof s->text - 1] = 0;
673 memset(s->line, 0, sizeof s->line);
674 strncpy(s->line,string,
675 s->space > (int)sizeof s->line ?
676 (int)sizeof s->line : s->space );
677 s->line[sizeof s->line - 1] = 0;
678 scroll_count = 1;
679 }
680}
681
682
683void lcd_stop_scroll(void)
684{
685 if ( scroll_count ) {
686 int w,h;
687 struct scrollinfo* s = &scroll;
688 scroll_count = 0;
689
690 lcd_getstringsize( s->text, FONT_UI, &w, &h);
691 lcd_clearrect(xmargin + s->startx*w/s->textlen,
692 ymargin + s->starty*h,
693 LCD_WIDTH - xmargin,
694 h);
695
696 /* restore scrolled row */
697 lcd_puts(s->startx,s->starty,s->text);
698 lcd_update();
699 }
700}
701
702void lcd_scroll_pause(void)
703{
704 scroll_count = 0;
705}
706
707void lcd_scroll_resume(void)
708{
709 scroll_count = 1;
710}
711
712void lcd_scroll_speed(int speed)
713{
714 scroll_speed = speed;
715}
716
717static void scroll_thread(void)
718{
719 struct scrollinfo* s = &scroll;
720
721 while ( 1 ) {
722 if ( !scroll_count ) {
723 yield();
724 continue;
725 }
726 /* wait 0.5s before starting scroll */
727 if ( scroll_count < scroll_speed/2 )
728 scroll_count++;
729 else {
730 int i;
731 int w, h;
732 for ( i=0; i<s->space-1; i++ )
733 s->line[i] = s->line[i+1];
734
735 if ( s->offset < s->textlen ) {
736 s->line[(int)s->space - 1] = s->text[(int)s->offset];
737 s->offset++;
738 }
739 else {
740 s->line[s->space - 1] = ' ';
741 if ( s->offset < s->textlen + scroll_spacing - 1 )
742 s->offset++;
743 else
744 s->offset = 0;
745 }
746
747 lcd_getstringsize( s->text, FONT_UI, &w, &h);
748 lcd_clearrect(xmargin + s->startx*w/s->textlen,
749 ymargin + s->starty*h,
750 LCD_WIDTH - xmargin,
751 h);
752
753 lcd_puts(s->startx,s->starty,s->line);
754 lcd_update();
755 }
756 sleep(HZ/scroll_speed);
757 }
758}
759
760#endif
761
762/* -----------------------------------------------------------------
763 * local variables:
764 * eval: (load-file "../rockbox-mode.el")
765 * end:
766 */
diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c
index 2293191139..38dbe3cc2c 100644
--- a/firmware/drivers/lcd.c
+++ b/firmware/drivers/lcd.c
@@ -17,116 +17,24 @@
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19 19
20#include "config.h" 20#include <stdbool.h>
21#include "lcd.h"
22#include "kernel.h"
23#include "thread.h"
24#include <string.h>
25#include <stdlib.h>
26#include "file.h"
27#include "debug.h"
28#include "system.h" 21#include "system.h"
29#include "font.h"
30
31#if defined(SIMULATOR)
32#include "sim_icons.h"
33#endif
34
35/*** definitions ***/
36 22
37#define LCDR (PBDR_ADDR+1) 23#define LCDR (PBDR_ADDR+1)
38 24
39#ifdef HAVE_LCD_CHARCELLS 25#ifdef HAVE_LCD_CHARCELLS
40
41#define LCD_DS 1 // PB0 = 1 --- 0001 --- LCD-DS 26#define LCD_DS 1 // PB0 = 1 --- 0001 --- LCD-DS
42#define LCD_CS 2 // PB1 = 1 --- 0010 --- /LCD-CS 27#define LCD_CS 2 // PB1 = 1 --- 0010 --- /LCD-CS
43#define LCD_SD 4 // PB2 = 1 --- 0100 --- LCD-SD 28#define LCD_SD 4 // PB2 = 1 --- 0100 --- LCD-SD
44#define LCD_SC 8 // PB3 = 1 --- 1000 --- LCD-SC 29#define LCD_SC 8 // PB3 = 1 --- 1000 --- LCD-SC
45#ifdef HAVE_NEW_CHARCELL_LCD
46# define LCD_CONTRAST_SET ((char)0x50)
47# define LCD_CRAM ((char)0x80) /* Characters */
48# define LCD_PRAM ((char)0xC0) /* Patterns */
49# define LCD_IRAM ((char)0x40) /* Icons */
50#else 30#else
51# define LCD_CONTRAST_SET ((char)0xA8)
52# define LCD_CRAM ((char)0xB0) /* Characters */
53# define LCD_PRAM ((char)0x80) /* Patterns */
54# define LCD_IRAM ((char)0xE0) /* Icons */
55#endif
56#define LCD_CURSOR(x,y) ((char)(LCD_CRAM+((y)*16+(x))))
57#define LCD_ICON(i) ((char)(LCD_IRAM+i))
58
59#elif HAVE_LCD_BITMAP
60
61#define LCD_SD 1 // PB0 = 1 --- 0001 31#define LCD_SD 1 // PB0 = 1 --- 0001
62#define LCD_SC 2 // PB1 = 1 --- 0010 32#define LCD_SC 2 // PB1 = 1 --- 0010
63#define LCD_RS 4 // PB2 = 1 --- 0100 33#define LCD_RS 4 // PB2 = 1 --- 0100
64#define LCD_CS 8 // PB3 = 1 --- 1000 34#define LCD_CS 8 // PB3 = 1 --- 1000
65#define LCD_DS LCD_RS 35#define LCD_DS LCD_RS
36#endif
66 37
67#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00)
68#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10)
69#define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20)
70#define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28)
71#define LCD_SET_DISPLAY_START_LINE ((char)0x40)
72#define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81)
73#define LCD_SET_SEGMENT_REMAP ((char)0xA0)
74#define LCD_SET_LCD_BIAS ((char)0xA2)
75#define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4)
76#define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5)
77#define LCD_SET_NORMAL_DISPLAY ((char)0xA6)
78#define LCD_SET_REVERSE_DISPLAY ((char)0xA7)
79#define LCD_SET_INDICATOR_OFF ((char)0xAC)
80#define LCD_SET_INDICATOR_ON ((char)0xAD)
81#define LCD_SET_DISPLAY_OFF ((char)0xAE)
82#define LCD_SET_DISPLAY_ON ((char)0xAF)
83#define LCD_SET_PAGE_ADDRESS ((char)0xB0)
84#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0)
85#define LCD_SET_DISPLAY_OFFSET ((char)0xD3)
86#define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0)
87#define LCD_SOFTWARE_RESET ((char)0xE2)
88#define LCD_NOP ((char)0xE3)
89#define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE)
90
91/* LCD command codes */
92#define LCD_CNTL_RESET 0xe2 // Software reset
93#define LCD_CNTL_POWER 0x2f // Power control
94#define LCD_CNTL_CONTRAST 0x81 // Contrast
95#define LCD_CNTL_OUTSCAN 0xc8 // Output scan direction
96#define LCD_CNTL_SEGREMAP 0xa1 // Segment remap
97#define LCD_CNTL_DISPON 0xaf // Display on
98
99#define LCD_CNTL_PAGE 0xb0 // Page address
100#define LCD_CNTL_HIGHCOL 0x10 // Upper column address
101#define LCD_CNTL_LOWCOL 0x00 // Lower column address
102
103
104#endif /* CHARCELL or BITMAP */
105
106
107/*** generic code ***/
108
109struct scrollinfo {
110 char text[MAX_PATH];
111 char line[32];
112 int textlen;
113 int offset;
114 int startx;
115 int starty;
116 int space;
117};
118
119static void scroll_thread(void);
120static char scroll_stack[DEFAULT_STACK_SIZE];
121static char scroll_name[] = "scroll";
122static char scroll_speed = 8; /* updates per second */
123static char scroll_spacing = 3; /* spaces between end and start of text */
124
125
126static struct scrollinfo scroll; /* only one scroll line at the moment */
127static int scroll_count = 0;
128
129#ifndef SIMULATOR
130/* 38/*
131 * About /CS,DS,SC,SD 39 * About /CS,DS,SC,SD
132 * ------------------ 40 * ------------------
@@ -174,12 +82,8 @@ static int scroll_count = 0;
174 * 82 *
175 */ 83 */
176 84
177#define ASM_IMPLEMENTATION 85void lcd_write(bool command, int byte) __attribute__ ((section (".icode")));
178 86void lcd_write(bool command, int byte)
179static void lcd_write(bool command, int byte) __attribute__ ((section (".icode")));
180static void lcd_write(bool command, int byte)
181
182#ifdef ASM_IMPLEMENTATION
183{ 87{
184 asm("and.b %0, @(r0,gbr)" 88 asm("and.b %0, @(r0,gbr)"
185 : 89 :
@@ -206,26 +110,6 @@ static void lcd_write(bool command, int byte)
206 /* %4 */ "I"(LCD_SC), 110 /* %4 */ "I"(LCD_SC),
207 /* %5 */ "z"(LCDR)); 111 /* %5 */ "z"(LCDR));
208 else 112 else
209#if 0
210 asm ("shll8 %0\n"
211 "0: \n\t"
212 "and.b %2, @(r0,gbr)\n\t"
213 "shll %0\n\t"
214 "bf 1f\n\t"
215 "or.b %3, @(r0,gbr)\n"
216 "1: \n\t"
217 "or.b %4, @(r0,gbr)\n"
218 "add #-1, %1\n\t"
219 "cmp/pl %1\n\t"
220 "bt 0b"
221 :
222 : /* %0 */ "r"(((unsigned)byte)<<16),
223 /* %1 */ "r"(8),
224 /* %2 */ "I"(~(LCD_SC|LCD_SD)),
225 /* %3 */ "I"(LCD_SD|LCD_DS),
226 /* %4 */ "I"(LCD_SC|LCD_DS),
227 /* %5 */ "z"(LCDR));
228#else
229 asm ("shll8 %0\n" 113 asm ("shll8 %0\n"
230 "0: \n\t" 114 "0: \n\t"
231 "and.b %2, @(r0,gbr)\n\t" 115 "and.b %2, @(r0,gbr)\n\t"
@@ -283,975 +167,9 @@ static void lcd_write(bool command, int byte)
283 /* %3 */ "I"(LCD_SD|LCD_DS), 167 /* %3 */ "I"(LCD_SD|LCD_DS),
284 /* %4 */ "I"(LCD_SC|LCD_DS), 168 /* %4 */ "I"(LCD_SC|LCD_DS),
285 /* %5 */ "z"(LCDR)); 169 /* %5 */ "z"(LCDR));
286#endif
287 170
288 asm("or.b %0, @(r0,gbr)" 171 asm("or.b %0, @(r0,gbr)"
289 : 172 :
290 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC), 173 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC),
291 /* %1 */ "z"(LCDR)); 174 /* %1 */ "z"(LCDR));
292} 175}
293#else
294{
295 int i;
296 char on,off;
297
298 PBDR &= ~LCD_CS; /* enable lcd chip select */
299
300 if ( command ) {
301 on=~(LCD_SD|LCD_SC|LCD_DS);
302 off=LCD_SC;
303 }
304 else {
305 on=~(LCD_SD|LCD_SC);
306 off=LCD_SC|LCD_DS;
307 }
308
309 /* clock out each bit, MSB first */
310 for (i=0x80;i;i>>=1)
311 {
312 PBDR &= on;
313 if (i & byte)
314 PBDR |= LCD_SD;
315 PBDR |= off;
316 }
317
318 PBDR |= LCD_CS; /* disable lcd chip select */
319}
320#endif /* ASM_IMPLEMENTATION */
321#endif /* !SIMULATOR */
322
323/*** model specific code */
324
325#ifdef HAVE_LCD_CHARCELLS
326
327#ifdef HAVE_NEW_CHARCELL_LCD
328
329static const unsigned char lcd_ascii[] = {
330 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
331 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
332 0x10,0x11,0x05,0x13,0x14,0x15,0x16,0x17,
333 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
334 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
335 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
336 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
337 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
338 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
339 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
340 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
341 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
342 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
343 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
344 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
345 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
346 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
347 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
348 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
349 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
350 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
351 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
352 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
353 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
354 0x41,0x41,0x41,0x41,0x41,0x41,0x20,0x43,
355 0x45,0x45,0x45,0x45,0x49,0x49,0x49,0x49,
356 0x44,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x20,
357 0x20,0x55,0x55,0x55,0x55,0x59,0x20,0x20,
358 0x61,0x61,0x61,0x61,0x61,0x61,0x20,0x63,
359 0x65,0x65,0x65,0x65,0x69,0x69,0x69,0x69,
360 0x6f,0x6e,0x6f,0x6f,0x6f,0x6f,0x6f,0x20,
361 0x20,0x75,0x75,0x75,0x75,0x79,0x20,0x79
362};
363
364#else
365
366static const unsigned char lcd_ascii[] = {
367 0x00,0x01,0x02,0x03,0x00,0x84,0x85,0x89,
368 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
369 0xec,0xe3,0xe2,0xe1,0xe0,0xdf,0x15,0x00,
370 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
371 0x24,0x25,0x26,0x37,0x06,0x29,0x2a,0x2b,
372 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,
373 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,
374 0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,
375 0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,
376 0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,
377 0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,
378 0x5c,0x5d,0x5e,0xa9,0x33,0xce,0x00,0x15,
379 0x00,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
380 0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
381 0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,
382 0x7c,0x7d,0x7e,0x24,0x24,0x24,0x24,0x24,
383 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
384 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
385 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
386 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
387 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
388 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
389 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
390 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
391 0x45,0x45,0x45,0x45,0x45,0x45,0x24,0x47,
392 0x49,0x49,0x49,0x49,0x4d,0x4d,0x4d,0x4d,
393 0x48,0x52,0x53,0x53,0x53,0x53,0x53,0x24,
394 0x24,0x59,0x59,0x59,0x59,0x5d,0x24,0x24,
395 0x65,0x65,0x65,0x65,0x65,0x65,0x24,0x67,
396 0x69,0x69,0x69,0x69,0x6d,0x6d,0x6d,0x6d,
397 0x73,0x72,0x73,0x73,0x73,0x73,0x73,0x24,
398 0x24,0x79,0x79,0x79,0x79,0x7d,0x24,0x7d
399};
400#endif /* HAVE_NEW_CHARCELL_LCD */
401
402#ifndef SIMULATOR
403void lcd_clear_display(void)
404{
405 int i;
406 lcd_write(true,LCD_CURSOR(0,0));
407 for (i=0;i<32;i++)
408 lcd_write(false,lcd_ascii[' ']);
409}
410
411void lcd_puts(int x, int y, unsigned char *string)
412{
413 int i;
414 lcd_write(true,LCD_CURSOR(x,y));
415 for (i=0; *string && x++<11; i++)
416 lcd_write(false,lcd_ascii[*(unsigned char*)string++]);
417 for (; x<11; x++)
418 lcd_write(false,lcd_ascii[' ']);
419}
420
421void lcd_putc(int x, int y, unsigned char ch)
422{
423 lcd_write(true,LCD_CURSOR(x,y));
424 lcd_write(false,lcd_ascii[ch]);
425}
426
427void lcd_define_pattern (int which,char *pattern,int length)
428{
429 int i;
430 lcd_write(true,LCD_PRAM|which);
431 for (i=0;i<length;i++)
432 lcd_write(false,pattern[i]);
433}
434
435void lcd_double_height(bool on)
436{
437 lcd_write(true,on?9:8);
438}
439
440static char icon_pos[] =
441{
442 0, 0, 0, 0, /* Battery */
443 2, /* USB */
444 3, /* Play */
445 4, /* Record */
446 5, /* Pause */
447 5, /* Audio */
448 6, /* Repeat */
449 7, /* 1 */
450 9, /* Volume */
451 9, /* Volume 1 */
452 9, /* Volume 2 */
453 10, /* Volume 3 */
454 10, /* Volume 4 */
455 10, /* Volume 5 */
456 10, /* Param */
457};
458
459static char icon_mask[] =
460{
461 0x02, 0x08, 0x04, 0x10, /* Battery */
462 0x04, /* USB */
463 0x10, /* Play */
464 0x10, /* Record */
465 0x02, /* Pause */
466 0x10, /* Audio */
467 0x02, /* Repeat */
468 0x01, /* 1 */
469 0x04, /* Volume */
470 0x02, /* Volume 1 */
471 0x01, /* Volume 2 */
472 0x08, /* Volume 3 */
473 0x04, /* Volume 4 */
474 0x01, /* Volume 5 */
475 0x10, /* Param */
476};
477
478void lcd_icon(int icon, bool enable)
479{
480 static unsigned char icon_mirror[11] = {0};
481 int pos, mask;
482
483 pos = icon_pos[icon];
484 mask = icon_mask[icon];
485
486 lcd_write(true, LCD_ICON(pos));
487
488 if(enable)
489 icon_mirror[pos] |= mask;
490 else
491 icon_mirror[pos] &= ~mask;
492
493 lcd_write(false, icon_mirror[pos]);
494}
495#endif /* !SIMULATOR */
496
497#endif /* HAVE_LCD_CHARCELLS */
498
499#if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
500void lcd_icon(int icon, bool enable)
501{
502 sim_lcd_icon(icon, enable);
503}
504#endif
505
506#if defined(HAVE_LCD_CHARCELLS) || defined(SIMULATOR) /* not BITMAP */
507void lcd_init (void)
508{
509 create_thread(scroll_thread, scroll_stack,
510 sizeof(scroll_stack), scroll_name);
511}
512#endif
513
514#ifdef SIMULATOR
515void lcd_set_contrast(int val)
516{
517 val = val;
518}
519#else
520#ifdef HAVE_LCD_BITMAP
521void lcd_set_contrast(int val)
522{
523 lcd_write(true, LCD_CNTL_CONTRAST);
524 lcd_write(true, val);
525}
526#else
527void lcd_set_contrast(int val)
528{
529 lcd_write(true, LCD_CONTRAST_SET);
530 lcd_write(false, 31-val);
531}
532#endif
533#endif
534
535#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) /* not CHARCELLS */
536
537/*
538 * All bitmaps have this format:
539 * Bits within a byte are arranged veritcally, LSB at top.
540 * Bytes are stored in column-major format, with byte 0 at top left,
541 * byte 1 is 2nd from top, etc. Bytes following left-most column
542 * starts 2nd left column, etc.
543 *
544 * Note: The HW takes bitmap bytes in row-major order.
545 *
546 * Memory copy of display bitmap
547 */
548unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
549
550static int xmargin=0;
551static int ymargin=0;
552
553/*
554 * ASCII character generation tables
555 *
556 * This contains only the printable characters (0x20-0x7f).
557 * Each element in this table is a character pattern bitmap.
558 */
559#define ASCII_MIN 0x20 /* First char in table */
560#define ASCII_MAX 0x7f /* Last char in table */
561
562/* All zeros and ones bitmaps for area filling */
563static unsigned char zeros[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00 };
565static unsigned char ones[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
566 0xff, 0xff };
567
568#ifndef SIMULATOR
569
570/*
571 * Initialize LCD
572 */
573void lcd_init (void)
574{
575 /* Initialize PB0-3 as output pins */
576 PBCR2 &= 0xff00; /* MD = 00 */
577 PBIOR |= 0x000f; /* IOR = 1 */
578
579 lcd_clear_display();
580 lcd_update();
581 create_thread(scroll_thread, scroll_stack,
582 sizeof(scroll_stack), scroll_name);
583}
584
585/*
586 * Update the display.
587 * This must be called after all other LCD functions that change the display.
588 */
589void lcd_update (void) __attribute__ ((section (".icode")));
590void lcd_update (void)
591{
592 int x, y;
593
594 /* Copy display bitmap to hardware */
595 for (y = 0; y < LCD_HEIGHT/8; y++)
596 {
597 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf));
598 lcd_write (true, LCD_CNTL_HIGHCOL);
599 lcd_write (true, LCD_CNTL_LOWCOL);
600
601 for (x = 0; x < LCD_WIDTH; x++)
602 lcd_write (false, lcd_framebuffer[x][y]);
603 }
604}
605
606/*
607 * Update a fraction of the display.
608 */
609void lcd_update_rect (int, int, int, int) __attribute__ ((section (".icode")));
610void lcd_update_rect (int x_start, int y,
611 int width, int height)
612{
613 int ymax;
614 int xmax;
615 int x;
616
617 /* The Y coordinates have to work on even 8 pixel rows */
618 ymax = (y + height)/8;
619 y /= 8;
620
621 xmax = x_start + width;
622
623 if(xmax > LCD_WIDTH)
624 xmax = LCD_WIDTH;
625 if(ymax >= LCD_HEIGHT/8)
626 ymax = LCD_HEIGHT/8-1;
627
628 /* Copy specified rectange bitmap to hardware */
629 for (; y <= ymax; y++)
630 {
631 lcd_write (true, LCD_CNTL_PAGE | (y & 0xf));
632 lcd_write (true, LCD_CNTL_HIGHCOL | ((x_start>>4) & 0xf));
633 lcd_write (true, LCD_CNTL_LOWCOL | (x_start & 0xf));
634
635 for (x = x_start; x < xmax; x++)
636 lcd_write (false, lcd_framebuffer[x][y]);
637 }
638}
639
640#endif /* SIMULATOR */
641
642/*
643 * Clear the display
644 */
645void lcd_clear_display (void)
646{
647#if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
648 /* Clear just the text portion of the display */
649 int x, y;
650 for (y = 8; y <= (32 + 7); ++y)
651 {
652 for (x = 0; x < LCD_WIDTH; x++)
653 CLEAR_PIXEL(x, y);
654 }
655 /* this function is being used when simulating a charcell LCD and
656 then we update immediately */
657 lcd_update();
658#else
659 memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
660#endif
661}
662
663void lcd_setmargins(int x, int y)
664{
665 xmargin = x;
666 ymargin = y;
667}
668
669int lcd_getxmargin(void)
670{
671 return xmargin;
672}
673
674int lcd_getymargin(void)
675{
676 return ymargin;
677}
678
679static int curfont = FONT_SYSFIXED;
680
681/*
682 * Put a string at specified character position
683 */
684void lcd_puts(int x, int y, unsigned char *str)
685{
686 int xpos,ypos,w,h;
687
688#if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
689 /* We make the simulator truncate the string if it reaches the right edge,
690 as otherwise it'll wrap. The real target doesn't wrap. */
691
692 char buffer[12];
693 if(strlen(str)+x > 11 ) {
694 strncpy(buffer, str, sizeof buffer);
695 buffer[11-x]=0;
696 str = buffer;
697 }
698 xmargin = 0;
699 ymargin = 8;
700#endif
701
702 if(!str || !str[0])
703 return;
704
705 lcd_getstringsize(str, curfont, &w, &h);
706 xpos = xmargin + x*w / strlen(str);
707 ypos = ymargin + y*h;
708 lcd_putsxy( xpos, ypos, str, curfont);
709 lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h);
710#if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
711 /* this function is being used when simulating a charcell LCD and
712 then we update immediately */
713 lcd_update();
714#endif
715}
716
717/* set current font*/
718void lcd_setfont(int newfont)
719{
720 curfont = newfont;
721}
722
723/*
724 * Return width and height of a given font.
725 */
726void lcd_getfontsize(int font, int *width, int *height)
727{
728 struct font* pf = font_get(font);
729
730 *width = pf->maxwidth;
731 *height = pf->height;
732}
733
734
735/*
736 * Return width and height of a given font.
737 */
738int lcd_getstringsize(unsigned char *str, int font, int *w, int *h)
739{
740 struct font* pf = font_get(font);
741 int ch;
742 int width = 0;
743
744 while((ch = *str++)) {
745 /* check input range*/
746 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
747 ch = pf->defaultchar;
748 ch -= pf->firstchar;
749
750 /* get proportional width and glyph bits*/
751 width += pf->width? pf->width[ch]: pf->maxwidth;
752 }
753 *w = width;
754 *h = pf->height;
755
756 return width;
757}
758
759/*
760 * Put a string at specified bit position
761 */
762void lcd_putsxy(int x, int y, unsigned char *str, int font)
763{
764 int ch;
765 struct font* pf = font_get(font);
766
767 while (((ch = *str++) != '\0')) {
768 bitmap_t *bits;
769 int width;
770
771 /* check input range*/
772 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
773 ch = pf->defaultchar;
774 ch -= pf->firstchar;
775
776 /* get proportional width and glyph bits*/
777 width = pf->width ? pf->width[ch] : pf->maxwidth;
778 if (x + width > LCD_WIDTH)
779 break;
780
781 /* no partial-height drawing for now...*/
782 if (y + pf->height > LCD_HEIGHT)
783 break;
784 bits = pf->bits + (pf->offset ? pf->offset[ch] : (pf->height * ch));
785
786 lcd_bitmap((unsigned char *)bits, x, y, width, pf->height, true);
787 x += width;
788 }
789}
790
791/*
792 * Display a bitmap at (x, y), size (nx, ny)
793 * clear is true to clear destination area first
794 */
795void lcd_bitmap (unsigned char *src, int x, int y, int nx, int ny,
796 bool clear) __attribute__ ((section (".icode")));
797void lcd_bitmap (unsigned char *src, int x, int y, int nx, int ny,
798 bool clear)
799{
800 unsigned char *dst;
801 unsigned char *dst2;
802 unsigned int data, mask, mask2, mask3, mask4;
803 int shift;
804
805 if (((unsigned)x >= LCD_WIDTH) || ((unsigned)y >= LCD_HEIGHT))
806 return;
807 if (((unsigned)(x + nx)) >= LCD_WIDTH)
808 nx = LCD_WIDTH - x;
809 if (((unsigned)(y + ny)) >= LCD_HEIGHT)
810 ny = LCD_HEIGHT - y;
811
812 shift = y & 7;
813 dst2 = &lcd_framebuffer[x][y/8];
814 ny += shift;
815
816 /* Calculate bit masks */
817 mask4 = ~(0xfe << ((ny-1) & 7));
818 if (clear)
819 {
820 mask = ~(0xff << shift);
821 mask2 = 0;
822 mask3 = ~mask4;
823 if (ny <= 8)
824 mask3 |= mask;
825 }
826 else
827 mask = mask2 = mask3 = 0xff;
828
829 /* Loop for each column */
830 for (x = 0; x < nx; x++)
831 {
832 dst = dst2;
833 dst2 += LCD_HEIGHT/8;
834 data = 0;
835 y = 0;
836
837 if (ny > 8)
838 {
839 /* First partial row */
840 data = *src++ << shift;
841 *dst = (*dst & mask) | data;
842 data >>= 8;
843 dst++;
844
845 /* Intermediate rows */
846 for (y = 8; y < ny-8; y += 8)
847 {
848 data |= *src++ << shift;
849 *dst = (*dst & mask2) | data;
850 data >>= 8;
851 dst++;
852 }
853 }
854
855 /* Last partial row */
856 if (y + shift < ny)
857 data |= *src++ << shift;
858 *dst = (*dst & mask3) | (data & mask4);
859 }
860}
861
862/*
863 * Draw a rectangle with point a (upper left) at (x, y)
864 * and size (nx, ny)
865 */
866void lcd_drawrect (int x, int y, int nx, int ny)
867{
868 int i;
869
870 if (x > LCD_WIDTH)
871 return;
872 if (y > LCD_HEIGHT)
873 return;
874
875 if (x + nx > LCD_WIDTH)
876 nx = LCD_WIDTH - x;
877 if (y + ny > LCD_HEIGHT)
878 ny = LCD_HEIGHT - y;
879
880 /* vertical lines */
881 for (i = 0; i < ny; i++) {
882 DRAW_PIXEL(x, (y + i));
883 DRAW_PIXEL((x + nx - 1), (y + i));
884 }
885
886 /* horizontal lines */
887 for (i = 0; i < nx; i++) {
888 DRAW_PIXEL((x + i),y);
889 DRAW_PIXEL((x + i),(y + ny - 1));
890 }
891}
892
893/*
894 * Clear a rectangular area at (x, y), size (nx, ny)
895 */
896void lcd_clearrect (int x, int y, int nx, int ny)
897{
898 int i;
899 for (i = 0; i < nx; i++)
900 lcd_bitmap (zeros, x+i, y, 1, ny, true);
901}
902
903/*
904 * Fill a rectangular area at (x, y), size (nx, ny)
905 */
906void lcd_fillrect (int x, int y, int nx, int ny)
907{
908 int i;
909 for (i = 0; i < nx; i++)
910 lcd_bitmap (ones, x+i, y, 1, ny, true);
911}
912
913/* Invert a rectangular area at (x, y), size (nx, ny) */
914void lcd_invertrect (int x, int y, int nx, int ny)
915{
916 int i, j;
917
918 if (x > LCD_WIDTH)
919 return;
920 if (y > LCD_HEIGHT)
921 return;
922
923 if (x + nx > LCD_WIDTH)
924 nx = LCD_WIDTH - x;
925 if (y + ny > LCD_HEIGHT)
926 ny = LCD_HEIGHT - y;
927
928 for (i = 0; i < nx; i++)
929 for (j = 0; j < ny; j++)
930 INVERT_PIXEL((x + i), (y + j));
931}
932
933void lcd_drawline( int x1, int y1, int x2, int y2 )
934{
935 int numpixels;
936 int i;
937 int deltax, deltay;
938 int d, dinc1, dinc2;
939 int x, xinc1, xinc2;
940 int y, yinc1, yinc2;
941
942 deltax = abs(x2 - x1);
943 deltay = abs(y2 - y1);
944
945 if(deltax >= deltay)
946 {
947 numpixels = deltax;
948 d = 2 * deltay - deltax;
949 dinc1 = deltay * 2;
950 dinc2 = (deltay - deltax) * 2;
951 xinc1 = 1;
952 xinc2 = 1;
953 yinc1 = 0;
954 yinc2 = 1;
955 }
956 else
957 {
958 numpixels = deltay;
959 d = 2 * deltax - deltay;
960 dinc1 = deltax * 2;
961 dinc2 = (deltax - deltay) * 2;
962 xinc1 = 0;
963 xinc2 = 1;
964 yinc1 = 1;
965 yinc2 = 1;
966 }
967 numpixels++; /* include endpoints */
968
969 if(x1 > x2)
970 {
971 xinc1 = -xinc1;
972 xinc2 = -xinc2;
973 }
974
975 if(y1 > y2)
976 {
977 yinc1 = -yinc1;
978 yinc2 = -yinc2;
979 }
980
981 x = x1;
982 y = y1;
983
984 for(i=0; i<numpixels; i++)
985 {
986 DRAW_PIXEL(x,y);
987
988 if(d < 0)
989 {
990 d += dinc1;
991 x += xinc1;
992 y += yinc1;
993 }
994 else
995 {
996 d += dinc2;
997 x += xinc2;
998 y += yinc2;
999 }
1000 }
1001}
1002
1003void lcd_clearline( int x1, int y1, int x2, int y2 )
1004{
1005 int numpixels;
1006 int i;
1007 int deltax, deltay;
1008 int d, dinc1, dinc2;
1009 int x, xinc1, xinc2;
1010 int y, yinc1, yinc2;
1011
1012 deltax = abs(x2 - x1);
1013 deltay = abs(y2 - y1);
1014
1015 if(deltax >= deltay)
1016 {
1017 numpixels = deltax;
1018 d = 2 * deltay - deltax;
1019 dinc1 = deltay * 2;
1020 dinc2 = (deltay - deltax) * 2;
1021 xinc1 = 1;
1022 xinc2 = 1;
1023 yinc1 = 0;
1024 yinc2 = 1;
1025 }
1026 else
1027 {
1028 numpixels = deltay;
1029 d = 2 * deltax - deltay;
1030 dinc1 = deltax * 2;
1031 dinc2 = (deltax - deltay) * 2;
1032 xinc1 = 0;
1033 xinc2 = 1;
1034 yinc1 = 1;
1035 yinc2 = 1;
1036 }
1037 numpixels++; /* include endpoints */
1038
1039 if(x1 > x2)
1040 {
1041 xinc1 = -xinc1;
1042 xinc2 = -xinc2;
1043 }
1044
1045 if(y1 > y2)
1046 {
1047 yinc1 = -yinc1;
1048 yinc2 = -yinc2;
1049 }
1050
1051 x = x1;
1052 y = y1;
1053
1054 for(i=0; i<numpixels; i++)
1055 {
1056 CLEAR_PIXEL(x,y);
1057
1058 if(d < 0)
1059 {
1060 d += dinc1;
1061 x += xinc1;
1062 y += yinc1;
1063 }
1064 else
1065 {
1066 d += dinc2;
1067 x += xinc2;
1068 y += yinc2;
1069 }
1070 }
1071}
1072
1073/*
1074 * Set a single pixel
1075 */
1076void lcd_drawpixel(int x, int y)
1077{
1078 DRAW_PIXEL(x,y);
1079}
1080
1081/*
1082 * Clear a single pixel
1083 */
1084void lcd_clearpixel(int x, int y)
1085{
1086 CLEAR_PIXEL(x,y);
1087}
1088
1089/*
1090 * Invert a single pixel
1091 */
1092void lcd_invertpixel(int x, int y)
1093{
1094 INVERT_PIXEL(x,y);
1095}
1096
1097#else
1098/* no LCD defined, no code to use */
1099#endif
1100
1101void lcd_puts_scroll(int x, int y, unsigned char* string )
1102{
1103 struct scrollinfo* s = &scroll;
1104#ifdef HAVE_LCD_CHARCELLS
1105 s->space = 11 - x;
1106#else
1107 unsigned char ch[2];
1108 int w, h;
1109 int width, height;
1110 lcd_getfontsize(curfont, &width, &height);
1111
1112 ch[1] = 0; /* zero terminate */
1113 ch[0] = string[0];
1114 width = 0;
1115 s->space = 0;
1116 while ( ch[0] &&
1117 (width + lcd_getstringsize(ch, curfont, &w, &h) <
1118 (LCD_WIDTH - x*8))) {
1119 width += w;
1120 s->space++;
1121 ch[0]=string[s->space];
1122 }
1123#endif
1124
1125 lcd_puts(x,y,string);
1126 s->textlen = strlen(string);
1127
1128#ifdef HAVE_LCD_BITMAP
1129 s->space += 2;
1130 lcd_getstringsize(string,curfont,&w,&h);
1131 if ( w > LCD_WIDTH - xmargin ) {
1132#else
1133 if ( s->textlen > s->space ) {
1134#endif
1135 s->offset=s->space;
1136 s->startx=x;
1137 s->starty=y;
1138 strncpy(s->text,string,sizeof s->text);
1139 s->text[sizeof s->text - 1] = 0;
1140 memset(s->line, 0, sizeof s->line);
1141 strncpy(s->line,string,
1142 s->space > (int)sizeof s->line ?
1143 (int)sizeof s->line : s->space );
1144 s->line[sizeof s->line - 1] = 0;
1145 scroll_count = 1;
1146 }
1147}
1148
1149
1150void lcd_stop_scroll(void)
1151{
1152 if ( scroll_count ) {
1153 struct scrollinfo* s = &scroll;
1154 scroll_count = 0;
1155
1156#ifdef HAVE_LCD_BITMAP
1157 {
1158 int w,h;
1159 /* FIXME no font index */
1160 lcd_getstringsize( s->text, FONT_UI, &w, &h);
1161 lcd_clearrect(xmargin + s->startx*w/s->textlen,
1162 ymargin + s->starty*h,
1163 LCD_WIDTH - xmargin,
1164 h);
1165 }
1166#endif
1167 /* restore scrolled row */
1168 lcd_puts(s->startx,s->starty,s->text);
1169 lcd_update();
1170 }
1171}
1172
1173void lcd_scroll_pause(void)
1174{
1175 scroll_count = 0;
1176}
1177
1178void lcd_scroll_resume(void)
1179{
1180 scroll_count = 1;
1181}
1182
1183void lcd_scroll_speed(int speed)
1184{
1185 scroll_speed = speed;
1186}
1187
1188static void scroll_thread(void)
1189{
1190 struct scrollinfo* s = &scroll;
1191
1192 while ( 1 ) {
1193 if ( !scroll_count ) {
1194 yield();
1195 continue;
1196 }
1197 /* wait 0.5s before starting scroll */
1198 if ( scroll_count < scroll_speed/2 )
1199 scroll_count++;
1200 else {
1201 int i;
1202 for ( i=0; i<s->space-1; i++ )
1203 s->line[i] = s->line[i+1];
1204
1205 if ( s->offset < s->textlen ) {
1206 s->line[(int)s->space - 1] = s->text[(int)s->offset];
1207 s->offset++;
1208 }
1209 else {
1210 s->line[s->space - 1] = ' ';
1211 if ( s->offset < s->textlen + scroll_spacing - 1 )
1212 s->offset++;
1213 else
1214 s->offset = 0;
1215 }
1216
1217#ifdef HAVE_LCD_BITMAP
1218 {
1219 /* FIXME no font index */
1220 int w, h;
1221 lcd_getstringsize( s->text, FONT_UI, &w, &h);
1222 lcd_clearrect(xmargin + s->startx*w/s->textlen,
1223 ymargin + s->starty*h,
1224 LCD_WIDTH - xmargin,
1225 h);
1226 }
1227#endif
1228 lcd_puts(s->startx,s->starty,s->line);
1229 lcd_update();
1230 }
1231 sleep(HZ/scroll_speed);
1232 }
1233}
1234
1235#ifndef SIMULATOR
1236#ifdef HAVE_LCD_BITMAP
1237/**
1238 * Rolls up the lcd display by the specified amount of lines.
1239 * Lines that are rolled out over the top of the screen are
1240 * rolled in from the bottom again. This is a hardware
1241 * remapping only and all operations on the lcd are affected.
1242 * ->
1243 * @param int lines - The number of lines that are rolled.
1244 * The value must be 0 <= pixels < LCD_HEIGHT.
1245 */
1246void lcd_roll(int lines)
1247{
1248 lcd_write(true, LCD_SET_DISPLAY_START_LINE | (lines & (LCD_HEIGHT-1)));
1249}
1250#endif
1251#endif
1252
1253/* -----------------------------------------------------------------
1254 * local variables:
1255 * eval: (load-file "../rockbox-mode.el")
1256 * end:
1257 */
diff --git a/firmware/drivers/lcd.h b/firmware/drivers/lcd.h
index 388f31c1cf..76e38375e4 100644
--- a/firmware/drivers/lcd.h
+++ b/firmware/drivers/lcd.h
@@ -37,6 +37,7 @@ extern void lcd_icon(int icon, bool enable);
37extern void lcd_stop_scroll(void); 37extern void lcd_stop_scroll(void);
38extern void lcd_scroll_speed( int speed ); 38extern void lcd_scroll_speed( int speed );
39extern void lcd_set_contrast(int val); 39extern void lcd_set_contrast(int val);
40extern void lcd_write( bool command, int byte );
40 41
41#if defined(SIMULATOR) || defined(HAVE_LCD_BITMAP) 42#if defined(SIMULATOR) || defined(HAVE_LCD_BITMAP)
42extern void lcd_update(void); 43extern void lcd_update(void);