diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-1bit-vert.c | 329 | ||||
-rw-r--r-- | firmware/drivers/lcd-remote-1bit-v.c | 884 |
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 | ||
36 | unsigned char lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; | 44 | FBFN(data) LCDFN(framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] |
45 | #if CONFIG_CPU != SH7034 | ||
46 | IBSS_ATTR | ||
47 | #endif | ||
48 | ; | ||
37 | 49 | ||
38 | static struct viewport default_vp = | 50 | static 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 | ||
54 | void lcd_set_viewport(struct viewport* vp) | 66 | void 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 | ||
62 | void lcd_update_viewport(void) | 74 | void 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 | ||
68 | void lcd_update_viewport_rect(int x, int y, int width, int height) | 80 | void 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 */ |
74 | void lcd_init(void) | 86 | void 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 | ||
84 | void lcd_set_drawmode(int mode) | 99 | void 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 | ||
89 | int lcd_get_drawmode(void) | 104 | int LCDFN(get_drawmode)(void) |
90 | { | 105 | { |
91 | return current_vp->drawmode; | 106 | return current_vp->drawmode; |
92 | } | 107 | } |
93 | 108 | ||
94 | void lcd_setmargins(int x, int y) | 109 | void 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 | ||
100 | int lcd_getxmargin(void) | 115 | int LCDFN(getxmargin)(void) |
101 | { | 116 | { |
102 | return current_vp->xmargin; | 117 | return current_vp->xmargin; |
103 | } | 118 | } |
104 | 119 | ||
105 | int lcd_getymargin(void) | 120 | int LCDFN(getymargin)(void) |
106 | { | 121 | { |
107 | return current_vp->ymargin; | 122 | return current_vp->ymargin; |
108 | } | 123 | } |
109 | 124 | ||
110 | int lcd_getwidth(void) | 125 | int LCDFN(getwidth)(void) |
111 | { | 126 | { |
112 | return current_vp->width; | 127 | return current_vp->width; |
113 | } | 128 | } |
114 | 129 | ||
115 | int lcd_getheight(void) | 130 | int LCDFN(getheight)(void) |
116 | { | 131 | { |
117 | return current_vp->height; | 132 | return current_vp->height; |
118 | } | 133 | } |
119 | 134 | ||
120 | void lcd_setfont(int newfont) | 135 | void LCDFN(setfont)(int newfont) |
121 | { | 136 | { |
122 | current_vp->font = newfont; | 137 | current_vp->font = newfont; |
123 | } | 138 | } |
124 | 139 | ||
125 | int lcd_getfont(void) | 140 | int LCDFN(getfont)(void) |
126 | { | 141 | { |
127 | return current_vp->font; | 142 | return current_vp->font; |
128 | } | 143 | } |
129 | 144 | ||
130 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 145 | int 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 | ||
137 | static void setpixel(int x, int y) | 152 | static 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 | ||
142 | static void clearpixel(int x, int y) | 157 | static 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 | ||
147 | static void flippixel(int x, int y) | 162 | static 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 | ||
152 | static void nopixel(int x, int y) | 167 | static 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 | ||
158 | lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { | 173 | LCDFN(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 | ||
163 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | 178 | static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask, |
164 | ICODE_ATTR; | 179 | unsigned bits) |
165 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | ||
166 | { | 180 | { |
167 | *address ^= bits & mask; | 181 | *address ^= bits & mask; |
168 | } | 182 | } |
169 | 183 | ||
170 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) | 184 | static void ICODE_ATTR bgblock(FBFN(data) *address, unsigned mask, |
171 | ICODE_ATTR; | 185 | unsigned bits) |
172 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) | ||
173 | { | 186 | { |
174 | *address &= bits | ~mask; | 187 | *address &= bits | ~mask; |
175 | } | 188 | } |
176 | 189 | ||
177 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) | 190 | static void ICODE_ATTR fgblock(FBFN(data) *address, unsigned mask, |
178 | ICODE_ATTR; | 191 | unsigned bits) |
179 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) | ||
180 | { | 192 | { |
181 | *address |= bits & mask; | 193 | *address |= bits & mask; |
182 | } | 194 | } |
183 | 195 | ||
184 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) | 196 | static void ICODE_ATTR solidblock(FBFN(data) *address, unsigned mask, |
185 | ICODE_ATTR; | 197 | unsigned bits) |
186 | static 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 | ||
194 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) | 205 | static void ICODE_ATTR flipinvblock(FBFN(data) *address, unsigned mask, |
195 | ICODE_ATTR; | 206 | unsigned bits) |
196 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
197 | { | 207 | { |
198 | *address ^= ~bits & mask; | 208 | *address ^= ~bits & mask; |
199 | } | 209 | } |
200 | 210 | ||
201 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) | 211 | static void ICODE_ATTR bginvblock(FBFN(data) *address, unsigned mask, |
202 | ICODE_ATTR; | 212 | unsigned bits) |
203 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
204 | { | 213 | { |
205 | *address &= ~(bits & mask); | 214 | *address &= ~(bits & mask); |
206 | } | 215 | } |
207 | 216 | ||
208 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) | 217 | static void ICODE_ATTR fginvblock(FBFN(data) *address, unsigned mask, |
209 | ICODE_ATTR; | 218 | unsigned bits) |
210 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
211 | { | 219 | { |
212 | *address |= ~bits & mask; | 220 | *address |= ~bits & mask; |
213 | } | 221 | } |
214 | 222 | ||
215 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) | 223 | static void ICODE_ATTR solidinvblock(FBFN(data) *address, unsigned mask, |
216 | ICODE_ATTR; | 224 | unsigned bits) |
217 | static 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 | ||
225 | lcd_blockfunc_type* const lcd_blockfuncs[8] = { | 232 | LCDFN(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 */ |
233 | void lcd_clear_display(void) | 240 | void 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 | ||
241 | void lcd_clear_viewport(void) | 248 | /* Clear the current viewport */ |
249 | void 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 */ |
266 | void lcd_drawpixel(int x, int y) | 274 | void 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 */ |
274 | void lcd_drawline(int x1, int y1, int x2, int y2) | 282 | void 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) */ |
346 | void lcd_hline(int x1, int x2, int y) | 354 | void 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) */ |
388 | void lcd_vline(int x, int y1, int y2) | 397 | void 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 */ |
436 | void lcd_drawrect(int x, int y, int width, int height) | 445 | void 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 */ |
451 | void lcd_fillrect(int x, int y, int width, int height) | 460 | void 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 */ |
548 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | 557 | void 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) |
551 | void 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 */ |
666 | void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) | 673 | void 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 */ |
672 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | 680 | static 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 */ |
704 | void lcd_putsxy(int x, int y, const unsigned char *str) | 712 | void 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 */ |
712 | void lcd_puts(int x, int y, const unsigned char *str) | 720 | void 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 | ||
717 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | 725 | void 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 | ||
722 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | 730 | void 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 */ |
729 | void lcd_puts_style_offset(int x, int y, const unsigned char *str, | 737 | void 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 ***/ |
754 | void lcd_puts_scroll(int x, int y, const unsigned char *string) | 762 | |
763 | void 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 | ||
759 | void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) | 768 | void 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 | ||
764 | void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | 774 | void 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 | ||
770 | void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | 780 | void 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 | ||
834 | void lcd_scroll_fn(void) | 845 | void 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 | ||
38 | fb_remote_data lcd_remote_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBWIDTH] | 27 | #include "lcd-1bit-vert.c" |
39 | IBSS_ATTR; | ||
40 | |||
41 | static 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 | |||
53 | static struct viewport* current_vp IDATA_ATTR = &default_vp; | ||
54 | |||
55 | /*** Viewports ***/ | ||
56 | |||
57 | void 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 | |||
65 | void 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 | |||
71 | void 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 | |||
79 | void lcd_remote_set_drawmode(int mode) | ||
80 | { | ||
81 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | ||
82 | } | ||
83 | |||
84 | int lcd_remote_get_drawmode(void) | ||
85 | { | ||
86 | return current_vp->drawmode; | ||
87 | } | ||
88 | |||
89 | void lcd_remote_setmargins(int x, int y) | ||
90 | { | ||
91 | current_vp->xmargin = x; | ||
92 | current_vp->ymargin = y; | ||
93 | } | ||
94 | |||
95 | int lcd_remote_getwidth(void) | ||
96 | { | ||
97 | return current_vp->width; | ||
98 | } | ||
99 | |||
100 | int lcd_remote_getheight(void) | ||
101 | { | ||
102 | return current_vp->height; | ||
103 | } | ||
104 | |||
105 | int lcd_remote_getxmargin(void) | ||
106 | { | ||
107 | return current_vp->xmargin; | ||
108 | } | ||
109 | |||
110 | int lcd_remote_getymargin(void) | ||
111 | { | ||
112 | return current_vp->ymargin; | ||
113 | } | ||
114 | |||
115 | void lcd_remote_setfont(int newfont) | ||
116 | { | ||
117 | current_vp->font = newfont; | ||
118 | } | ||
119 | |||
120 | int lcd_remote_getfont(void) | ||
121 | { | ||
122 | return current_vp->font; | ||
123 | } | ||
124 | |||
125 | int 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 | |||
132 | static void setpixel(int x, int y) | ||
133 | { | ||
134 | lcd_remote_framebuffer[y>>3][x] |= 1 << (y & 7); | ||
135 | } | ||
136 | |||
137 | static void clearpixel(int x, int y) | ||
138 | { | ||
139 | lcd_remote_framebuffer[y>>3][x] &= ~(1 << (y & 7)); | ||
140 | } | ||
141 | |||
142 | static void flippixel(int x, int y) | ||
143 | { | ||
144 | lcd_remote_framebuffer[y>>3][x] ^= 1 << (y & 7); | ||
145 | } | ||
146 | |||
147 | static void nopixel(int x, int y) | ||
148 | { | ||
149 | (void)x; | ||
150 | (void)y; | ||
151 | } | ||
152 | |||
153 | lcd_remote_pixelfunc_type* const lcd_remote_pixelfuncs[8] = { | ||
154 | flippixel, nopixel, setpixel, setpixel, | ||
155 | nopixel, clearpixel, nopixel, clearpixel | ||
156 | }; | ||
157 | |||
158 | static void flipblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
159 | ICODE_ATTR; | ||
160 | static void flipblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
161 | { | ||
162 | *address ^= bits & mask; | ||
163 | } | ||
164 | |||
165 | static void bgblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
166 | ICODE_ATTR; | ||
167 | static void bgblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
168 | { | ||
169 | *address &= bits | ~mask; | ||
170 | } | ||
171 | |||
172 | static void fgblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
173 | ICODE_ATTR; | ||
174 | static void fgblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
175 | { | ||
176 | *address |= bits & mask; | ||
177 | } | ||
178 | |||
179 | static void solidblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
180 | ICODE_ATTR; | ||
181 | static 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 | |||
189 | static void flipinvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
190 | ICODE_ATTR; | ||
191 | static void flipinvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
192 | { | ||
193 | *address ^= ~bits & mask; | ||
194 | } | ||
195 | |||
196 | static void bginvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
197 | ICODE_ATTR; | ||
198 | static void bginvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
199 | { | ||
200 | *address &= ~(bits & mask); | ||
201 | } | ||
202 | |||
203 | static void fginvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
204 | ICODE_ATTR; | ||
205 | static void fginvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
206 | { | ||
207 | *address |= ~bits & mask; | ||
208 | } | ||
209 | |||
210 | static void solidinvblock(fb_remote_data *address, unsigned mask, unsigned bits) | ||
211 | ICODE_ATTR; | ||
212 | static 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 | |||
220 | lcd_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 */ | ||
228 | void 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 */ | ||
238 | void 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 */ | ||
263 | void 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 */ | ||
271 | void 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) */ | ||
342 | void 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) */ | ||
385 | void 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 */ | ||
433 | void 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 */ | ||
448 | void 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 */ | ||
546 | void 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; | ||
549 | void 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 */ | ||
664 | void 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 */ | ||
671 | void 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 */ | ||
704 | void 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 */ | ||
712 | void 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 | |||
717 | void 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 | |||
722 | void 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 */ | ||
729 | void 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 | |||
755 | void 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 | |||
760 | void 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 | |||
765 | void 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 | |||
770 | void 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 | |||
835 | void 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 */ | ||
895 | void lcd_remote_init(void) | ||
896 | { | ||
897 | #ifndef SIMULATOR | ||
898 | /* Call device specific init */ | ||
899 | lcd_remote_init_device(); | ||
900 | #endif | ||
901 | } | ||