summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-03-09 18:27:12 +0000
committerJens Arnold <amiconn@rockbox.org>2008-03-09 18:27:12 +0000
commit7317139eb487ce3a59f0895c8edcfb1a2c8109f7 (patch)
treee5d95d50ecd7a7253d3ff769c9343e75e459c6fd
parented8402ca5ec33f70ac6b28531b05a22c0cf75f9c (diff)
downloadrockbox-7317139eb487ce3a59f0895c8edcfb1a2c8109f7.tar.gz
rockbox-7317139eb487ce3a59f0895c8edcfb1a2c8109f7.zip
Reuse the 1 bit vertical-packed LCD driver code for the remote LCD driver with the same pixelformat instead of duplicating everything.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16593 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/lcd-1bit-vert.c329
-rw-r--r--firmware/drivers/lcd-remote-1bit-v.c884
2 files changed, 175 insertions, 1038 deletions
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c
index 7c9cd26e2a..3a6e59c461 100644
--- a/firmware/drivers/lcd-1bit-vert.c
+++ b/firmware/drivers/lcd-1bit-vert.c
@@ -16,6 +16,7 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19
19#include "config.h" 20#include "config.h"
20 21
21#include "lcd.h" 22#include "lcd.h"
@@ -31,16 +32,27 @@
31#include "bidi.h" 32#include "bidi.h"
32#include "scroll_engine.h" 33#include "scroll_engine.h"
33 34
35#ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */
36#define LCDFN(fn) lcd_ ## fn
37#define FBFN(fn) fb_ ## fn
38#define LCDM(ma) LCD_ ## ma
39#define MAIN_LCD
40#endif
41
34/*** globals ***/ 42/*** globals ***/
35 43
36unsigned char lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; 44FBFN(data) LCDFN(framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)]
45#if CONFIG_CPU != SH7034
46 IBSS_ATTR
47#endif
48 ;
37 49
38static struct viewport default_vp = 50static struct viewport default_vp =
39{ 51{
40 .x = 0, 52 .x = 0,
41 .y = 0, 53 .y = 0,
42 .width = LCD_WIDTH, 54 .width = LCDM(WIDTH),
43 .height = LCD_HEIGHT, 55 .height = LCDM(HEIGHT),
44 .font = FONT_SYSFIXED, 56 .font = FONT_SYSFIXED,
45 .drawmode = DRMODE_SOLID, 57 .drawmode = DRMODE_SOLID,
46 .xmargin = 0, 58 .xmargin = 0,
@@ -51,7 +63,7 @@ static struct viewport* current_vp = &default_vp;
51 63
52/*** Viewports ***/ 64/*** Viewports ***/
53 65
54void lcd_set_viewport(struct viewport* vp) 66void LCDFN(set_viewport)(struct viewport* vp)
55{ 67{
56 if (vp == NULL) 68 if (vp == NULL)
57 current_vp = &default_vp; 69 current_vp = &default_vp;
@@ -59,75 +71,78 @@ void lcd_set_viewport(struct viewport* vp)
59 current_vp = vp; 71 current_vp = vp;
60} 72}
61 73
62void lcd_update_viewport(void) 74void LCDFN(update_viewport)(void)
63{ 75{
64 lcd_update_rect(current_vp->x, current_vp->y, 76 LCDFN(update_rect)(current_vp->x, current_vp->y,
65 current_vp->width, current_vp->height); 77 current_vp->width, current_vp->height);
66} 78}
67 79
68void lcd_update_viewport_rect(int x, int y, int width, int height) 80void LCDFN(update_viewport_rect)(int x, int y, int width, int height)
69{ 81{
70 lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height); 82 LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height);
71} 83}
72 84
73/* LCD init */ 85/* LCD init */
74void lcd_init(void) 86void LCDFN(init)(void)
75{ 87{
76 lcd_clear_display(); 88 LCDFN(clear_display)();
77 /* Call device specific init */ 89#ifndef SIMULATOR
78 lcd_init_device(); 90 LCDFN(init_device)();
91#endif
92#ifdef MAIN_LCD
79 scroll_init(); 93 scroll_init();
94#endif
80} 95}
81 96
82/*** parameter handling ***/ 97/*** parameter handling ***/
83 98
84void lcd_set_drawmode(int mode) 99void LCDFN(set_drawmode)(int mode)
85{ 100{
86 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 101 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
87} 102}
88 103
89int lcd_get_drawmode(void) 104int LCDFN(get_drawmode)(void)
90{ 105{
91 return current_vp->drawmode; 106 return current_vp->drawmode;
92} 107}
93 108
94void lcd_setmargins(int x, int y) 109void LCDFN(setmargins)(int x, int y)
95{ 110{
96 current_vp->xmargin = x; 111 current_vp->xmargin = x;
97 current_vp->ymargin = y; 112 current_vp->ymargin = y;
98} 113}
99 114
100int lcd_getxmargin(void) 115int LCDFN(getxmargin)(void)
101{ 116{
102 return current_vp->xmargin; 117 return current_vp->xmargin;
103} 118}
104 119
105int lcd_getymargin(void) 120int LCDFN(getymargin)(void)
106{ 121{
107 return current_vp->ymargin; 122 return current_vp->ymargin;
108} 123}
109 124
110int lcd_getwidth(void) 125int LCDFN(getwidth)(void)
111{ 126{
112 return current_vp->width; 127 return current_vp->width;
113} 128}
114 129
115int lcd_getheight(void) 130int LCDFN(getheight)(void)
116{ 131{
117 return current_vp->height; 132 return current_vp->height;
118} 133}
119 134
120void lcd_setfont(int newfont) 135void LCDFN(setfont)(int newfont)
121{ 136{
122 current_vp->font = newfont; 137 current_vp->font = newfont;
123} 138}
124 139
125int lcd_getfont(void) 140int LCDFN(getfont)(void)
126{ 141{
127 return current_vp->font; 142 return current_vp->font;
128} 143}
129 144
130int lcd_getstringsize(const unsigned char *str, int *w, int *h) 145int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h)
131{ 146{
132 return font_getstringsize(str, w, h, current_vp->font); 147 return font_getstringsize(str, w, h, current_vp->font);
133} 148}
@@ -136,17 +151,17 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h)
136 151
137static void setpixel(int x, int y) 152static void setpixel(int x, int y)
138{ 153{
139 lcd_framebuffer[y>>3][x] |= 1 << (y & 7); 154 LCDFN(framebuffer)[y>>3][x] |= 1 << (y & 7);
140} 155}
141 156
142static void clearpixel(int x, int y) 157static void clearpixel(int x, int y)
143{ 158{
144 lcd_framebuffer[y>>3][x] &= ~(1 << (y & 7)); 159 LCDFN(framebuffer)[y>>3][x] &= ~(1 << (y & 7));
145} 160}
146 161
147static void flippixel(int x, int y) 162static void flippixel(int x, int y)
148{ 163{
149 lcd_framebuffer[y>>3][x] ^= 1 << (y & 7); 164 LCDFN(framebuffer)[y>>3][x] ^= 1 << (y & 7);
150} 165}
151 166
152static void nopixel(int x, int y) 167static void nopixel(int x, int y)
@@ -155,35 +170,31 @@ static void nopixel(int x, int y)
155 (void)y; 170 (void)y;
156} 171}
157 172
158lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { 173LCDFN(pixelfunc_type)* const LCDFN(pixelfuncs)[8] = {
159 flippixel, nopixel, setpixel, setpixel, 174 flippixel, nopixel, setpixel, setpixel,
160 nopixel, clearpixel, nopixel, clearpixel 175 nopixel, clearpixel, nopixel, clearpixel
161}; 176};
162 177
163static void flipblock(unsigned char *address, unsigned mask, unsigned bits) 178static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask,
164 ICODE_ATTR; 179 unsigned bits)
165static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
166{ 180{
167 *address ^= bits & mask; 181 *address ^= bits & mask;
168} 182}
169 183
170static void bgblock(unsigned char *address, unsigned mask, unsigned bits) 184static void ICODE_ATTR bgblock(FBFN(data) *address, unsigned mask,
171 ICODE_ATTR; 185 unsigned bits)
172static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
173{ 186{
174 *address &= bits | ~mask; 187 *address &= bits | ~mask;
175} 188}
176 189
177static void fgblock(unsigned char *address, unsigned mask, unsigned bits) 190static void ICODE_ATTR fgblock(FBFN(data) *address, unsigned mask,
178 ICODE_ATTR; 191 unsigned bits)
179static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
180{ 192{
181 *address |= bits & mask; 193 *address |= bits & mask;
182} 194}
183 195
184static void solidblock(unsigned char *address, unsigned mask, unsigned bits) 196static void ICODE_ATTR solidblock(FBFN(data) *address, unsigned mask,
185 ICODE_ATTR; 197 unsigned bits)
186static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
187{ 198{
188 unsigned data = *(char*)address; 199 unsigned data = *(char*)address;
189 200
@@ -191,30 +202,26 @@ static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
191 *address = data ^ (bits & mask); 202 *address = data ^ (bits & mask);
192} 203}
193 204
194static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) 205static void ICODE_ATTR flipinvblock(FBFN(data) *address, unsigned mask,
195 ICODE_ATTR; 206 unsigned bits)
196static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
197{ 207{
198 *address ^= ~bits & mask; 208 *address ^= ~bits & mask;
199} 209}
200 210
201static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) 211static void ICODE_ATTR bginvblock(FBFN(data) *address, unsigned mask,
202 ICODE_ATTR; 212 unsigned bits)
203static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
204{ 213{
205 *address &= ~(bits & mask); 214 *address &= ~(bits & mask);
206} 215}
207 216
208static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) 217static void ICODE_ATTR fginvblock(FBFN(data) *address, unsigned mask,
209 ICODE_ATTR; 218 unsigned bits)
210static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
211{ 219{
212 *address |= ~bits & mask; 220 *address |= ~bits & mask;
213} 221}
214 222
215static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) 223static void ICODE_ATTR solidinvblock(FBFN(data) *address, unsigned mask,
216 ICODE_ATTR; 224 unsigned bits)
217static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
218{ 225{
219 unsigned data = *(char *)address; 226 unsigned data = *(char *)address;
220 227
@@ -222,7 +229,7 @@ static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
222 *address = data ^ (bits & mask); 229 *address = data ^ (bits & mask);
223} 230}
224 231
225lcd_blockfunc_type* const lcd_blockfuncs[8] = { 232LCDFN(blockfunc_type)* const LCDFN(blockfuncs)[8] = {
226 flipblock, bgblock, fgblock, solidblock, 233 flipblock, bgblock, fgblock, solidblock,
227 flipinvblock, bginvblock, fginvblock, solidinvblock 234 flipinvblock, bginvblock, fginvblock, solidinvblock
228}; 235};
@@ -230,21 +237,22 @@ lcd_blockfunc_type* const lcd_blockfuncs[8] = {
230/*** drawing functions ***/ 237/*** drawing functions ***/
231 238
232/* Clear the whole display */ 239/* Clear the whole display */
233void lcd_clear_display(void) 240void LCDFN(clear_display)(void)
234{ 241{
235 unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; 242 unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0;
236 243
237 memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); 244 memset(LCDFN(framebuffer), bits, sizeof LCDFN(framebuffer));
238 lcd_scroll_info.lines = 0; 245 LCDFN(scroll_info).lines = 0;
239} 246}
240 247
241void lcd_clear_viewport(void) 248/* Clear the current viewport */
249void LCDFN(clear_viewport)(void)
242{ 250{
243 int oldmode; 251 int oldmode;
244 252
245 if (current_vp == &default_vp) 253 if (current_vp == &default_vp)
246 { 254 {
247 lcd_clear_display(); 255 LCDFN(clear_display)();
248 } 256 }
249 else 257 else
250 { 258 {
@@ -254,24 +262,24 @@ void lcd_clear_viewport(void)
254 current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) | 262 current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) |
255 DRMODE_SOLID; 263 DRMODE_SOLID;
256 264
257 lcd_fillrect(0, 0, current_vp->width, current_vp->height); 265 LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height);
258 266
259 current_vp->drawmode = oldmode; 267 current_vp->drawmode = oldmode;
260 268
261 lcd_scroll_stop(current_vp); 269 LCDFN(scroll_stop)(current_vp);
262 } 270 }
263} 271}
264 272
265/* Set a single pixel */ 273/* Set a single pixel */
266void lcd_drawpixel(int x, int y) 274void LCDFN(drawpixel)(int x, int y)
267{ 275{
268 if (((unsigned)x < (unsigned)current_vp->width) && 276 if (((unsigned)x < (unsigned)current_vp->width) &&
269 ((unsigned)y < (unsigned)current_vp->height)) 277 ((unsigned)y < (unsigned)current_vp->height))
270 lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); 278 LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y);
271} 279}
272 280
273/* Draw a line */ 281/* Draw a line */
274void lcd_drawline(int x1, int y1, int x2, int y2) 282void LCDFN(drawline)(int x1, int y1, int x2, int y2)
275{ 283{
276 int numpixels; 284 int numpixels;
277 int i; 285 int i;
@@ -279,7 +287,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
279 int d, dinc1, dinc2; 287 int d, dinc1, dinc2;
280 int x, xinc1, xinc2; 288 int x, xinc1, xinc2;
281 int y, yinc1, yinc2; 289 int y, yinc1, yinc2;
282 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; 290 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode];
283 291
284 deltax = abs(x2 - x1); 292 deltax = abs(x2 - x1);
285 deltay = abs(y2 - y1); 293 deltay = abs(y2 - y1);
@@ -323,8 +331,8 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
323 331
324 for (i = 0; i < numpixels; i++) 332 for (i = 0; i < numpixels; i++)
325 { 333 {
326 if (((unsigned)x < (unsigned)current_vp->width) && 334 if (((unsigned)x < (unsigned)current_vp->width)
327 ((unsigned)y < (unsigned)current_vp->height)) 335 && ((unsigned)y < (unsigned)current_vp->height))
328 pfunc(current_vp->x + x, current_vp->y + y); 336 pfunc(current_vp->x + x, current_vp->y + y);
329 337
330 if (d < 0) 338 if (d < 0)
@@ -343,12 +351,12 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
343} 351}
344 352
345/* Draw a horizontal line (optimised) */ 353/* Draw a horizontal line (optimised) */
346void lcd_hline(int x1, int x2, int y) 354void LCDFN(hline)(int x1, int x2, int y)
347{ 355{
348 int x; 356 int x, width;
349 unsigned char *dst, *dst_end; 357 unsigned char *dst, *dst_end;
350 unsigned mask; 358 unsigned mask;
351 lcd_blockfunc_type *bfunc; 359 LCDFN(blockfunc_type) *bfunc;
352 360
353 /* direction flip */ 361 /* direction flip */
354 if (x2 < x1) 362 if (x2 < x1)
@@ -369,28 +377,29 @@ void lcd_hline(int x1, int x2, int y)
369 if (x2 >= current_vp->width) 377 if (x2 >= current_vp->width)
370 x2 = current_vp->width-1; 378 x2 = current_vp->width-1;
371 379
372 /* adjust for viewport */ 380 width = x2 - x1 + 1;
373 y += current_vp->y; 381
382 /* adjust to viewport */
374 x1 += current_vp->x; 383 x1 += current_vp->x;
375 x2 += current_vp->x; 384 y += current_vp->y;
376 385
377 bfunc = lcd_blockfuncs[current_vp->drawmode]; 386 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
378 dst = &lcd_framebuffer[y>>3][x1]; 387 dst = &LCDFN(framebuffer)[y>>3][x1];
379 mask = 1 << (y & 7); 388 mask = 1 << (y & 7);
380 389
381 dst_end = dst + x2 - x1; 390 dst_end = dst + width;
382 do 391 do
383 bfunc(dst++, mask, 0xFFu); 392 bfunc(dst++, mask, 0xFFu);
384 while (dst <= dst_end); 393 while (dst < dst_end);
385} 394}
386 395
387/* Draw a vertical line (optimised) */ 396/* Draw a vertical line (optimised) */
388void lcd_vline(int x, int y1, int y2) 397void LCDFN(vline)(int x, int y1, int y2)
389{ 398{
390 int ny; 399 int ny;
391 unsigned char *dst; 400 FBFN(data) *dst;
392 unsigned mask, mask_bottom; 401 unsigned mask, mask_bottom;
393 lcd_blockfunc_type *bfunc; 402 LCDFN(blockfunc_type) *bfunc;
394 403
395 /* direction flip */ 404 /* direction flip */
396 if (y2 < y1) 405 if (y2 < y1)
@@ -416,8 +425,8 @@ void lcd_vline(int x, int y1, int y2)
416 y2 += current_vp->y; 425 y2 += current_vp->y;
417 x += current_vp->x; 426 x += current_vp->x;
418 427
419 bfunc = lcd_blockfuncs[current_vp->drawmode]; 428 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
420 dst = &lcd_framebuffer[y1>>3][x]; 429 dst = &LCDFN(framebuffer)[y1>>3][x];
421 ny = y2 - (y1 & ~7); 430 ny = y2 - (y1 & ~7);
422 mask = 0xFFu << (y1 & 7); 431 mask = 0xFFu << (y1 & 7);
423 mask_bottom = 0xFFu >> (~ny & 7); 432 mask_bottom = 0xFFu >> (~ny & 7);
@@ -425,7 +434,7 @@ void lcd_vline(int x, int y1, int y2)
425 for (; ny >= 8; ny -= 8) 434 for (; ny >= 8; ny -= 8)
426 { 435 {
427 bfunc(dst, mask, 0xFFu); 436 bfunc(dst, mask, 0xFFu);
428 dst += LCD_WIDTH; 437 dst += LCDM(WIDTH);
429 mask = 0xFFu; 438 mask = 0xFFu;
430 } 439 }
431 mask &= mask_bottom; 440 mask &= mask_bottom;
@@ -433,7 +442,7 @@ void lcd_vline(int x, int y1, int y2)
433} 442}
434 443
435/* Draw a rectangular box */ 444/* Draw a rectangular box */
436void lcd_drawrect(int x, int y, int width, int height) 445void LCDFN(drawrect)(int x, int y, int width, int height)
437{ 446{
438 if ((width <= 0) || (height <= 0)) 447 if ((width <= 0) || (height <= 0))
439 return; 448 return;
@@ -441,20 +450,20 @@ void lcd_drawrect(int x, int y, int width, int height)
441 int x2 = x + width - 1; 450 int x2 = x + width - 1;
442 int y2 = y + height - 1; 451 int y2 = y + height - 1;
443 452
444 lcd_vline(x, y, y2); 453 LCDFN(vline)(x, y, y2);
445 lcd_vline(x2, y, y2); 454 LCDFN(vline)(x2, y, y2);
446 lcd_hline(x, x2, y); 455 LCDFN(hline)(x, x2, y);
447 lcd_hline(x, x2, y2); 456 LCDFN(hline)(x, x2, y2);
448} 457}
449 458
450/* Fill a rectangular area */ 459/* Fill a rectangular area */
451void lcd_fillrect(int x, int y, int width, int height) 460void LCDFN(fillrect)(int x, int y, int width, int height)
452{ 461{
453 int ny; 462 int ny;
454 unsigned char *dst, *dst_end; 463 FBFN(data) *dst, *dst_end;
455 unsigned mask, mask_bottom; 464 unsigned mask, mask_bottom;
456 unsigned bits = 0; 465 unsigned bits = 0;
457 lcd_blockfunc_type *bfunc; 466 LCDFN(blockfunc_type) *bfunc;
458 bool fillopt = false; 467 bool fillopt = false;
459 468
460 /* nothing to draw? */ 469 /* nothing to draw? */
@@ -497,8 +506,8 @@ void lcd_fillrect(int x, int y, int width, int height)
497 bits = 0xFFu; 506 bits = 0xFFu;
498 } 507 }
499 } 508 }
500 bfunc = lcd_blockfuncs[current_vp->drawmode]; 509 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
501 dst = &lcd_framebuffer[y>>3][x]; 510 dst = &LCDFN(framebuffer)[y>>3][x];
502 ny = height - 1 + (y & 7); 511 ny = height - 1 + (y & 7);
503 mask = 0xFFu << (y & 7); 512 mask = 0xFFu << (y & 7);
504 mask_bottom = 0xFFu >> (~ny & 7); 513 mask_bottom = 0xFFu >> (~ny & 7);
@@ -509,7 +518,7 @@ void lcd_fillrect(int x, int y, int width, int height)
509 memset(dst, bits, width); 518 memset(dst, bits, width);
510 else 519 else
511 { 520 {
512 unsigned char *dst_row = dst; 521 FBFN(data) *dst_row = dst;
513 522
514 dst_end = dst_row + width; 523 dst_end = dst_row + width;
515 do 524 do
@@ -517,7 +526,7 @@ void lcd_fillrect(int x, int y, int width, int height)
517 while (dst_row < dst_end); 526 while (dst_row < dst_end);
518 } 527 }
519 528
520 dst += LCD_WIDTH; 529 dst += LCDM(WIDTH);
521 mask = 0xFFu; 530 mask = 0xFFu;
522 } 531 }
523 mask &= mask_bottom; 532 mask &= mask_bottom;
@@ -545,16 +554,14 @@ void lcd_fillrect(int x, int y, int width, int height)
545 * This is the same as the internal lcd hw format. */ 554 * This is the same as the internal lcd hw format. */
546 555
547/* Draw a partial bitmap */ 556/* Draw a partial bitmap */
548void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, 557void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
549 int stride, int x, int y, int width, int height) 558 int src_y, int stride, int x, int y,
550 ICODE_ATTR; 559 int width, int height)
551void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
552 int stride, int x, int y, int width, int height)
553{ 560{
554 int shift, ny; 561 int shift, ny;
555 unsigned char *dst, *dst_end; 562 FBFN(data) *dst, *dst_end;
556 unsigned mask, mask_bottom; 563 unsigned mask, mask_bottom;
557 lcd_blockfunc_type *bfunc; 564 LCDFN(blockfunc_type) *bfunc;
558 565
559 /* nothing to draw? */ 566 /* nothing to draw? */
560 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 567 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
@@ -586,11 +593,11 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
586 src += stride * (src_y >> 3) + src_x; /* move starting point */ 593 src += stride * (src_y >> 3) + src_x; /* move starting point */
587 src_y &= 7; 594 src_y &= 7;
588 y -= src_y; 595 y -= src_y;
589 dst = &lcd_framebuffer[y>>3][x]; 596 dst = &LCDFN(framebuffer)[y>>3][x];
590 shift = y & 7; 597 shift = y & 7;
591 ny = height - 1 + shift + src_y; 598 ny = height - 1 + shift + src_y;
592 599
593 bfunc = lcd_blockfuncs[current_vp->drawmode]; 600 bfunc = LCDFN(blockfuncs)[current_vp->drawmode];
594 mask = 0xFFu << (shift + src_y); 601 mask = 0xFFu << (shift + src_y);
595 mask_bottom = 0xFFu >> (~ny & 7); 602 mask_bottom = 0xFFu >> (~ny & 7);
596 603
@@ -605,7 +612,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
605 else 612 else
606 { 613 {
607 const unsigned char *src_row = src; 614 const unsigned char *src_row = src;
608 unsigned char *dst_row = dst; 615 FBFN(data) *dst_row = dst;
609 616
610 dst_end = dst_row + width; 617 dst_end = dst_row + width;
611 do 618 do
@@ -614,7 +621,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
614 } 621 }
615 622
616 src += stride; 623 src += stride;
617 dst += LCD_WIDTH; 624 dst += LCDM(WIDTH);
618 mask = 0xFFu; 625 mask = 0xFFu;
619 } 626 }
620 mask &= mask_bottom; 627 mask &= mask_bottom;
@@ -635,7 +642,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
635 do 642 do
636 { 643 {
637 const unsigned char *src_col = src++; 644 const unsigned char *src_col = src++;
638 unsigned char *dst_col = dst++; 645 FBFN(data) *dst_col = dst++;
639 unsigned mask_col = mask; 646 unsigned mask_col = mask;
640 unsigned data = 0; 647 unsigned data = 0;
641 648
@@ -652,7 +659,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
652 mask_col >>= 8; 659 mask_col >>= 8;
653 660
654 src_col += stride; 661 src_col += stride;
655 dst_col += LCD_WIDTH; 662 dst_col += LCDM(WIDTH);
656 data >>= 8; 663 data >>= 8;
657 } 664 }
658 data |= *src_col << shift; 665 data |= *src_col << shift;
@@ -663,13 +670,14 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
663} 670}
664 671
665/* Draw a full bitmap */ 672/* Draw a full bitmap */
666void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) 673void LCDFN(bitmap)(const unsigned char *src, int x, int y, int width,
674 int height)
667{ 675{
668 lcd_bitmap_part(src, 0, 0, width, x, y, width, height); 676 LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height);
669} 677}
670 678
671/* put a string at a given pixel position, skipping first ofs pixel columns */ 679/* put a string at a given pixel position, skipping first ofs pixel columns */
672static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) 680static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
673{ 681{
674 unsigned short ch; 682 unsigned short ch;
675 unsigned short *ucs; 683 unsigned short *ucs;
@@ -683,7 +691,7 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
683 const unsigned char *bits; 691 const unsigned char *bits;
684 692
685 /* get proportional width and glyph bits */ 693 /* get proportional width and glyph bits */
686 width = font_get_width(pf,ch); 694 width = font_get_width(pf, ch);
687 695
688 if (ofs > width) 696 if (ofs > width)
689 { 697 {
@@ -693,82 +701,84 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
693 701
694 bits = font_get_bits(pf, ch); 702 bits = font_get_bits(pf, ch);
695 703
696 lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, 704 LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs,
697 pf->height); 705 pf->height);
698 706
699 x += width - ofs; 707 x += width - ofs;
700 ofs = 0; 708 ofs = 0;
701 } 709 }
702} 710}
703/* put a string at a given pixel position */ 711/* put a string at a given pixel position */
704void lcd_putsxy(int x, int y, const unsigned char *str) 712void LCDFN(putsxy)(int x, int y, const unsigned char *str)
705{ 713{
706 lcd_putsxyofs(x, y, 0, str); 714 LCDFN(putsxyofs)(x, y, 0, str);
707} 715}
708 716
709/*** Line oriented text output ***/ 717/*** Line oriented text output ***/
710 718
711/* put a string at a given char position */ 719/* put a string at a given char position */
712void lcd_puts(int x, int y, const unsigned char *str) 720void LCDFN(puts)(int x, int y, const unsigned char *str)
713{ 721{
714 lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, 0); 722 LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, 0);
715} 723}
716 724
717void lcd_puts_style(int x, int y, const unsigned char *str, int style) 725void LCDFN(puts_style)(int x, int y, const unsigned char *str, int style)
718{ 726{
719 lcd_puts_style_offset(x, y, str, style, 0); 727 LCDFN(puts_style_offset)(x, y, str, style, 0);
720} 728}
721 729
722void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) 730void LCDFN(puts_offset)(int x, int y, const unsigned char *str, int offset)
723{ 731{
724 lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, offset); 732 LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, offset);
725} 733}
726 734
727/* put a string at a given char position, style, and pixel position, 735/* put a string at a given char position, style, and pixel position,
728 * skipping first offset pixel columns */ 736 * skipping first offset pixel columns */
729void lcd_puts_style_offset(int x, int y, const unsigned char *str, 737void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str,
730 int style, int offset) 738 int style, int offset)
731{ 739{
732 int xpos,ypos,w,h,xrect; 740 int xpos,ypos,w,h,xrect;
733 int lastmode = current_vp->drawmode; 741 int lastmode = current_vp->drawmode;
734 742
735 /* make sure scrolling is turned off on the line we are updating */ 743 /* make sure scrolling is turned off on the line we are updating */
736 lcd_scroll_stop_line(current_vp, y); 744 LCDFN(scroll_stop_line)(current_vp, y);
737 745
738 if(!str || !str[0]) 746 if(!str || !str[0])
739 return; 747 return;
740 748
741 lcd_getstringsize(str, &w, &h); 749 LCDFN(getstringsize)(str, &w, &h);
742 xpos = current_vp->xmargin + x*w / utf8length(str); 750 xpos = current_vp->xmargin + x*w / utf8length(str);
743 ypos = current_vp->ymargin + y*h; 751 ypos = current_vp->ymargin + y*h;
744 current_vp->drawmode = (style & STYLE_INVERT) ? 752 current_vp->drawmode = (style & STYLE_INVERT) ?
745 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 753 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
746 lcd_putsxyofs(xpos, ypos, offset, str); 754 LCDFN(putsxyofs)(xpos, ypos, offset, str);
747 current_vp->drawmode ^= DRMODE_INVERSEVID; 755 current_vp->drawmode ^= DRMODE_INVERSEVID;
748 xrect = xpos + MAX(w - offset, 0); 756 xrect = xpos + MAX(w - offset, 0);
749 lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); 757 LCDFN(fillrect)(xrect, ypos, current_vp->width - xrect, h);
750 current_vp->drawmode = lastmode; 758 current_vp->drawmode = lastmode;
751} 759}
752 760
753/*** scrolling ***/ 761/*** scrolling ***/
754void lcd_puts_scroll(int x, int y, const unsigned char *string) 762
763void LCDFN(puts_scroll)(int x, int y, const unsigned char *string)
755{ 764{
756 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); 765 LCDFN(puts_scroll_style)(x, y, string, STYLE_DEFAULT);
757} 766}
758 767
759void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) 768void LCDFN(puts_scroll_style)(int x, int y, const unsigned char *string,
769 int style)
760{ 770{
761 lcd_puts_scroll_style_offset(x, y, string, style, 0); 771 LCDFN(puts_scroll_style_offset)(x, y, string, style, 0);
762} 772}
763 773
764void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, 774void LCDFN(puts_scroll_offset)(int x, int y, const unsigned char *string,
765 int offset) 775 int offset)
766{ 776{
767 lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); 777 LCDFN(puts_scroll_style_offset)(x, y, string, STYLE_DEFAULT, offset);
768} 778}
769 779
770void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, 780void LCDFN(puts_scroll_style_offset)(int x, int y, const unsigned char *string,
771 int style, int offset) 781 int style, int offset)
772{ 782{
773 struct scrollinfo* s; 783 struct scrollinfo* s;
774 int w, h; 784 int w, h;
@@ -777,21 +787,21 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
777 return; 787 return;
778 788
779 /* remove any previously scrolling line at the same location */ 789 /* remove any previously scrolling line at the same location */
780 lcd_scroll_stop_line(current_vp, y); 790 LCDFN(scroll_stop_line)(current_vp, y);
781 791
782 if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; 792 if (LCDFN(scroll_info.lines) >= LCDM(SCROLLABLE_LINES)) return;
783 793
784 s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; 794 s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines];
785 795
786 s->start_tick = current_tick + lcd_scroll_info.delay; 796 s->start_tick = current_tick + LCDFN(scroll_info).delay;
787 s->style = style; 797 s->style = style;
788 if (style & STYLE_INVERT) { 798 if (style & STYLE_INVERT) {
789 lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); 799 LCDFN(puts_style_offset)(x,y,string,STYLE_INVERT,offset);
790 } 800 }
791 else 801 else
792 lcd_puts_offset(x,y,string,offset); 802 LCDFN(puts_offset)(x,y,string,offset);
793 803
794 lcd_getstringsize(string, &w, &h); 804 LCDFN(getstringsize)(string, &w, &h);
795 805
796 if (current_vp->width - x * 8 - current_vp->xmargin < w) { 806 if (current_vp->width - x * 8 - current_vp->xmargin < w) {
797 /* prepare scroll line */ 807 /* prepare scroll line */
@@ -801,13 +811,13 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
801 strcpy(s->line, string); 811 strcpy(s->line, string);
802 812
803 /* get width */ 813 /* get width */
804 s->width = lcd_getstringsize(s->line, &w, &h); 814 s->width = LCDFN(getstringsize)(s->line, &w, &h);
805 815
806 /* scroll bidirectional or forward only depending on the string 816 /* scroll bidirectional or forward only depending on the string
807 width */ 817 width */
808 if ( lcd_scroll_info.bidir_limit ) { 818 if ( LCDFN(scroll_info).bidir_limit ) {
809 s->bidir = s->width < (current_vp->width - current_vp->xmargin) * 819 s->bidir = s->width < (current_vp->width - current_vp->xmargin) *
810 (100 + lcd_scroll_info.bidir_limit) / 100; 820 (100 + LCDFN(scroll_info).bidir_limit) / 100;
811 } 821 }
812 else 822 else
813 s->bidir = false; 823 s->bidir = false;
@@ -815,7 +825,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
815 if (!s->bidir) { /* add spaces if scrolling in the round */ 825 if (!s->bidir) { /* add spaces if scrolling in the round */
816 strcat(s->line, " "); 826 strcat(s->line, " ");
817 /* get new width incl. spaces */ 827 /* get new width incl. spaces */
818 s->width = lcd_getstringsize(s->line, &w, &h); 828 s->width = LCDFN(getstringsize)(s->line, &w, &h);
819 } 829 }
820 830
821 end = strchr(s->line, '\0'); 831 end = strchr(s->line, '\0');
@@ -827,11 +837,12 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
827 s->offset = offset; 837 s->offset = offset;
828 s->startx = current_vp->xmargin + x * s->width / s->len;; 838 s->startx = current_vp->xmargin + x * s->width / s->len;;
829 s->backward = false; 839 s->backward = false;
830 lcd_scroll_info.lines++; 840
841 LCDFN(scroll_info).lines++;
831 } 842 }
832} 843}
833 844
834void lcd_scroll_fn(void) 845void LCDFN(scroll_fn)(void)
835{ 846{
836 struct font* pf; 847 struct font* pf;
837 struct scrollinfo* s; 848 struct scrollinfo* s;
@@ -840,19 +851,19 @@ void lcd_scroll_fn(void)
840 int lastmode; 851 int lastmode;
841 struct viewport* old_vp = current_vp; 852 struct viewport* old_vp = current_vp;
842 853
843 for ( index = 0; index < lcd_scroll_info.lines; index++ ) { 854 for ( index = 0; index < LCDFN(scroll_info).lines; index++ ) {
844 s = &lcd_scroll_info.scroll[index]; 855 s = &LCDFN(scroll_info).scroll[index];
845 856
846 /* check pause */ 857 /* check pause */
847 if (TIME_BEFORE(current_tick, s->start_tick)) 858 if (TIME_BEFORE(current_tick, s->start_tick))
848 continue; 859 continue;
849 860
850 lcd_set_viewport(s->vp); 861 LCDFN(set_viewport)(s->vp);
851 862
852 if (s->backward) 863 if (s->backward)
853 s->offset -= lcd_scroll_info.step; 864 s->offset -= LCDFN(scroll_info).step;
854 else 865 else
855 s->offset += lcd_scroll_info.step; 866 s->offset += LCDFN(scroll_info).step;
856 867
857 pf = font_get(current_vp->font); 868 pf = font_get(current_vp->font);
858 xpos = s->startx; 869 xpos = s->startx;
@@ -863,13 +874,13 @@ void lcd_scroll_fn(void)
863 /* at beginning of line */ 874 /* at beginning of line */
864 s->offset = 0; 875 s->offset = 0;
865 s->backward = false; 876 s->backward = false;
866 s->start_tick = current_tick + lcd_scroll_info.delay * 2; 877 s->start_tick = current_tick + LCDFN(scroll_info).delay * 2;
867 } 878 }
868 if (s->offset >= s->width - (current_vp->width - xpos)) { 879 if (s->offset >= s->width - (current_vp->width - xpos)) {
869 /* at end of line */ 880 /* at end of line */
870 s->offset = s->width - (current_vp->width - xpos); 881 s->offset = s->width - (current_vp->width - xpos);
871 s->backward = true; 882 s->backward = true;
872 s->start_tick = current_tick + lcd_scroll_info.delay * 2; 883 s->start_tick = current_tick + LCDFN(scroll_info).delay * 2;
873 } 884 }
874 } 885 }
875 else { 886 else {
@@ -881,10 +892,10 @@ void lcd_scroll_fn(void)
881 lastmode = current_vp->drawmode; 892 lastmode = current_vp->drawmode;
882 current_vp->drawmode = (s->style&STYLE_INVERT) ? 893 current_vp->drawmode = (s->style&STYLE_INVERT) ?
883 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 894 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
884 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 895 LCDFN(putsxyofs)(xpos, ypos, s->offset, s->line);
885 current_vp->drawmode = lastmode; 896 current_vp->drawmode = lastmode;
886 lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height); 897 LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width - xpos, pf->height);
887 } 898 }
888 899
889 lcd_set_viewport(old_vp); 900 LCDFN(set_viewport)(old_vp);
890} 901}
diff --git a/firmware/drivers/lcd-remote-1bit-v.c b/firmware/drivers/lcd-remote-1bit-v.c
index 20c6f6655c..bed7cc6671 100644
--- a/firmware/drivers/lcd-remote-1bit-v.c
+++ b/firmware/drivers/lcd-remote-1bit-v.c
@@ -17,885 +17,11 @@
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19 19
20#include "config.h"
21#include "cpu.h"
22#include "lcd.h"
23#include "lcd-remote.h" 20#include "lcd-remote.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#include "rbunicode.h"
33#include "bidi.h"
34#include "scroll_engine.h"
35 21
36/*** globals ***/ 22/* Compile 1 bit vertical packing LCD driver for remote LCD */
23#define LCDFN(fn) lcd_remote_ ## fn
24#define FBFN(fn) fb_remote_ ## fn
25#define LCDM(ma) LCD_REMOTE_ ## ma
37 26
38fb_remote_data lcd_remote_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBWIDTH] 27#include "lcd-1bit-vert.c"
39 IBSS_ATTR;
40
41static struct viewport default_vp =
42{
43 .x = 0,
44 .y = 0,
45 .width = LCD_REMOTE_WIDTH,
46 .height = LCD_REMOTE_HEIGHT,
47 .font = FONT_SYSFIXED,
48 .drawmode = DRMODE_SOLID,
49 .xmargin = 0,
50 .ymargin = 0,
51};
52
53static struct viewport* current_vp IDATA_ATTR = &default_vp;
54
55/*** Viewports ***/
56
57void lcd_remote_set_viewport(struct viewport* vp)
58{
59 if (vp == NULL)
60 current_vp = &default_vp;
61 else
62 current_vp = vp;
63}
64
65void lcd_remote_update_viewport(void)
66{
67 lcd_remote_update_rect(current_vp->x, current_vp->y,
68 current_vp->width, current_vp->height);
69}
70
71void lcd_remote_update_viewport_rect(int x, int y, int width, int height)
72{
73 lcd_remote_update_rect(current_vp->x + x, current_vp->y + y, width, height);
74}
75
76
77/*** parameter handling ***/
78
79void lcd_remote_set_drawmode(int mode)
80{
81 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
82}
83
84int lcd_remote_get_drawmode(void)
85{
86 return current_vp->drawmode;
87}
88
89void lcd_remote_setmargins(int x, int y)
90{
91 current_vp->xmargin = x;
92 current_vp->ymargin = y;
93}
94
95int lcd_remote_getwidth(void)
96{
97 return current_vp->width;
98}
99
100int lcd_remote_getheight(void)
101{
102 return current_vp->height;
103}
104
105int lcd_remote_getxmargin(void)
106{
107 return current_vp->xmargin;
108}
109
110int lcd_remote_getymargin(void)
111{
112 return current_vp->ymargin;
113}
114
115void lcd_remote_setfont(int newfont)
116{
117 current_vp->font = newfont;
118}
119
120int lcd_remote_getfont(void)
121{
122 return current_vp->font;
123}
124
125int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h)
126{
127 return font_getstringsize(str, w, h, current_vp->font);
128}
129
130/*** low-level drawing functions ***/
131
132static void setpixel(int x, int y)
133{
134 lcd_remote_framebuffer[y>>3][x] |= 1 << (y & 7);
135}
136
137static void clearpixel(int x, int y)
138{
139 lcd_remote_framebuffer[y>>3][x] &= ~(1 << (y & 7));
140}
141
142static void flippixel(int x, int y)
143{
144 lcd_remote_framebuffer[y>>3][x] ^= 1 << (y & 7);
145}
146
147static void nopixel(int x, int y)
148{
149 (void)x;
150 (void)y;
151}
152
153lcd_remote_pixelfunc_type* const lcd_remote_pixelfuncs[8] = {
154 flippixel, nopixel, setpixel, setpixel,
155 nopixel, clearpixel, nopixel, clearpixel
156};
157
158static void flipblock(fb_remote_data *address, unsigned mask, unsigned bits)
159 ICODE_ATTR;
160static void flipblock(fb_remote_data *address, unsigned mask, unsigned bits)
161{
162 *address ^= bits & mask;
163}
164
165static void bgblock(fb_remote_data *address, unsigned mask, unsigned bits)
166 ICODE_ATTR;
167static void bgblock(fb_remote_data *address, unsigned mask, unsigned bits)
168{
169 *address &= bits | ~mask;
170}
171
172static void fgblock(fb_remote_data *address, unsigned mask, unsigned bits)
173 ICODE_ATTR;
174static void fgblock(fb_remote_data *address, unsigned mask, unsigned bits)
175{
176 *address |= bits & mask;
177}
178
179static void solidblock(fb_remote_data *address, unsigned mask, unsigned bits)
180 ICODE_ATTR;
181static void solidblock(fb_remote_data *address, unsigned mask, unsigned bits)
182{
183 unsigned data = *address;
184
185 bits ^= data;
186 *address = data ^ (bits & mask);
187}
188
189static void flipinvblock(fb_remote_data *address, unsigned mask, unsigned bits)
190 ICODE_ATTR;
191static void flipinvblock(fb_remote_data *address, unsigned mask, unsigned bits)
192{
193 *address ^= ~bits & mask;
194}
195
196static void bginvblock(fb_remote_data *address, unsigned mask, unsigned bits)
197 ICODE_ATTR;
198static void bginvblock(fb_remote_data *address, unsigned mask, unsigned bits)
199{
200 *address &= ~(bits & mask);
201}
202
203static void fginvblock(fb_remote_data *address, unsigned mask, unsigned bits)
204 ICODE_ATTR;
205static void fginvblock(fb_remote_data *address, unsigned mask, unsigned bits)
206{
207 *address |= ~bits & mask;
208}
209
210static void solidinvblock(fb_remote_data *address, unsigned mask, unsigned bits)
211 ICODE_ATTR;
212static void solidinvblock(fb_remote_data *address, unsigned mask, unsigned bits)
213{
214 unsigned data = *address;
215
216 bits = ~bits ^ data;
217 *address = data ^ (bits & mask);
218}
219
220lcd_remote_blockfunc_type* const lcd_remote_blockfuncs[8] = {
221 flipblock, bgblock, fgblock, solidblock,
222 flipinvblock, bginvblock, fginvblock, solidinvblock
223};
224
225/*** drawing functions ***/
226
227/* Clear the whole display */
228void lcd_remote_clear_display(void)
229{
230 unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0;
231
232 memset(lcd_remote_framebuffer, bits, sizeof lcd_remote_framebuffer);
233
234 lcd_remote_scroll_info.lines = 0;
235}
236
237/* Clear the current viewport */
238void lcd_remote_clear_viewport(void)
239{
240 int oldmode;
241
242 if (current_vp == &default_vp)
243 {
244 lcd_remote_clear_display();
245 }
246 else
247 {
248 oldmode = current_vp->drawmode;
249
250 /* Invert the INVERSEVID bit and set basic mode to SOLID */
251 current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) |
252 DRMODE_SOLID;
253
254 lcd_remote_fillrect(0, 0, current_vp->width, current_vp->height);
255
256 current_vp->drawmode = oldmode;
257
258 lcd_remote_scroll_stop(current_vp);
259 }
260}
261
262/* Set a single pixel */
263void lcd_remote_drawpixel(int x, int y)
264{
265 if (((unsigned)x < (unsigned)current_vp->width) &&
266 ((unsigned)y < (unsigned)current_vp->height))
267 lcd_remote_pixelfuncs[current_vp->drawmode](current_vp->x+x, current_vp->y+y);
268}
269
270/* Draw a line */
271void lcd_remote_drawline(int x1, int y1, int x2, int y2)
272{
273 int numpixels;
274 int i;
275 int deltax, deltay;
276 int d, dinc1, dinc2;
277 int x, xinc1, xinc2;
278 int y, yinc1, yinc2;
279 lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[current_vp->drawmode];
280
281 deltax = abs(x2 - x1);
282 deltay = abs(y2 - y1);
283 xinc2 = 1;
284 yinc2 = 1;
285
286 if (deltax >= deltay)
287 {
288 numpixels = deltax;
289 d = 2 * deltay - deltax;
290 dinc1 = deltay * 2;
291 dinc2 = (deltay - deltax) * 2;
292 xinc1 = 1;
293 yinc1 = 0;
294 }
295 else
296 {
297 numpixels = deltay;
298 d = 2 * deltax - deltay;
299 dinc1 = deltax * 2;
300 dinc2 = (deltax - deltay) * 2;
301 xinc1 = 0;
302 yinc1 = 1;
303 }
304 numpixels++; /* include endpoints */
305
306 if (x1 > x2)
307 {
308 xinc1 = -xinc1;
309 xinc2 = -xinc2;
310 }
311
312 if (y1 > y2)
313 {
314 yinc1 = -yinc1;
315 yinc2 = -yinc2;
316 }
317
318 x = x1;
319 y = y1;
320
321 for (i = 0; i < numpixels; i++)
322 {
323 if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height))
324 pfunc(x + current_vp->x, y + current_vp->y);
325
326 if (d < 0)
327 {
328 d += dinc1;
329 x += xinc1;
330 y += yinc1;
331 }
332 else
333 {
334 d += dinc2;
335 x += xinc2;
336 y += yinc2;
337 }
338 }
339}
340
341/* Draw a horizontal line (optimised) */
342void lcd_remote_hline(int x1, int x2, int y)
343{
344 int x, width;
345 fb_remote_data *dst, *dst_end;
346 unsigned mask;
347 lcd_remote_blockfunc_type *bfunc;
348
349 /* direction flip */
350 if (x2 < x1)
351 {
352 x = x1;
353 x1 = x2;
354 x2 = x;
355 }
356
357 /* nothing to draw? */
358 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width)
359 || (x2 < 0))
360 return;
361
362 /* clipping */
363 if (x1 < 0)
364 x1 = 0;
365 if (x2 >= current_vp->width)
366 x2 = current_vp->width-1;
367
368 width = x2 - x1 + 1;
369
370 /* Adjust x1 and y to viewport */
371 x1 += current_vp->x;
372 y += current_vp->y;
373
374 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
375 dst = &lcd_remote_framebuffer[y>>3][x1];
376 mask = 1 << (y & 7);
377
378 dst_end = dst + width;
379 do
380 bfunc(dst++, mask, 0xFFu);
381 while (dst < dst_end);
382}
383
384/* Draw a vertical line (optimised) */
385void lcd_remote_vline(int x, int y1, int y2)
386{
387 int ny;
388 fb_remote_data *dst;
389 unsigned mask, mask_bottom;
390 lcd_remote_blockfunc_type *bfunc;
391
392 /* direction flip */
393 if (y2 < y1)
394 {
395 ny = y1;
396 y1 = y2;
397 y2 = ny;
398 }
399
400 /* nothing to draw? */
401 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height)
402 || (y2 < 0))
403 return;
404
405 /* clipping */
406 if (y1 < 0)
407 y1 = 0;
408 if (y2 >= current_vp->height)
409 y2 = current_vp->height-1;
410
411 /* adjust for viewport */
412 y1 += current_vp->y;
413 y2 += current_vp->y;
414 x += current_vp->x;
415
416 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
417 dst = &lcd_remote_framebuffer[y1>>3][x];
418 ny = y2 - (y1 & ~7);
419 mask = 0xFFu << (y1 & 7);
420 mask_bottom = 0xFFu >> (~ny & 7);
421
422 for (; ny >= 8; ny -= 8)
423 {
424 bfunc(dst, mask, 0xFFu);
425 dst += LCD_REMOTE_WIDTH;
426 mask = 0xFFu;
427 }
428 mask &= mask_bottom;
429 bfunc(dst, mask, 0xFFu);
430}
431
432/* Draw a rectangular box */
433void lcd_remote_drawrect(int x, int y, int width, int height)
434{
435 if ((width <= 0) || (height <= 0))
436 return;
437
438 int x2 = x + width - 1;
439 int y2 = y + height - 1;
440
441 lcd_remote_vline(x, y, y2);
442 lcd_remote_vline(x2, y, y2);
443 lcd_remote_hline(x, x2, y);
444 lcd_remote_hline(x, x2, y2);
445}
446
447/* Fill a rectangular area */
448void lcd_remote_fillrect(int x, int y, int width, int height)
449{
450 int ny;
451 fb_remote_data *dst, *dst_end;
452 unsigned mask, mask_bottom;
453 unsigned bits = 0;
454 lcd_remote_blockfunc_type *bfunc;
455 bool fillopt = false;
456
457 /* nothing to draw? */
458 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
459 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
460 return;
461
462 /* clipping */
463 if (x < 0)
464 {
465 width += x;
466 x = 0;
467 }
468 if (y < 0)
469 {
470 height += y;
471 y = 0;
472 }
473 if (x + width > current_vp->width)
474 width = current_vp->width - x;
475 if (y + height > current_vp->height)
476 height = current_vp->height - y;
477
478 /* adjust for viewport */
479 x += current_vp->x;
480 y += current_vp->y;
481
482 if (current_vp->drawmode & DRMODE_INVERSEVID)
483 {
484 if (current_vp->drawmode & DRMODE_BG)
485 {
486 fillopt = true;
487 }
488 }
489 else
490 {
491 if (current_vp->drawmode & DRMODE_FG)
492 {
493 fillopt = true;
494 bits = 0xFFu;
495 }
496 }
497
498 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
499 dst = &lcd_remote_framebuffer[y>>3][x];
500 ny = height - 1 + (y & 7);
501 mask = 0xFFu << (y & 7);
502 mask_bottom = 0xFFu >> (~ny & 7);
503
504 for (; ny >= 8; ny -= 8)
505 {
506 if (fillopt && (mask == 0xFFu))
507 memset(dst, bits, width);
508 else
509 {
510 fb_remote_data *dst_row = dst;
511
512 dst_end = dst_row + width;
513 do
514 bfunc(dst_row++, mask, 0xFFu);
515 while (dst_row < dst_end);
516 }
517
518 dst += LCD_REMOTE_WIDTH;
519 mask = 0xFFu;
520 }
521 mask &= mask_bottom;
522
523 if (fillopt && (mask == 0xFFu))
524 memset(dst, bits, width);
525 else
526 {
527 dst_end = dst + width;
528 do
529 bfunc(dst++, mask, 0xFFu);
530 while (dst < dst_end);
531 }
532}
533
534/* About Rockbox' internal bitmap format:
535 *
536 * A bitmap contains one bit for every pixel that defines if that pixel is
537 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
538 * at top.
539 * The bytes are stored in row-major order, with byte 0 being top left,
540 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
541 * 0..7, the second row defines pixel row 8..15 etc.
542 *
543 * This is the same as the internal lcd hw format. */
544
545/* Draw a partial bitmap */
546void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y,
547 int stride, int x, int y, int width, int height)
548 ICODE_ATTR;
549void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y,
550 int stride, int x, int y, int width, int height)
551{
552 int shift, ny;
553 fb_remote_data *dst, *dst_end;
554 unsigned mask, mask_bottom;
555 lcd_remote_blockfunc_type *bfunc;
556
557 /* nothing to draw? */
558 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
559 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
560 return;
561
562 /* clipping */
563 if (x < 0)
564 {
565 width += x;
566 src_x -= x;
567 x = 0;
568 }
569 if (y < 0)
570 {
571 height += y;
572 src_y -= y;
573 y = 0;
574 }
575 if (x + width > current_vp->width)
576 width = current_vp->width - x;
577 if (y + height > current_vp->height)
578 height = current_vp->height - y;
579
580 /* adjust for viewports */
581 x += current_vp->x;
582 y += current_vp->y;
583
584 src += stride * (src_y >> 3) + src_x; /* move starting point */
585 src_y &= 7;
586 y -= src_y;
587 dst = &lcd_remote_framebuffer[y>>3][x];
588 shift = y & 7;
589 ny = height - 1 + shift + src_y;
590
591 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
592 mask = 0xFFu << (shift + src_y);
593 mask_bottom = 0xFFu >> (~ny & 7);
594
595 if (shift == 0)
596 {
597 bool copyopt = (current_vp->drawmode == DRMODE_SOLID);
598
599 for (; ny >= 8; ny -= 8)
600 {
601 if (copyopt && (mask == 0xFFu))
602 memcpy(dst, src, width);
603 else
604 {
605 const unsigned char *src_row = src;
606 fb_remote_data *dst_row = dst;
607
608 dst_end = dst_row + width;
609 do
610 bfunc(dst_row++, mask, *src_row++);
611 while (dst_row < dst_end);
612 }
613
614 src += stride;
615 dst += LCD_REMOTE_WIDTH;
616 mask = 0xFFu;
617 }
618 mask &= mask_bottom;
619
620 if (copyopt && (mask == 0xFFu))
621 memcpy(dst, src, width);
622 else
623 {
624 dst_end = dst + width;
625 do
626 bfunc(dst++, mask, *src++);
627 while (dst < dst_end);
628 }
629 }
630 else
631 {
632 dst_end = dst + width;
633 do
634 {
635 const unsigned char *src_col = src++;
636 fb_remote_data *dst_col = dst++;
637 unsigned mask_col = mask;
638 unsigned data = 0;
639
640 for (y = ny; y >= 8; y -= 8)
641 {
642 data |= *src_col << shift;
643
644 if (mask_col & 0xFFu)
645 {
646 bfunc(dst_col, mask_col, data);
647 mask_col = 0xFFu;
648 }
649 else
650 mask_col >>= 8;
651
652 src_col += stride;
653 dst_col += LCD_REMOTE_WIDTH;
654 data >>= 8;
655 }
656 data |= *src_col << shift;
657 bfunc(dst_col, mask_col & mask_bottom, data);
658 }
659 while (dst < dst_end);
660 }
661}
662
663/* Draw a full bitmap */
664void lcd_remote_bitmap(const unsigned char *src, int x, int y, int width,
665 int height)
666{
667 lcd_remote_bitmap_part(src, 0, 0, width, x, y, width, height);
668}
669
670/* put a string at a given pixel position, skipping first ofs pixel columns */
671void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str)
672{
673 unsigned short ch;
674 unsigned short *ucs;
675 struct font* pf = font_get(current_vp->font);
676
677 ucs = bidi_l2v(str, 1);
678
679 while ((ch = *ucs++) != 0 && x < current_vp->width)
680 {
681 int width;
682 const unsigned char *bits;
683
684 /* get proportional width and glyph bits */
685 width = font_get_width(pf, ch);
686
687 if (ofs > width)
688 {
689 ofs -= width;
690 continue;
691 }
692
693 bits = font_get_bits(pf, ch);
694
695 lcd_remote_bitmap_part(bits, ofs, 0, width, x, y, width - ofs,
696 pf->height);
697
698 x += width - ofs;
699 ofs = 0;
700 }
701}
702
703/* put a string at a given pixel position */
704void lcd_remote_putsxy(int x, int y, const unsigned char *str)
705{
706 lcd_remote_putsxyofs(x, y, 0, str);
707}
708
709/*** line oriented text output ***/
710
711/* put a string at a given char position */
712void lcd_remote_puts(int x, int y, const unsigned char *str)
713{
714 lcd_remote_puts_style_offset(x, y, str, STYLE_DEFAULT, 0);
715}
716
717void lcd_remote_puts_style(int x, int y, const unsigned char *str, int style)
718{
719 lcd_remote_puts_style_offset(x, y, str, style, 0);
720}
721
722void lcd_remote_puts_offset(int x, int y, const unsigned char *str, int offset)
723{
724 lcd_remote_puts_style_offset(x, y, str, STYLE_DEFAULT, offset);
725}
726
727/* put a string at a given char position, style, and pixel position,
728 * skipping first offset pixel columns */
729void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str,
730 int style, int offset)
731{
732 int xpos,ypos,w,h,xrect;
733 int lastmode = current_vp->drawmode;
734
735 /* make sure scrolling is turned off on the line we are updating */
736 lcd_remote_scroll_stop_line(current_vp, y);
737
738 if(!str || !str[0])
739 return;
740
741 lcd_remote_getstringsize(str, &w, &h);
742 xpos = current_vp->xmargin + x*w / utf8length((char *)str);
743 ypos = current_vp->ymargin + y*h;
744 current_vp->drawmode = (style & STYLE_INVERT) ?
745 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
746 lcd_remote_putsxyofs(xpos, ypos, offset, str);
747 current_vp->drawmode ^= DRMODE_INVERSEVID;
748 xrect = xpos + MAX(w - offset, 0);
749 lcd_remote_fillrect(xrect, ypos, current_vp->width - xrect, h);
750 current_vp->drawmode = lastmode;
751}
752
753/*** scrolling ***/
754
755void lcd_remote_puts_scroll(int x, int y, const unsigned char *string)
756{
757 lcd_remote_puts_scroll_style(x, y, string, STYLE_DEFAULT);
758}
759
760void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int style)
761{
762 lcd_remote_puts_scroll_style_offset(x, y, string, style, 0);
763}
764
765void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string, int offset)
766{
767 lcd_remote_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset);
768}
769
770void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *string,
771 int style, int offset)
772{
773 struct scrollinfo* s;
774 int w, h;
775
776 if ((unsigned)y >= (unsigned)current_vp->height)
777 return;
778
779 /* remove any previously scrolling line at the same location */
780 lcd_remote_scroll_stop_line(current_vp, y);
781
782 if (lcd_remote_scroll_info.lines >= LCD_REMOTE_SCROLLABLE_LINES) return;
783
784 s = &lcd_remote_scroll_info.scroll[lcd_remote_scroll_info.lines];
785
786 s->start_tick = current_tick + lcd_remote_scroll_info.delay;
787 s->style = style;
788 if (style & STYLE_INVERT) {
789 lcd_remote_puts_style_offset(x,y,string,STYLE_INVERT,offset);
790 }
791 else
792 lcd_remote_puts_offset(x,y,string,offset);
793
794 lcd_remote_getstringsize(string, &w, &h);
795
796 if (current_vp->width - x * 8 - current_vp->xmargin < w) {
797 /* prepare scroll line */
798 char *end;
799
800 memset(s->line, 0, sizeof s->line);
801 strcpy(s->line, (char *)string);
802
803 /* get width */
804 s->width = lcd_remote_getstringsize((unsigned char *)s->line, &w, &h);
805
806 /* scroll bidirectional or forward only depending on the string
807 width */
808 if ( lcd_remote_scroll_info.bidir_limit ) {
809 s->bidir = s->width < (current_vp->width - current_vp->xmargin) *
810 (100 + lcd_remote_scroll_info.bidir_limit) / 100;
811 }
812 else
813 s->bidir = false;
814
815 if (!s->bidir) { /* add spaces if scrolling in the round */
816 strcat(s->line, " ");
817 /* get new width incl. spaces */
818 s->width = lcd_remote_getstringsize((unsigned char *)s->line, &w, &h);
819 }
820
821 end = strchr(s->line, '\0');
822 strncpy(end, (char *)string, current_vp->width/2);
823
824 s->vp = current_vp;
825 s->y = y;
826 s->len = utf8length((char *)string);
827 s->offset = offset;
828 s->startx = current_vp->xmargin + x * s->width / s->len;
829 s->backward = false;
830
831 lcd_remote_scroll_info.lines++;
832 }
833}
834
835void lcd_remote_scroll_fn(void)
836{
837 struct font* pf;
838 struct scrollinfo* s;
839 int index;
840 int xpos, ypos;
841 int lastmode;
842 struct viewport* old_vp = current_vp;
843
844 for ( index = 0; index < lcd_remote_scroll_info.lines; index++ ) {
845 s = &lcd_remote_scroll_info.scroll[index];
846
847 /* check pause */
848 if (TIME_BEFORE(current_tick, s->start_tick))
849 continue;
850
851 lcd_remote_set_viewport(s->vp);
852
853 if (s->backward)
854 s->offset -= lcd_remote_scroll_info.step;
855 else
856 s->offset += lcd_remote_scroll_info.step;
857
858 pf = font_get(current_vp->font);
859 xpos = s->startx;
860 ypos = current_vp->ymargin + s->y * pf->height;
861
862 if (s->bidir) { /* scroll bidirectional */
863 if (s->offset <= 0) {
864 /* at beginning of line */
865 s->offset = 0;
866 s->backward = false;
867 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
868 }
869 if (s->offset >= s->width - (current_vp->width - xpos)) {
870 /* at end of line */
871 s->offset = s->width - (current_vp->width - xpos);
872 s->backward = true;
873 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
874 }
875 }
876 else {
877 /* scroll forward the whole time */
878 if (s->offset >= s->width)
879 s->offset %= s->width;
880 }
881
882 lastmode = current_vp->drawmode;
883 current_vp->drawmode = (s->style&STYLE_INVERT) ?
884 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
885 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
886 current_vp->drawmode = lastmode;
887 lcd_remote_update_viewport_rect(xpos, ypos,
888 current_vp->width - xpos, pf->height);
889 }
890
891 lcd_remote_set_viewport(old_vp);
892}
893
894/* LCD init */
895void lcd_remote_init(void)
896{
897#ifndef SIMULATOR
898 /* Call device specific init */
899 lcd_remote_init_device();
900#endif
901}