diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-h100.c | 387 | ||||
-rw-r--r-- | firmware/drivers/lcd-recorder.c | 374 | ||||
-rw-r--r-- | firmware/export/lcd.h | 26 |
3 files changed, 497 insertions, 290 deletions
diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c index af3782c0b3..2b0326eb3b 100644 --- a/firmware/drivers/lcd-h100.c +++ b/firmware/drivers/lcd-h100.c | |||
@@ -66,21 +66,10 @@ unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH] | |||
66 | #endif | 66 | #endif |
67 | ; | 67 | ; |
68 | 68 | ||
69 | static int drawmode = DRMODE_SOLID; | ||
69 | static int xmargin = 0; | 70 | static int xmargin = 0; |
70 | static int ymargin = 0; | 71 | static int ymargin = 0; |
71 | static int curfont = FONT_SYSFIXED; | 72 | static int curfont = FONT_SYSFIXED; |
72 | #ifndef SIMULATOR | ||
73 | static int xoffset = 0; /* needed for flip */ | ||
74 | #endif | ||
75 | |||
76 | /* All zeros and ones bitmaps for area filling */ | ||
77 | static const unsigned char zeros[16] = { | ||
78 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
79 | }; | ||
80 | static const unsigned char ones[16] = { | ||
81 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
82 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
83 | }; | ||
84 | 73 | ||
85 | /* scrolling */ | 74 | /* scrolling */ |
86 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 75 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
@@ -128,14 +117,12 @@ void lcd_set_flip(bool yesno) | |||
128 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 1); | 117 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 1); |
129 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 0); | 118 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 0); |
130 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 0); | 119 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 0); |
131 | xoffset = 160 - LCD_WIDTH; /* 160 colums minus the 160 we have */ | ||
132 | } | 120 | } |
133 | else | 121 | else |
134 | { | 122 | { |
135 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); | 123 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); |
136 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); | 124 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); |
137 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); | 125 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); |
138 | xoffset = 0; | ||
139 | } | 126 | } |
140 | } | 127 | } |
141 | 128 | ||
@@ -227,7 +214,7 @@ void lcd_blit(const unsigned char* p_data, int x, int y, int width, | |||
227 | while (height--) | 214 | while (height--) |
228 | { | 215 | { |
229 | lcd_write_command_ex(LCD_CNTL_PAGE, y++ & 0xf, -1); | 216 | lcd_write_command_ex(LCD_CNTL_PAGE, y++ & 0xf, -1); |
230 | lcd_write_command_ex(LCD_CNTL_COLUMN, x+xoffset, -1); | 217 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); |
231 | 218 | ||
232 | lcd_write_command(LCD_CNTL_DATA_WRITE); | 219 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
233 | lcd_write_data(p_data, width); | 220 | lcd_write_data(p_data, width); |
@@ -275,7 +262,7 @@ void lcd_update_rect(int x_start, int y, int width, int height) | |||
275 | for (; y <= ymax; y++) | 262 | for (; y <= ymax; y++) |
276 | { | 263 | { |
277 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); | 264 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); |
278 | lcd_write_command_ex(LCD_CNTL_COLUMN, x_start+xoffset, -1); | 265 | lcd_write_command_ex(LCD_CNTL_COLUMN, x_start, -1); |
279 | 266 | ||
280 | lcd_write_command(LCD_CNTL_DATA_WRITE); | 267 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
281 | lcd_write_data (&lcd_framebuffer[y][x_start], width); | 268 | lcd_write_data (&lcd_framebuffer[y][x_start], width); |
@@ -285,6 +272,16 @@ void lcd_update_rect(int x_start, int y, int width, int height) | |||
285 | 272 | ||
286 | /*** parameter handling ***/ | 273 | /*** parameter handling ***/ |
287 | 274 | ||
275 | void lcd_set_drawmode(int mode) | ||
276 | { | ||
277 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | ||
278 | } | ||
279 | |||
280 | int lcd_get_drawmode(void) | ||
281 | { | ||
282 | return drawmode; | ||
283 | } | ||
284 | |||
288 | void lcd_setmargins(int x, int y) | 285 | void lcd_setmargins(int x, int y) |
289 | { | 286 | { |
290 | xmargin = x; | 287 | xmargin = x; |
@@ -311,103 +308,75 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
311 | return font_getstringsize(str, w, h, curfont); | 308 | return font_getstringsize(str, w, h, curfont); |
312 | } | 309 | } |
313 | 310 | ||
314 | /*** drawing functions ***/ | 311 | /*** low-level drawing functions ***/ |
315 | 312 | ||
316 | void lcd_clear_display(void) | 313 | static void setpixel(int x, int y) |
317 | { | 314 | { |
318 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | 315 | lcd_framebuffer[y/8][x] |= 1 << (y & 7); |
319 | scrolling_lines = 0; | ||
320 | } | 316 | } |
321 | 317 | ||
322 | /* Set a single pixel */ | 318 | static void clearpixel(int x, int y) |
323 | void lcd_drawpixel(int x, int y) | ||
324 | { | 319 | { |
325 | DRAW_PIXEL(x,y); | 320 | lcd_framebuffer[y/8][x] &= ~(1 << (y & 7)); |
326 | } | 321 | } |
327 | 322 | ||
328 | /* Clear a single pixel */ | 323 | static void flippixel(int x, int y) |
329 | void lcd_clearpixel(int x, int y) | ||
330 | { | 324 | { |
331 | CLEAR_PIXEL(x,y); | 325 | lcd_framebuffer[y/8][x] ^= 1 << (y & 7); |
332 | } | 326 | } |
333 | 327 | ||
334 | /* Invert a single pixel */ | 328 | static void nopixel(int x, int y) |
335 | void lcd_invertpixel(int x, int y) | ||
336 | { | 329 | { |
337 | INVERT_PIXEL(x,y); | 330 | (void)x; |
331 | (void)y; | ||
338 | } | 332 | } |
339 | 333 | ||
340 | void lcd_drawline(int x1, int y1, int x2, int y2) | 334 | tLCDPixelFunc* pixelfunc[8] = {flippixel, nopixel, setpixel, setpixel, |
335 | nopixel, clearpixel, nopixel, clearpixel}; | ||
336 | |||
337 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | ||
341 | { | 338 | { |
342 | int numpixels; | 339 | *address ^= (bits & mask); |
343 | int i; | 340 | } |
344 | int deltax, deltay; | ||
345 | int d, dinc1, dinc2; | ||
346 | int x, xinc1, xinc2; | ||
347 | int y, yinc1, yinc2; | ||
348 | 341 | ||
349 | deltax = abs(x2 - x1); | 342 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) |
350 | deltay = abs(y2 - y1); | 343 | { |
344 | *address &= (bits | ~mask); | ||
345 | } | ||
351 | 346 | ||
352 | if(deltax >= deltay) | 347 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) |
353 | { | 348 | { |
354 | numpixels = deltax; | 349 | *address |= (bits & mask); |
355 | d = 2 * deltay - deltax; | 350 | } |
356 | dinc1 = deltay * 2; | ||
357 | dinc2 = (deltay - deltax) * 2; | ||
358 | xinc1 = 1; | ||
359 | xinc2 = 1; | ||
360 | yinc1 = 0; | ||
361 | yinc2 = 1; | ||
362 | } | ||
363 | else | ||
364 | { | ||
365 | numpixels = deltay; | ||
366 | d = 2 * deltax - deltay; | ||
367 | dinc1 = deltax * 2; | ||
368 | dinc2 = (deltax - deltay) * 2; | ||
369 | xinc1 = 0; | ||
370 | xinc2 = 1; | ||
371 | yinc1 = 1; | ||
372 | yinc2 = 1; | ||
373 | } | ||
374 | numpixels++; /* include endpoints */ | ||
375 | 351 | ||
376 | if(x1 > x2) | 352 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) |
377 | { | 353 | { |
378 | xinc1 = -xinc1; | 354 | *address = (*address & ~mask) | (bits & mask); |
379 | xinc2 = -xinc2; | 355 | } |
380 | } | ||
381 | 356 | ||
382 | if(y1 > y2) | 357 | tLCDBlockFunc* blockfunc[4] = {flipblock, bgblock, fgblock, solidblock}; |
383 | { | ||
384 | yinc1 = -yinc1; | ||
385 | yinc2 = -yinc2; | ||
386 | } | ||
387 | 358 | ||
388 | x = x1; | 359 | /*** drawing functions ***/ |
389 | y = y1; | ||
390 | 360 | ||
391 | for(i=0; i<numpixels; i++) | 361 | /* Clear the whole display */ |
392 | { | 362 | void lcd_clear_display(void) |
393 | DRAW_PIXEL(x,y); | 363 | { |
364 | if (drawmode & DRMODE_INVERSEVID) | ||
365 | memset (lcd_framebuffer, 0xFF, sizeof lcd_framebuffer); | ||
366 | else | ||
367 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | ||
368 | scrolling_lines = 0; | ||
369 | } | ||
394 | 370 | ||
395 | if(d < 0) | 371 | /* Set a single pixel */ |
396 | { | 372 | void lcd_drawpixel(int x, int y) |
397 | d += dinc1; | 373 | { |
398 | x += xinc1; | 374 | if (((unsigned)x < LCD_WIDTH) || ((unsigned)y < LCD_HEIGHT)) |
399 | y += yinc1; | 375 | pixelfunc[drawmode](x, y); |
400 | } | ||
401 | else | ||
402 | { | ||
403 | d += dinc2; | ||
404 | x += xinc2; | ||
405 | y += yinc2; | ||
406 | } | ||
407 | } | ||
408 | } | 376 | } |
409 | 377 | ||
410 | void lcd_clearline(int x1, int y1, int x2, int y2) | 378 | /* Draw a line */ |
379 | void lcd_drawline(int x1, int y1, int x2, int y2) | ||
411 | { | 380 | { |
412 | int numpixels; | 381 | int numpixels; |
413 | int i; | 382 | int i; |
@@ -415,20 +384,21 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
415 | int d, dinc1, dinc2; | 384 | int d, dinc1, dinc2; |
416 | int x, xinc1, xinc2; | 385 | int x, xinc1, xinc2; |
417 | int y, yinc1, yinc2; | 386 | int y, yinc1, yinc2; |
387 | tLCDPixelFunc *pfunc = pixelfunc[drawmode]; | ||
418 | 388 | ||
419 | deltax = abs(x2 - x1); | 389 | deltax = abs(x2 - x1); |
420 | deltay = abs(y2 - y1); | 390 | deltay = abs(y2 - y1); |
391 | xinc2 = 1; | ||
392 | yinc2 = 1; | ||
421 | 393 | ||
422 | if(deltax >= deltay) | 394 | if (deltax >= deltay) |
423 | { | 395 | { |
424 | numpixels = deltax; | 396 | numpixels = deltax; |
425 | d = 2 * deltay - deltax; | 397 | d = 2 * deltay - deltax; |
426 | dinc1 = deltay * 2; | 398 | dinc1 = deltay * 2; |
427 | dinc2 = (deltay - deltax) * 2; | 399 | dinc2 = (deltay - deltax) * 2; |
428 | xinc1 = 1; | 400 | xinc1 = 1; |
429 | xinc2 = 1; | ||
430 | yinc1 = 0; | 401 | yinc1 = 0; |
431 | yinc2 = 1; | ||
432 | } | 402 | } |
433 | else | 403 | else |
434 | { | 404 | { |
@@ -437,19 +407,17 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
437 | dinc1 = deltax * 2; | 407 | dinc1 = deltax * 2; |
438 | dinc2 = (deltax - deltay) * 2; | 408 | dinc2 = (deltax - deltay) * 2; |
439 | xinc1 = 0; | 409 | xinc1 = 0; |
440 | xinc2 = 1; | ||
441 | yinc1 = 1; | 410 | yinc1 = 1; |
442 | yinc2 = 1; | ||
443 | } | 411 | } |
444 | numpixels++; /* include endpoints */ | 412 | numpixels++; /* include endpoints */ |
445 | 413 | ||
446 | if(x1 > x2) | 414 | if (x1 > x2) |
447 | { | 415 | { |
448 | xinc1 = -xinc1; | 416 | xinc1 = -xinc1; |
449 | xinc2 = -xinc2; | 417 | xinc2 = -xinc2; |
450 | } | 418 | } |
451 | 419 | ||
452 | if(y1 > y2) | 420 | if (y1 > y2) |
453 | { | 421 | { |
454 | yinc1 = -yinc1; | 422 | yinc1 = -yinc1; |
455 | yinc2 = -yinc2; | 423 | yinc2 = -yinc2; |
@@ -458,11 +426,12 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
458 | x = x1; | 426 | x = x1; |
459 | y = y1; | 427 | y = y1; |
460 | 428 | ||
461 | for(i=0; i<numpixels; i++) | 429 | for (i = 0; i < numpixels; i++) |
462 | { | 430 | { |
463 | CLEAR_PIXEL(x,y); | 431 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) |
432 | pfunc(x, y); | ||
464 | 433 | ||
465 | if(d < 0) | 434 | if (d < 0) |
466 | { | 435 | { |
467 | d += dinc1; | 436 | d += dinc1; |
468 | x += xinc1; | 437 | x += xinc1; |
@@ -477,68 +446,178 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
477 | } | 446 | } |
478 | } | 447 | } |
479 | 448 | ||
480 | /* Draw a rectangle with upper left corner at (x, y) and size (nx, ny) */ | 449 | /* Draw a horizontal line (optimised) */ |
481 | void lcd_drawrect(int x, int y, int nx, int ny) | 450 | void lcd_hline(int x1, int x2, int y) |
482 | { | 451 | { |
483 | int i; | 452 | int x; |
453 | unsigned char *dst; | ||
454 | unsigned char mask, bits; | ||
455 | tLCDBlockFunc *bfunc; | ||
484 | 456 | ||
485 | if (x > LCD_WIDTH) | 457 | /* direction flip */ |
486 | return; | 458 | if (x2 < x1) |
487 | if (y > LCD_HEIGHT) | 459 | { |
488 | return; | 460 | x = x1; |
461 | x1 = x2; | ||
462 | x2 = x; | ||
463 | } | ||
464 | |||
465 | /* nothing to draw? */ | ||
466 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) | ||
467 | return; | ||
468 | |||
469 | /* clipping */ | ||
470 | if (x1 < 0) | ||
471 | x1 = 0; | ||
472 | if (x2 >= LCD_WIDTH) | ||
473 | x2 = LCD_WIDTH-1; | ||
474 | |||
475 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | ||
476 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | ||
477 | dst = &lcd_framebuffer[y/8][x1]; | ||
478 | mask = 1 << (y & 7); | ||
489 | 479 | ||
490 | if (x + nx > LCD_WIDTH) | 480 | for (x = x1; x <= x2; x++) |
491 | nx = LCD_WIDTH - x; | 481 | bfunc(dst++, mask, bits); |
492 | if (y + ny > LCD_HEIGHT) | 482 | } |
493 | ny = LCD_HEIGHT - y; | ||
494 | 483 | ||
495 | /* vertical lines */ | 484 | /* Draw a vertical line (optimised) */ |
496 | for (i = 0; i < ny; i++) { | 485 | void lcd_vline(int x, int y1, int y2) |
497 | DRAW_PIXEL(x, (y + i)); | 486 | { |
498 | DRAW_PIXEL((x + nx - 1), (y + i)); | 487 | int ny; |
488 | unsigned char *dst; | ||
489 | unsigned char mask_top, mask_bottom, bits; | ||
490 | tLCDBlockFunc *bfunc; | ||
491 | |||
492 | /* direction flip */ | ||
493 | if (y2 < y1) | ||
494 | { | ||
495 | ny = y1; | ||
496 | y1 = y2; | ||
497 | y2 = ny; | ||
499 | } | 498 | } |
500 | 499 | ||
501 | /* horizontal lines */ | 500 | /* nothing to draw? */ |
502 | for (i = 0; i < nx; i++) { | 501 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) |
503 | DRAW_PIXEL((x + i),y); | 502 | return; |
504 | DRAW_PIXEL((x + i),(y + ny - 1)); | 503 | |
504 | /* clipping */ | ||
505 | if (y1 < 0) | ||
506 | y1 = 0; | ||
507 | if (y2 >= LCD_HEIGHT) | ||
508 | y2 = LCD_HEIGHT-1; | ||
509 | |||
510 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | ||
511 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | ||
512 | dst = &lcd_framebuffer[y1/8][x]; | ||
513 | ny = y2 - (y1 & ~7); | ||
514 | mask_top = 0xFFu << (y1 & 7); | ||
515 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
516 | |||
517 | if (ny >= 8) | ||
518 | { | ||
519 | bfunc(dst, mask_top, bits); | ||
520 | dst += LCD_WIDTH; | ||
521 | |||
522 | for (; ny > 15; ny -= 8) | ||
523 | { | ||
524 | bfunc(dst, 0xFFu, bits); | ||
525 | dst += LCD_WIDTH; | ||
526 | } | ||
505 | } | 527 | } |
528 | else | ||
529 | mask_bottom &= mask_top; | ||
530 | |||
531 | bfunc(dst, mask_bottom, bits); | ||
506 | } | 532 | } |
507 | 533 | ||
508 | /* Clear a rectangular area at (x, y), size (nx, ny) */ | 534 | /* Draw a rectangular box */ |
509 | void lcd_clearrect(int x, int y, int nx, int ny) | 535 | void lcd_drawrect(int x, int y, int width, int height) |
510 | { | 536 | { |
511 | int i; | 537 | if ((width <= 0) || (height <= 0)) |
512 | for (i = 0; i < nx; i++) | 538 | return; |
513 | lcd_bitmap (zeros, x+i, y, 1, ny, true); | 539 | |
540 | int x2 = x + width - 1; | ||
541 | int y2 = y + height - 1; | ||
542 | |||
543 | lcd_vline(x, y, y2); | ||
544 | lcd_vline(x2, y, y2); | ||
545 | lcd_hline(x, x2, y); | ||
546 | lcd_hline(x, x2, y2); | ||
514 | } | 547 | } |
515 | 548 | ||
516 | /* Fill a rectangular area at (x, y), size (nx, ny) */ | 549 | /* helper function for lcd_fillrect() */ |
517 | void lcd_fillrect(int x, int y, int nx, int ny) | 550 | static void fillrow(tLCDBlockFunc *bfunc, unsigned char *address, |
551 | int width, unsigned mask, unsigned bits) | ||
518 | { | 552 | { |
519 | int i; | 553 | int i; |
520 | for (i = 0; i < nx; i++) | 554 | |
521 | lcd_bitmap (ones, x+i, y, 1, ny, true); | 555 | for (i = 0; i < width; i++) |
556 | bfunc(address++, mask, bits); | ||
522 | } | 557 | } |
523 | 558 | ||
524 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | 559 | /* Fill a rectangular area */ |
525 | void lcd_invertrect(int x, int y, int nx, int ny) | 560 | void lcd_fillrect(int x, int y, int width, int height) |
526 | { | 561 | { |
527 | int i, j; | 562 | int ny; |
563 | unsigned char *dst; | ||
564 | unsigned char mask_top, mask_bottom, bits; | ||
565 | tLCDBlockFunc *bfunc; | ||
566 | bool fillopt = (drawmode & DRMODE_INVERSEVID) ? | ||
567 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); | ||
528 | 568 | ||
529 | if (x > LCD_WIDTH) | 569 | /* nothing to draw? */ |
570 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
571 | || (x + width < 0) || (y + height < 0)) | ||
530 | return; | 572 | return; |
531 | if (y > LCD_HEIGHT) | ||
532 | return; | ||
533 | |||
534 | if (x + nx > LCD_WIDTH) | ||
535 | nx = LCD_WIDTH - x; | ||
536 | if (y + ny > LCD_HEIGHT) | ||
537 | ny = LCD_HEIGHT - y; | ||
538 | 573 | ||
539 | for (i = 0; i < nx; i++) | 574 | /* clipping */ |
540 | for (j = 0; j < ny; j++) | 575 | if (x < 0) |
541 | INVERT_PIXEL((x + i), (y + j)); | 576 | { |
577 | width += x; | ||
578 | x = 0; | ||
579 | } | ||
580 | if (y < 0) | ||
581 | { | ||
582 | height += y; | ||
583 | y = 0; | ||
584 | } | ||
585 | if (x + width > LCD_WIDTH) | ||
586 | width = LCD_WIDTH - x; | ||
587 | if (y + height > LCD_HEIGHT) | ||
588 | height = LCD_HEIGHT - y; | ||
589 | |||
590 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | ||
591 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | ||
592 | dst = &lcd_framebuffer[y/8][x]; | ||
593 | ny = height - 1 + (y & 7); | ||
594 | mask_top = 0xFFu << (y & 7); | ||
595 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
596 | |||
597 | if (ny >= 8) | ||
598 | { | ||
599 | if (fillopt && mask_top == 0xFF) | ||
600 | memset(dst, bits, width); | ||
601 | else | ||
602 | fillrow(bfunc, dst, width, mask_top, bits); | ||
603 | dst += LCD_WIDTH; | ||
604 | |||
605 | for (; ny > 15; ny -= 8) | ||
606 | { | ||
607 | if (fillopt) | ||
608 | memset(dst, bits, width); | ||
609 | else | ||
610 | fillrow(bfunc, dst, width, 0xFFu, bits); | ||
611 | dst += LCD_WIDTH; | ||
612 | } | ||
613 | } | ||
614 | else | ||
615 | mask_bottom &= mask_top; | ||
616 | |||
617 | if (fillopt && mask_bottom == 0xFF) | ||
618 | memset(dst, bits, width); | ||
619 | else | ||
620 | fillrow(bfunc, dst, width, mask_bottom, bits); | ||
542 | } | 621 | } |
543 | 622 | ||
544 | /* About Rockbox' internal bitmap format: | 623 | /* About Rockbox' internal bitmap format: |
@@ -706,6 +785,7 @@ void lcd_putsxy(int x, int y, const unsigned char *str) | |||
706 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | 785 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) |
707 | { | 786 | { |
708 | int xpos,ypos,w,h; | 787 | int xpos,ypos,w,h; |
788 | int lastmode = lcd_get_drawmode(); | ||
709 | 789 | ||
710 | /* make sure scrolling is turned off on the line we are updating */ | 790 | /* make sure scrolling is turned off on the line we are updating */ |
711 | scrolling_lines &= ~(1 << y); | 791 | scrolling_lines &= ~(1 << y); |
@@ -717,9 +797,14 @@ void lcd_puts_style(int x, int y, const unsigned char *str, int style) | |||
717 | xpos = xmargin + x*w / strlen(str); | 797 | xpos = xmargin + x*w / strlen(str); |
718 | ypos = ymargin + y*h; | 798 | ypos = ymargin + y*h; |
719 | lcd_putsxy(xpos, ypos, str); | 799 | lcd_putsxy(xpos, ypos, str); |
720 | lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | 800 | lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); |
801 | lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | ||
721 | if (style & STYLE_INVERT) | 802 | if (style & STYLE_INVERT) |
722 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, h); | 803 | { |
804 | lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
805 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); | ||
806 | } | ||
807 | lcd_set_drawmode(lastmode); | ||
723 | } | 808 | } |
724 | 809 | ||
725 | /* put a string at a given char position */ | 810 | /* put a string at a given char position */ |
@@ -835,6 +920,7 @@ static void scroll_thread(void) | |||
835 | struct scrollinfo* s; | 920 | struct scrollinfo* s; |
836 | int index; | 921 | int index; |
837 | int xpos, ypos; | 922 | int xpos, ypos; |
923 | int lastmode; | ||
838 | 924 | ||
839 | /* initialize scroll struct array */ | 925 | /* initialize scroll struct array */ |
840 | scrolling_lines = 0; | 926 | scrolling_lines = 0; |
@@ -880,10 +966,17 @@ static void scroll_thread(void) | |||
880 | s->offset %= s->width; | 966 | s->offset %= s->width; |
881 | } | 967 | } |
882 | 968 | ||
883 | lcd_clearrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 969 | lastmode = lcd_get_drawmode(); |
970 | lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
971 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | ||
972 | lcd_set_drawmode(DRMODE_SOLID); | ||
884 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 973 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
885 | if (s->invert) | 974 | if (s->invert) |
886 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 975 | { |
976 | lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
977 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | ||
978 | } | ||
979 | lcd_set_drawmode(lastmode); | ||
887 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 980 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); |
888 | } | 981 | } |
889 | 982 | ||
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c index 52455a1ff5..16a47f28bf 100644 --- a/firmware/drivers/lcd-recorder.c +++ b/firmware/drivers/lcd-recorder.c | |||
@@ -77,6 +77,7 @@ | |||
77 | 77 | ||
78 | unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; | 78 | unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; |
79 | 79 | ||
80 | static int drawmode = DRMODE_SOLID; | ||
80 | static int xmargin = 0; | 81 | static int xmargin = 0; |
81 | static int ymargin = 0; | 82 | static int ymargin = 0; |
82 | static int curfont = FONT_SYSFIXED; | 83 | static int curfont = FONT_SYSFIXED; |
@@ -84,11 +85,6 @@ static int curfont = FONT_SYSFIXED; | |||
84 | static int xoffset; /* needed for flip */ | 85 | static int xoffset; /* needed for flip */ |
85 | #endif | 86 | #endif |
86 | 87 | ||
87 | /* All zeros and ones bitmaps for area filling */ | ||
88 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
89 | static const unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, | ||
90 | 0xff, 0xff, 0xff, 0xff}; | ||
91 | |||
92 | /* scrolling */ | 88 | /* scrolling */ |
93 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 89 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
94 | static void scroll_thread(void); | 90 | static void scroll_thread(void); |
@@ -335,6 +331,16 @@ void lcd_update_rect(int x_start, int y, int width, int height) | |||
335 | 331 | ||
336 | /*** parameter handling ***/ | 332 | /*** parameter handling ***/ |
337 | 333 | ||
334 | void lcd_set_drawmode(int mode) | ||
335 | { | ||
336 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | ||
337 | } | ||
338 | |||
339 | int lcd_get_drawmode(void) | ||
340 | { | ||
341 | return drawmode; | ||
342 | } | ||
343 | |||
338 | void lcd_setmargins(int x, int y) | 344 | void lcd_setmargins(int x, int y) |
339 | { | 345 | { |
340 | xmargin = x; | 346 | xmargin = x; |
@@ -361,103 +367,75 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
361 | return font_getstringsize(str, w, h, curfont); | 367 | return font_getstringsize(str, w, h, curfont); |
362 | } | 368 | } |
363 | 369 | ||
364 | /*** drawing functions ***/ | 370 | /*** low-level drawing functions ***/ |
365 | 371 | ||
366 | void lcd_clear_display(void) | 372 | static void setpixel(int x, int y) |
367 | { | 373 | { |
368 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | 374 | lcd_framebuffer[y/8][x] |= 1 << (y & 7); |
369 | scrolling_lines = 0; | ||
370 | } | 375 | } |
371 | 376 | ||
372 | /* Set a single pixel */ | 377 | static void clearpixel(int x, int y) |
373 | void lcd_drawpixel(int x, int y) | ||
374 | { | 378 | { |
375 | DRAW_PIXEL(x,y); | 379 | lcd_framebuffer[y/8][x] &= ~(1 << (y & 7)); |
376 | } | 380 | } |
377 | 381 | ||
378 | /* Clear a single pixel */ | 382 | static void flippixel(int x, int y) |
379 | void lcd_clearpixel(int x, int y) | ||
380 | { | 383 | { |
381 | CLEAR_PIXEL(x,y); | 384 | lcd_framebuffer[y/8][x] ^= 1 << (y & 7); |
382 | } | 385 | } |
383 | 386 | ||
384 | /* Invert a single pixel */ | 387 | static void nopixel(int x, int y) |
385 | void lcd_invertpixel(int x, int y) | ||
386 | { | 388 | { |
387 | INVERT_PIXEL(x,y); | 389 | (void)x; |
390 | (void)y; | ||
388 | } | 391 | } |
389 | 392 | ||
390 | void lcd_drawline(int x1, int y1, int x2, int y2) | 393 | tLCDPixelFunc* pixelfunc[8] = {flippixel, nopixel, setpixel, setpixel, |
394 | nopixel, clearpixel, nopixel, clearpixel}; | ||
395 | |||
396 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | ||
391 | { | 397 | { |
392 | int numpixels; | 398 | *address ^= (bits & mask); |
393 | int i; | 399 | } |
394 | int deltax, deltay; | ||
395 | int d, dinc1, dinc2; | ||
396 | int x, xinc1, xinc2; | ||
397 | int y, yinc1, yinc2; | ||
398 | 400 | ||
399 | deltax = abs(x2 - x1); | 401 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) |
400 | deltay = abs(y2 - y1); | 402 | { |
403 | *address &= (bits | ~mask); | ||
404 | } | ||
401 | 405 | ||
402 | if(deltax >= deltay) | 406 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) |
403 | { | 407 | { |
404 | numpixels = deltax; | 408 | *address |= (bits & mask); |
405 | d = 2 * deltay - deltax; | 409 | } |
406 | dinc1 = deltay * 2; | ||
407 | dinc2 = (deltay - deltax) * 2; | ||
408 | xinc1 = 1; | ||
409 | xinc2 = 1; | ||
410 | yinc1 = 0; | ||
411 | yinc2 = 1; | ||
412 | } | ||
413 | else | ||
414 | { | ||
415 | numpixels = deltay; | ||
416 | d = 2 * deltax - deltay; | ||
417 | dinc1 = deltax * 2; | ||
418 | dinc2 = (deltax - deltay) * 2; | ||
419 | xinc1 = 0; | ||
420 | xinc2 = 1; | ||
421 | yinc1 = 1; | ||
422 | yinc2 = 1; | ||
423 | } | ||
424 | numpixels++; /* include endpoints */ | ||
425 | 410 | ||
426 | if(x1 > x2) | 411 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) |
427 | { | 412 | { |
428 | xinc1 = -xinc1; | 413 | *address = (*address & ~mask) | (bits & mask); |
429 | xinc2 = -xinc2; | 414 | } |
430 | } | ||
431 | 415 | ||
432 | if(y1 > y2) | 416 | tLCDBlockFunc* blockfunc[4] = {flipblock, bgblock, fgblock, solidblock}; |
433 | { | ||
434 | yinc1 = -yinc1; | ||
435 | yinc2 = -yinc2; | ||
436 | } | ||
437 | 417 | ||
438 | x = x1; | 418 | /*** drawing functions ***/ |
439 | y = y1; | ||
440 | 419 | ||
441 | for(i=0; i<numpixels; i++) | 420 | /* Clear the whole display */ |
442 | { | 421 | void lcd_clear_display(void) |
443 | DRAW_PIXEL(x,y); | 422 | { |
423 | if (drawmode & DRMODE_INVERSEVID) | ||
424 | memset (lcd_framebuffer, 0xFF, sizeof lcd_framebuffer); | ||
425 | else | ||
426 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | ||
427 | scrolling_lines = 0; | ||
428 | } | ||
444 | 429 | ||
445 | if(d < 0) | 430 | /* Set a single pixel */ |
446 | { | 431 | void lcd_drawpixel(int x, int y) |
447 | d += dinc1; | 432 | { |
448 | x += xinc1; | 433 | if (((unsigned)x < LCD_WIDTH) || ((unsigned)y < LCD_HEIGHT)) |
449 | y += yinc1; | 434 | pixelfunc[drawmode](x, y); |
450 | } | ||
451 | else | ||
452 | { | ||
453 | d += dinc2; | ||
454 | x += xinc2; | ||
455 | y += yinc2; | ||
456 | } | ||
457 | } | ||
458 | } | 435 | } |
459 | 436 | ||
460 | void lcd_clearline(int x1, int y1, int x2, int y2) | 437 | /* Draw a line */ |
438 | void lcd_drawline(int x1, int y1, int x2, int y2) | ||
461 | { | 439 | { |
462 | int numpixels; | 440 | int numpixels; |
463 | int i; | 441 | int i; |
@@ -465,20 +443,21 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
465 | int d, dinc1, dinc2; | 443 | int d, dinc1, dinc2; |
466 | int x, xinc1, xinc2; | 444 | int x, xinc1, xinc2; |
467 | int y, yinc1, yinc2; | 445 | int y, yinc1, yinc2; |
446 | tLCDPixelFunc *pfunc = pixelfunc[drawmode]; | ||
468 | 447 | ||
469 | deltax = abs(x2 - x1); | 448 | deltax = abs(x2 - x1); |
470 | deltay = abs(y2 - y1); | 449 | deltay = abs(y2 - y1); |
450 | xinc2 = 1; | ||
451 | yinc2 = 1; | ||
471 | 452 | ||
472 | if(deltax >= deltay) | 453 | if (deltax >= deltay) |
473 | { | 454 | { |
474 | numpixels = deltax; | 455 | numpixels = deltax; |
475 | d = 2 * deltay - deltax; | 456 | d = 2 * deltay - deltax; |
476 | dinc1 = deltay * 2; | 457 | dinc1 = deltay * 2; |
477 | dinc2 = (deltay - deltax) * 2; | 458 | dinc2 = (deltay - deltax) * 2; |
478 | xinc1 = 1; | 459 | xinc1 = 1; |
479 | xinc2 = 1; | ||
480 | yinc1 = 0; | 460 | yinc1 = 0; |
481 | yinc2 = 1; | ||
482 | } | 461 | } |
483 | else | 462 | else |
484 | { | 463 | { |
@@ -487,19 +466,17 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
487 | dinc1 = deltax * 2; | 466 | dinc1 = deltax * 2; |
488 | dinc2 = (deltax - deltay) * 2; | 467 | dinc2 = (deltax - deltay) * 2; |
489 | xinc1 = 0; | 468 | xinc1 = 0; |
490 | xinc2 = 1; | ||
491 | yinc1 = 1; | 469 | yinc1 = 1; |
492 | yinc2 = 1; | ||
493 | } | 470 | } |
494 | numpixels++; /* include endpoints */ | 471 | numpixels++; /* include endpoints */ |
495 | 472 | ||
496 | if(x1 > x2) | 473 | if (x1 > x2) |
497 | { | 474 | { |
498 | xinc1 = -xinc1; | 475 | xinc1 = -xinc1; |
499 | xinc2 = -xinc2; | 476 | xinc2 = -xinc2; |
500 | } | 477 | } |
501 | 478 | ||
502 | if(y1 > y2) | 479 | if (y1 > y2) |
503 | { | 480 | { |
504 | yinc1 = -yinc1; | 481 | yinc1 = -yinc1; |
505 | yinc2 = -yinc2; | 482 | yinc2 = -yinc2; |
@@ -508,11 +485,12 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
508 | x = x1; | 485 | x = x1; |
509 | y = y1; | 486 | y = y1; |
510 | 487 | ||
511 | for(i=0; i<numpixels; i++) | 488 | for (i = 0; i < numpixels; i++) |
512 | { | 489 | { |
513 | CLEAR_PIXEL(x,y); | 490 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) |
491 | pfunc(x, y); | ||
514 | 492 | ||
515 | if(d < 0) | 493 | if (d < 0) |
516 | { | 494 | { |
517 | d += dinc1; | 495 | d += dinc1; |
518 | x += xinc1; | 496 | x += xinc1; |
@@ -527,68 +505,178 @@ void lcd_clearline(int x1, int y1, int x2, int y2) | |||
527 | } | 505 | } |
528 | } | 506 | } |
529 | 507 | ||
530 | /* Draw a rectangle with upper left corner at (x, y) and size (nx, ny) */ | 508 | /* Draw a horizontal line (optimised) */ |
531 | void lcd_drawrect(int x, int y, int nx, int ny) | 509 | void lcd_hline(int x1, int x2, int y) |
532 | { | 510 | { |
533 | int i; | 511 | int x; |
512 | unsigned char *dst; | ||
513 | unsigned char mask, bits; | ||
514 | tLCDBlockFunc *bfunc; | ||
534 | 515 | ||
535 | if (x > LCD_WIDTH) | 516 | /* direction flip */ |
536 | return; | 517 | if (x2 < x1) |
537 | if (y > LCD_HEIGHT) | 518 | { |
538 | return; | 519 | x = x1; |
520 | x1 = x2; | ||
521 | x2 = x; | ||
522 | } | ||
523 | |||
524 | /* nothing to draw? */ | ||
525 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) | ||
526 | return; | ||
527 | |||
528 | /* clipping */ | ||
529 | if (x1 < 0) | ||
530 | x1 = 0; | ||
531 | if (x2 >= LCD_WIDTH) | ||
532 | x2 = LCD_WIDTH-1; | ||
533 | |||
534 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | ||
535 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | ||
536 | dst = &lcd_framebuffer[y/8][x1]; | ||
537 | mask = 1 << (y & 7); | ||
539 | 538 | ||
540 | if (x + nx > LCD_WIDTH) | 539 | for (x = x1; x <= x2; x++) |
541 | nx = LCD_WIDTH - x; | 540 | bfunc(dst++, mask, bits); |
542 | if (y + ny > LCD_HEIGHT) | 541 | } |
543 | ny = LCD_HEIGHT - y; | 542 | |
543 | /* Draw a vertical line (optimised) */ | ||
544 | void lcd_vline(int x, int y1, int y2) | ||
545 | { | ||
546 | int ny; | ||
547 | unsigned char *dst; | ||
548 | unsigned char mask_top, mask_bottom, bits; | ||
549 | tLCDBlockFunc *bfunc; | ||
544 | 550 | ||
545 | /* vertical lines */ | 551 | /* direction flip */ |
546 | for (i = 0; i < ny; i++) { | 552 | if (y2 < y1) |
547 | DRAW_PIXEL(x, (y + i)); | 553 | { |
548 | DRAW_PIXEL((x + nx - 1), (y + i)); | 554 | ny = y1; |
555 | y1 = y2; | ||
556 | y2 = ny; | ||
549 | } | 557 | } |
550 | 558 | ||
551 | /* horizontal lines */ | 559 | /* nothing to draw? */ |
552 | for (i = 0; i < nx; i++) { | 560 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) |
553 | DRAW_PIXEL((x + i),y); | 561 | return; |
554 | DRAW_PIXEL((x + i),(y + ny - 1)); | 562 | |
563 | /* clipping */ | ||
564 | if (y1 < 0) | ||
565 | y1 = 0; | ||
566 | if (y2 >= LCD_HEIGHT) | ||
567 | y2 = LCD_HEIGHT-1; | ||
568 | |||
569 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | ||
570 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | ||
571 | dst = &lcd_framebuffer[y1/8][x]; | ||
572 | ny = y2 - (y1 & ~7); | ||
573 | mask_top = 0xFFu << (y1 & 7); | ||
574 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
575 | |||
576 | if (ny >= 8) | ||
577 | { | ||
578 | bfunc(dst, mask_top, bits); | ||
579 | dst += LCD_WIDTH; | ||
580 | |||
581 | for (; ny > 15; ny -= 8) | ||
582 | { | ||
583 | bfunc(dst, 0xFFu, bits); | ||
584 | dst += LCD_WIDTH; | ||
585 | } | ||
555 | } | 586 | } |
587 | else | ||
588 | mask_bottom &= mask_top; | ||
589 | |||
590 | bfunc(dst, mask_bottom, bits); | ||
556 | } | 591 | } |
557 | 592 | ||
558 | /* Clear a rectangular area at (x, y), size (nx, ny) */ | 593 | /* Draw a rectangular box */ |
559 | void lcd_clearrect(int x, int y, int nx, int ny) | 594 | void lcd_drawrect(int x, int y, int width, int height) |
560 | { | 595 | { |
561 | int i; | 596 | if ((width <= 0) || (height <= 0)) |
562 | for (i = 0; i < nx; i++) | 597 | return; |
563 | lcd_bitmap(zeros, x+i, y, 1, ny, true); | 598 | |
599 | int x2 = x + width - 1; | ||
600 | int y2 = y + height - 1; | ||
601 | |||
602 | lcd_vline(x, y, y2); | ||
603 | lcd_vline(x2, y, y2); | ||
604 | lcd_hline(x, x2, y); | ||
605 | lcd_hline(x, x2, y2); | ||
564 | } | 606 | } |
565 | 607 | ||
566 | /* Fill a rectangular area at (x, y), size (nx, ny) */ | 608 | /* helper function for lcd_fillrect() */ |
567 | void lcd_fillrect(int x, int y, int nx, int ny) | 609 | static void fillrow(tLCDBlockFunc *bfunc, unsigned char *address, |
610 | int width, unsigned mask, unsigned bits) | ||
568 | { | 611 | { |
569 | int i; | 612 | int i; |
570 | for (i = 0; i < nx; i++) | 613 | |
571 | lcd_bitmap(ones, x+i, y, 1, ny, true); | 614 | for (i = 0; i < width; i++) |
615 | bfunc(address++, mask, bits); | ||
572 | } | 616 | } |
573 | 617 | ||
574 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | 618 | /* Fill a rectangular area */ |
575 | void lcd_invertrect(int x, int y, int nx, int ny) | 619 | void lcd_fillrect(int x, int y, int width, int height) |
576 | { | 620 | { |
577 | int i, j; | 621 | int ny; |
578 | 622 | unsigned char *dst; | |
579 | if (x > LCD_WIDTH) | 623 | unsigned char mask_top, mask_bottom, bits; |
580 | return; | 624 | tLCDBlockFunc *bfunc; |
581 | if (y > LCD_HEIGHT) | 625 | bool fillopt = (drawmode & DRMODE_INVERSEVID) ? |
626 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); | ||
627 | |||
628 | /* nothing to draw? */ | ||
629 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
630 | || (x + width < 0) || (y + height < 0)) | ||
582 | return; | 631 | return; |
583 | 632 | ||
584 | if (x + nx > LCD_WIDTH) | 633 | /* clipping */ |
585 | nx = LCD_WIDTH - x; | 634 | if (x < 0) |
586 | if (y + ny > LCD_HEIGHT) | 635 | { |
587 | ny = LCD_HEIGHT - y; | 636 | width += x; |
588 | 637 | x = 0; | |
589 | for (i = 0; i < nx; i++) | 638 | } |
590 | for (j = 0; j < ny; j++) | 639 | if (y < 0) |
591 | INVERT_PIXEL((x + i), (y + j)); | 640 | { |
641 | height += y; | ||
642 | y = 0; | ||
643 | } | ||
644 | if (x + width > LCD_WIDTH) | ||
645 | width = LCD_WIDTH - x; | ||
646 | if (y + height > LCD_HEIGHT) | ||
647 | height = LCD_HEIGHT - y; | ||
648 | |||
649 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | ||
650 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | ||
651 | dst = &lcd_framebuffer[y/8][x]; | ||
652 | ny = height - 1 + (y & 7); | ||
653 | mask_top = 0xFFu << (y & 7); | ||
654 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | ||
655 | |||
656 | if (ny >= 8) | ||
657 | { | ||
658 | if (fillopt && mask_top == 0xFF) | ||
659 | memset(dst, bits, width); | ||
660 | else | ||
661 | fillrow(bfunc, dst, width, mask_top, bits); | ||
662 | dst += LCD_WIDTH; | ||
663 | |||
664 | for (; ny > 15; ny -= 8) | ||
665 | { | ||
666 | if (fillopt) | ||
667 | memset(dst, bits, width); | ||
668 | else | ||
669 | fillrow(bfunc, dst, width, 0xFFu, bits); | ||
670 | dst += LCD_WIDTH; | ||
671 | } | ||
672 | } | ||
673 | else | ||
674 | mask_bottom &= mask_top; | ||
675 | |||
676 | if (fillopt && mask_bottom == 0xFF) | ||
677 | memset(dst, bits, width); | ||
678 | else | ||
679 | fillrow(bfunc, dst, width, mask_bottom, bits); | ||
592 | } | 680 | } |
593 | 681 | ||
594 | /* About Rockbox' internal bitmap format: | 682 | /* About Rockbox' internal bitmap format: |
@@ -756,6 +844,7 @@ void lcd_putsxy(int x, int y, const unsigned char *str) | |||
756 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | 844 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) |
757 | { | 845 | { |
758 | int xpos,ypos,w,h; | 846 | int xpos,ypos,w,h; |
847 | int lastmode = lcd_get_drawmode(); | ||
759 | 848 | ||
760 | /* make sure scrolling is turned off on the line we are updating */ | 849 | /* make sure scrolling is turned off on the line we are updating */ |
761 | scrolling_lines &= ~(1 << y); | 850 | scrolling_lines &= ~(1 << y); |
@@ -767,9 +856,14 @@ void lcd_puts_style(int x, int y, const unsigned char *str, int style) | |||
767 | xpos = xmargin + x*w / strlen(str); | 856 | xpos = xmargin + x*w / strlen(str); |
768 | ypos = ymargin + y*h; | 857 | ypos = ymargin + y*h; |
769 | lcd_putsxy(xpos, ypos, str); | 858 | lcd_putsxy(xpos, ypos, str); |
770 | lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | 859 | lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); |
860 | lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); | ||
771 | if (style & STYLE_INVERT) | 861 | if (style & STYLE_INVERT) |
772 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, h); | 862 | { |
863 | lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
864 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); | ||
865 | } | ||
866 | lcd_set_drawmode(lastmode); | ||
773 | } | 867 | } |
774 | 868 | ||
775 | /* put a string at a given char position */ | 869 | /* put a string at a given char position */ |
@@ -885,6 +979,7 @@ static void scroll_thread(void) | |||
885 | struct scrollinfo* s; | 979 | struct scrollinfo* s; |
886 | int index; | 980 | int index; |
887 | int xpos, ypos; | 981 | int xpos, ypos; |
982 | int lastmode; | ||
888 | 983 | ||
889 | /* initialize scroll struct array */ | 984 | /* initialize scroll struct array */ |
890 | scrolling_lines = 0; | 985 | scrolling_lines = 0; |
@@ -930,10 +1025,17 @@ static void scroll_thread(void) | |||
930 | s->offset %= s->width; | 1025 | s->offset %= s->width; |
931 | } | 1026 | } |
932 | 1027 | ||
933 | lcd_clearrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1028 | lastmode = lcd_get_drawmode(); |
1029 | lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
1030 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | ||
1031 | lcd_set_drawmode(DRMODE_SOLID); | ||
934 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 1032 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
935 | if (s->invert) | 1033 | if (s->invert) |
936 | lcd_invertrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1034 | { |
1035 | lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
1036 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | ||
1037 | } | ||
1038 | lcd_set_drawmode(lastmode); | ||
937 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1039 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); |
938 | } | 1040 | } |
939 | 1041 | ||
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 8c05fb984f..700ebbf67c 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -115,33 +115,45 @@ extern void lcd_jump_scroll_delay(int ms); | |||
115 | 115 | ||
116 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) | 116 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) |
117 | 117 | ||
118 | /* draw modes */ | ||
119 | #define DRMODE_COMPLEMENT 0 | ||
120 | #define DRMODE_BG 1 | ||
121 | #define DRMODE_FG 2 | ||
122 | #define DRMODE_SOLID 3 | ||
123 | #define DRMODE_INVERSEVID 4 /* used as bit modifier for basic modes */ | ||
124 | |||
118 | #define DRAW_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] |= (1<<((y)&7)) | 125 | #define DRAW_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] |= (1<<((y)&7)) |
119 | #define CLEAR_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] &= ~(1<<((y)&7)) | 126 | #define CLEAR_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] &= ~(1<<((y)&7)) |
120 | #define INVERT_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] ^= (1<<((y)&7)) | 127 | #define INVERT_PIXEL(x,y) lcd_framebuffer[(y)/8][(x)] ^= (1<<((y)&7)) |
121 | 128 | ||
129 | typedef void tLCDPixelFunc(int x, int y); /* for b&w */ | ||
130 | typedef void tLCDBlockFunc(unsigned char *address, unsigned mask, unsigned bits); | ||
131 | |||
122 | /* Memory copy of display bitmap */ | 132 | /* Memory copy of display bitmap */ |
123 | extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; | 133 | extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; |
124 | 134 | ||
125 | extern void lcd_set_invert_display(bool yesno); | 135 | extern void lcd_set_invert_display(bool yesno); |
126 | extern void lcd_set_flip(bool yesno); | 136 | extern void lcd_set_flip(bool yesno); |
127 | extern void lcd_roll(int pixels); | 137 | extern void lcd_roll(int pixels); |
138 | |||
139 | extern void lcd_set_drawmode(int mode); | ||
140 | extern int lcd_get_drawmode(void); | ||
128 | extern void lcd_setmargins(int xmargin, int ymargin); | 141 | extern void lcd_setmargins(int xmargin, int ymargin); |
129 | extern int lcd_getxmargin(void); | 142 | extern int lcd_getxmargin(void); |
130 | extern int lcd_getymargin(void); | 143 | extern int lcd_getymargin(void); |
131 | extern void lcd_setfont(int font); | 144 | extern void lcd_setfont(int font); |
132 | extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); | 145 | extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); |
146 | |||
133 | extern void lcd_drawpixel(int x, int y); | 147 | extern void lcd_drawpixel(int x, int y); |
134 | extern void lcd_clearpixel(int x, int y); | ||
135 | extern void lcd_invertpixel(int x, int y); | ||
136 | extern void lcd_drawline(int x1, int y1, int x2, int y2); | 148 | extern void lcd_drawline(int x1, int y1, int x2, int y2); |
137 | extern void lcd_clearline(int x1, int y1, int x2, int y2); | 149 | extern void lcd_hline(int x1, int x2, int y); |
138 | extern void lcd_drawrect(int x, int y, int nx, int ny); | 150 | extern void lcd_vline(int x, int y1, int y2); |
139 | extern void lcd_clearrect(int x, int y, int nx, int ny); | 151 | extern void lcd_drawrect(int x, int y, int width, int height); |
140 | extern void lcd_fillrect(int x, int y, int nx, int ny); | 152 | extern void lcd_fillrect(int x, int y, int width, int height); |
141 | extern void lcd_invertrect(int x, int y, int nx, int ny); | ||
142 | extern void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 153 | extern void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, |
143 | bool clear); | 154 | bool clear); |
144 | extern void lcd_putsxy(int x, int y, const unsigned char *string); | 155 | extern void lcd_putsxy(int x, int y, const unsigned char *string); |
156 | |||
145 | extern void lcd_invertscroll(int x, int y); | 157 | extern void lcd_invertscroll(int x, int y); |
146 | extern void lcd_bidir_scroll(int threshold); | 158 | extern void lcd_bidir_scroll(int threshold); |
147 | extern void lcd_scroll_step(int pixels); | 159 | extern void lcd_scroll_step(int pixels); |