1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Alan Korr
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
35 #if defined(SIMULATOR)
36 #include "sim_icons.h"
42 #define LCDR (PBDR_ADDR+1)
44 #ifdef HAVE_LCD_CHARCELLS
46 #define LCD_DS 1 // PB0 = 1 --- 0001 --- LCD-DS
47 #define LCD_CS 2 // PB1 = 1 --- 0010 --- /LCD-CS
48 #define LCD_SD 4 // PB2 = 1 --- 0100 --- LCD-SD
49 #define LCD_SC 8 // PB3 = 1 --- 1000 --- LCD-SC
50 #ifdef HAVE_NEW_CHARCELL_LCD
51 # define LCD_CONTRAST_SET ((char)0x50)
52 # define LCD_CRAM ((char)0x80) /* Characters */
53 # define LCD_PRAM ((char)0xC0) /* Patterns */
54 # define LCD_IRAM ((char)0x40) /* Icons */
56 # define LCD_CONTRAST_SET ((char)0xA8)
57 # define LCD_CRAM ((char)0xB0) /* Characters */
58 # define LCD_PRAM ((char)0x80) /* Patterns */
59 # define LCD_IRAM ((char)0xE0) /* Icons */
61 #define LCD_CURSOR(x,y) ((char)(LCD_CRAM+((y)*16+(x))))
62 #define LCD_ICON(i) ((char)(LCD_IRAM+i))
66 #define LCD_SD 1 // PB0 = 1 --- 0001
67 #define LCD_SC 2 // PB1 = 1 --- 0010
68 #define LCD_RS 4 // PB2 = 1 --- 0100
69 #define LCD_CS 8 // PB3 = 1 --- 1000
72 #define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00)
73 #define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10)
74 #define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20)
75 #define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28)
76 #define LCD_SET_DISPLAY_START_LINE ((char)0x40)
77 #define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81)
78 #define LCD_SET_SEGMENT_REMAP ((char)0xA0)
79 #define LCD_SET_LCD_BIAS ((char)0xA2)
80 #define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4)
81 #define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5)
82 #define LCD_SET_NORMAL_DISPLAY ((char)0xA6)
83 #define LCD_SET_REVERSE_DISPLAY ((char)0xA7)
84 #define LCD_SET_INDICATOR_OFF ((char)0xAC)
85 #define LCD_SET_INDICATOR_ON ((char)0xAD)
86 #define LCD_SET_DISPLAY_OFF ((char)0xAE)
87 #define LCD_SET_DISPLAY_ON ((char)0xAF)
88 #define LCD_SET_PAGE_ADDRESS ((char)0xB0)
89 #define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0)
90 #define LCD_SET_DISPLAY_OFFSET ((char)0xD3)
91 #define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0)
92 #define LCD_SOFTWARE_RESET ((char)0xE2)
93 #define LCD_NOP ((char)0xE3)
94 #define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE)
96 /* LCD command codes */
97 #define LCD_CNTL_RESET 0xe2 // Software reset
98 #define LCD_CNTL_POWER 0x2f // Power control
99 #define LCD_CNTL_CONTRAST 0x81 // Contrast
100 #define LCD_CNTL_OUTSCAN 0xc8 // Output scan direction
101 #define LCD_CNTL_SEGREMAP 0xa1 // Segment remap
102 #define LCD_CNTL_DISPON 0xaf // Display on
104 #define LCD_CNTL_PAGE 0xb0 // Page address
105 #define LCD_CNTL_HIGHCOL 0x10 // Upper column address
106 #define LCD_CNTL_LOWCOL 0x00 // Lower column address
109 #endif /* CHARCELL or BITMAP */
112 /*** generic code ***/
124 static void scroll_thread(void);
125 static char scroll_stack
[DEFAULT_STACK_SIZE
];
126 static char scroll_name
[] = "scroll";
127 static char scroll_speed
= 8; /* updates per second */
128 static char scroll_spacing
= 3; /* spaces between end and start of text */
131 static struct scrollinfo scroll
; /* only one scroll line at the moment */
132 static int scroll_count
= 0;
139 * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines)
141 * - /CS -> Chip Selection line :
142 * 0 : LCD chipset is activated.
143 * - DS -> Data Selection line, latched at the rising edge
144 * of the 8th serial clock (*) :
145 * 0 : instruction register,
147 * - SC -> Serial Clock line (SDA).
148 * - SD -> Serial Data line (SCK), latched at the rising edge
149 * of each serial clock (*).
153 * \______________________________________________________/
154 * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____
155 * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/
156 * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____
158 * _____ _ _ _ _ _ _ _ ________
159 * SC \ * \ * \ * \ * \ * \ * \ * \ *
160 * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
161 * _ _________________________________________________________
163 * _/\_________________________________________________________
168 * The only way to do logical operations in an atomic way
171 * or.b/and.b/tst.b/xor.b #imm,@(r0,gbr)
173 * but GCC doesn't generate them at all so some assembly
174 * codes are needed here.
176 * The Global Base Register gbr is expected to be zero
177 * and r0 is the address of one register in the on-chip
182 #define ASM_IMPLEMENTATION
184 static void lcd_write(bool command
, int byte
) __attribute__ ((section (".icode")));
185 static void lcd_write(bool command
, int byte
)
187 #ifdef ASM_IMPLEMENTATION
189 asm("and.b %0, @(r0,gbr)"
191 : /* %0 */ "I"(~(LCD_CS
|LCD_DS
|LCD_SD
|LCD_SC
)),
197 "and.b %2,@(r0,gbr)\n\t"
200 "or.b %3,@(r0,gbr)\n"
202 "or.b %4,@(r0,gbr)\n"
207 : /* %0 */ "r"(((unsigned)byte
)<<16),
209 /* %2 */ "I"(~(LCD_SC
|LCD_SD
|LCD_DS
)),
210 /* %3 */ "I"(LCD_SD
),
211 /* %4 */ "I"(LCD_SC
),
217 "and.b %2, @(r0,gbr)\n\t"
220 "or.b %3, @(r0,gbr)\n"
222 "or.b %4, @(r0,gbr)\n"
227 : /* %0 */ "r"(((unsigned)byte
)<<16),
229 /* %2 */ "I"(~(LCD_SC
|LCD_SD
)),
230 /* %3 */ "I"(LCD_SD
|LCD_DS
),
231 /* %4 */ "I"(LCD_SC
|LCD_DS
),
236 "and.b %2, @(r0,gbr)\n\t"
239 "or.b %3, @(r0,gbr)\n"
241 "or.b %4, @(r0,gbr)\n"
242 "and.b %2, @(r0,gbr)\n\t"
245 "or.b %3, @(r0,gbr)\n"
247 "or.b %4, @(r0,gbr)\n"
248 "and.b %2, @(r0,gbr)\n\t"
251 "or.b %3, @(r0,gbr)\n"
253 "or.b %4, @(r0,gbr)\n"
254 "and.b %2, @(r0,gbr)\n\t"
257 "or.b %3, @(r0,gbr)\n"
259 "or.b %4, @(r0,gbr)\n"
260 "and.b %2, @(r0,gbr)\n\t"
263 "or.b %3, @(r0,gbr)\n"
265 "or.b %4, @(r0,gbr)\n"
266 "and.b %2, @(r0,gbr)\n\t"
269 "or.b %3, @(r0,gbr)\n"
271 "or.b %4, @(r0,gbr)\n"
272 "and.b %2, @(r0,gbr)\n\t"
275 "or.b %3, @(r0,gbr)\n"
277 "or.b %4, @(r0,gbr)\n"
278 "and.b %2, @(r0,gbr)\n\t"
281 "or.b %3, @(r0,gbr)\n"
283 "or.b %4, @(r0,gbr)\n"
285 : /* %0 */ "r"(((unsigned)byte
)<<16),
287 /* %2 */ "I"(~(LCD_SC
|LCD_SD
)),
288 /* %3 */ "I"(LCD_SD
|LCD_DS
),
289 /* %4 */ "I"(LCD_SC
|LCD_DS
),
293 asm("or.b %0, @(r0,gbr)"
295 : /* %0 */ "I"(LCD_CS
|LCD_DS
|LCD_SD
|LCD_SC
),
303 PBDR
&= ~LCD_CS
; /* enable lcd chip select */
306 on
=~(LCD_SD
|LCD_SC
|LCD_DS
);
314 /* clock out each bit, MSB first */
323 PBDR
|= LCD_CS
; /* disable lcd chip select */
325 #endif /* ASM_IMPLEMENTATION */
326 #endif /* !SIMULATOR */
328 /*** model specific code */
330 #ifdef HAVE_LCD_CHARCELLS
332 #ifdef HAVE_NEW_CHARCELL_LCD
334 static const unsigned char lcd_ascii
[] = {
335 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
336 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
337 0x10,0x11,0x05,0x13,0x14,0x15,0x16,0x17,
338 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
339 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
340 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
341 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
342 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
343 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
344 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
345 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
346 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
347 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
348 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
349 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
350 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
351 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
352 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
353 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
354 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
355 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
356 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
357 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
358 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
359 0x41,0x41,0x41,0x41,0x41,0x41,0x20,0x43,
360 0x45,0x45,0x45,0x45,0x49,0x49,0x49,0x49,
361 0x44,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x20,
362 0x20,0x55,0x55,0x55,0x55,0x59,0x20,0x20,
363 0x61,0x61,0x61,0x61,0x61,0x61,0x20,0x63,
364 0x65,0x65,0x65,0x65,0x69,0x69,0x69,0x69,
365 0x6f,0x6e,0x6f,0x6f,0x6f,0x6f,0x6f,0x20,
366 0x20,0x75,0x75,0x75,0x75,0x79,0x20,0x79
371 static const unsigned char lcd_ascii
[] = {
372 0x00,0x01,0x02,0x03,0x00,0x84,0x85,0x89,
373 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
374 0xec,0xe3,0xe2,0xe1,0xe0,0xdf,0x15,0x00,
375 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
376 0x24,0x25,0x26,0x37,0x06,0x29,0x2a,0x2b,
377 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,
378 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,
379 0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,
380 0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,
381 0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,
382 0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,
383 0x5c,0x5d,0x5e,0xa9,0x33,0xce,0x00,0x15,
384 0x00,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
385 0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
386 0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,
387 0x7c,0x7d,0x7e,0x24,0x24,0x24,0x24,0x24,
388 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
389 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
390 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
391 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
392 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
393 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
394 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
395 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
396 0x45,0x45,0x45,0x45,0x45,0x45,0x24,0x47,
397 0x49,0x49,0x49,0x49,0x4d,0x4d,0x4d,0x4d,
398 0x48,0x52,0x53,0x53,0x53,0x53,0x53,0x24,
399 0x24,0x59,0x59,0x59,0x59,0x5d,0x24,0x24,
400 0x65,0x65,0x65,0x65,0x65,0x65,0x24,0x67,
401 0x69,0x69,0x69,0x69,0x6d,0x6d,0x6d,0x6d,
402 0x73,0x72,0x73,0x73,0x73,0x73,0x73,0x24,
403 0x24,0x79,0x79,0x79,0x79,0x7d,0x24,0x7d
405 #endif /* HAVE_NEW_CHARCELL_LCD */
408 void lcd_clear_display(void)
411 lcd_write(true,LCD_CURSOR(0,0));
413 lcd_write(false,lcd_ascii
[' ']);
416 void lcd_puts(int x
, int y
, unsigned char *string
)
418 lcd_write(true,LCD_CURSOR(x
,y
));
419 while (*string
&& x
++<11)
420 lcd_write(false,lcd_ascii
[*(unsigned char*)string
++]);
423 void lcd_define_pattern (int which
,char *pattern
,int length
)
426 lcd_write(true,LCD_PRAM
|which
);
427 for (i
=0;i
<length
;i
++)
428 lcd_write(false,pattern
[i
]);
431 void lcd_double_height(bool on
)
433 lcd_write(true,on
?9:8);
436 static char icon_pos
[] =
438 0, 0, 0, 0, /* Battery */
455 static char icon_mask
[] =
457 0x02, 0x08, 0x04, 0x10, /* Battery */
474 void lcd_icon(int icon
, bool enable
)
476 static unsigned char icon_mirror
[11] = {0};
479 pos
= icon_pos
[icon
];
480 mask
= icon_mask
[icon
];
482 lcd_write(true, LCD_ICON(pos
));
485 icon_mirror
[pos
] |= mask
;
487 icon_mirror
[pos
] &= ~mask
;
489 lcd_write(false, icon_mirror
[pos
]);
491 #endif /* !SIMULATOR */
493 #endif /* HAVE_LCD_CHARCELLS */
495 #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
496 void lcd_icon(int icon
, bool enable
)
498 sim_lcd_icon(icon
, enable
);
502 #if defined(HAVE_LCD_CHARCELLS) || defined(SIMULATOR) /* not BITMAP */
505 create_thread(scroll_thread
, scroll_stack
,
506 sizeof(scroll_stack
), scroll_name
);
507 #if defined(LOADABLE_FONTS) && defined(SIMULATOR)
514 void lcd_set_contrast(int val
)
519 #ifdef HAVE_LCD_BITMAP
520 void lcd_set_contrast(int val
)
522 lcd_write(true, LCD_CNTL_CONTRAST
);
523 lcd_write(true, val
);
526 void lcd_set_contrast(int val
)
528 lcd_write(true, LCD_CONTRAST_SET
);
529 lcd_write(false, 31-val
);
534 #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) /* not CHARCELLS */
537 * All bitmaps have this format:
538 * Bits within a byte are arranged veritcally, LSB at top.
539 * Bytes are stored in column-major format, with byte 0 at top left,
540 * byte 1 is 2nd from top, etc. Bytes following left-most column
541 * starts 2nd left column, etc.
543 * Note: The HW takes bitmap bytes in row-major order.
545 * Memory copy of display bitmap
547 unsigned char lcd_framebuffer
[LCD_WIDTH
][LCD_HEIGHT
/8] __attribute__ ((section (".idata")));
550 static int xmargin
=0;
551 static int ymargin
=0;
554 * ASCII character generation tables
556 * This contains only the printable characters (0x20-0x7f).
557 * Each element in this table is a character pattern bitmap.
559 #define ASCII_MIN 0x20 /* First char in table */
560 #define ASCII_MAX 0x7f /* Last char in table */
562 extern unsigned char char_gen_6x8
[][5];
563 extern unsigned char char_gen_8x12
[][14];
564 extern unsigned char char_gen_12x16
[][22];
566 /* All zeros and ones bitmaps for area filling */
567 static unsigned char zeros
[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 static unsigned char ones
[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
571 static char fonts
[] = { 6,8,12 };
572 static char fontheight
[] = { 8,12,16 };
581 /* Initialize PB0-3 as output pins */
582 PBCR2
&= 0xff00; /* MD = 00 */
583 PBIOR
|= 0x000f; /* IOR = 1 */
587 create_thread(scroll_thread
, scroll_stack
,
588 sizeof(scroll_stack
), scroll_name
);
592 * Update the display.
593 * This must be called after all other LCD functions that change the display.
595 void lcd_update (void) __attribute__ ((section (".icode")));
596 void lcd_update (void)
600 /* Copy display bitmap to hardware */
601 for (y
= 0; y
< LCD_HEIGHT
/8; y
++)
603 lcd_write (true, LCD_CNTL_PAGE
| (y
& 0xf));
604 lcd_write (true, LCD_CNTL_HIGHCOL
);
605 lcd_write (true, LCD_CNTL_LOWCOL
);
607 for (x
= 0; x
< LCD_WIDTH
; x
++)
608 lcd_write (false, lcd_framebuffer
[x
][y
]);
613 * Update a fraction of the display.
615 void lcd_update_rect (int, int, int, int) __attribute__ ((section (".icode")));
616 void lcd_update_rect (int x_start
, int y
,
617 int width
, int height
)
623 /* The Y coordinates have to work on even 8 pixel rows */
624 ymax
= (y
+ height
)/8;
627 xmax
= x_start
+ width
;
631 if(ymax
>= LCD_HEIGHT
/8)
632 ymax
= LCD_HEIGHT
/8-1;
634 /* Copy specified rectange bitmap to hardware */
635 for (; y
<= ymax
; y
++)
637 lcd_write (true, LCD_CNTL_PAGE
| (y
& 0xf));
638 lcd_write (true, LCD_CNTL_HIGHCOL
| ((x_start
>>4) & 0xf));
639 lcd_write (true, LCD_CNTL_LOWCOL
| (x_start
& 0xf));
641 for (x
= x_start
; x
< xmax
; x
++)
642 lcd_write (false, lcd_framebuffer
[x
][y
]);
646 #endif /* SIMULATOR */
651 void lcd_clear_display (void)
653 #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
654 /* Clear just the text portion of the display */
656 for (y
= 8; y
<= (32 + 7); ++y
)
658 for (x
= 0; x
< LCD_WIDTH
; x
++)
661 /* this function is being used when simulating a charcell LCD and
662 then we update immediately */
665 memset (lcd_framebuffer
, 0, sizeof lcd_framebuffer
);
669 void lcd_setfont(int newfont
)
674 void lcd_setmargins(int x
, int y
)
680 int lcd_getxmargin(void)
685 int lcd_getymargin(void)
692 #ifdef LOADABLE_FONTS
694 static unsigned char* _font
= NULL
;
696 int lcd_init_fonts(void)
699 _font
= ajf_read_font("/system.ajf");
703 lcd_putsxy(0,0,"No font", 0);
710 void lcd_setldfont(unsigned char* f
)
715 unsigned char* lcd_getcurrentldfont()
718 panicf("No font loaded!");
723 * Return width and height of a string with a given font.
725 int lcd_getstringsize(unsigned char *str
, unsigned char* font
, int *w
, int *h
)
732 panicf("No font specified");
737 ajf_get_charsize(ch
, font
, &dw
, &dh
);
749 * Put a string at specified bit position
752 void lcd_putsldfxy(int x
, int y
, unsigned char *str
)
761 lcd_putsxy(0,0,"No font", 0);
765 while (((ch
= *str
++) != '\0'))
767 unsigned char *char_buf
= ajf_get_charbuf(ch
, _font
, &nx
, &ny
);
770 char_buf
= ajf_get_charbuf('?', _font
, &nx
, &ny
);
774 if(lcd_x
+ nx
> LCD_WIDTH
)
777 lcd_bitmap (&char_buf
[0], lcd_x
, lcd_y
, nx
, ny
, true);
786 extern unsigned char char_dw_8x8_prop
[][9];
789 * Return width and height of a given font.
791 int lcd_getstringsize(unsigned char *str
, unsigned int font
, int *w
, int *h
)
795 unsigned char ch
, byte
;
798 while((ch
= *str
++)) {
799 /* Limit to char generation table */
801 /* replace unsupported letters with question marks */
806 byte
= char_dw_8x8_prop
[ch
][8];
807 width
+= (byte
>>4) + 1;
808 if((byte
& 0x0f) > height
)
809 height
= byte
& 0x0f;
819 * Put a string at specified bit position
822 void lcd_putspropxy(int x
, int y
, unsigned char *str
, int thisfont
)
833 while (((ch
= *str
++) != '\0'))
835 /* Limit to char generation table */
837 /* replace unsupported letters with question marks */
842 nx
= char_dw_8x8_prop
[ch
][8] >> 4;
844 if(lcd_x
+ nx
> LCD_WIDTH
)
847 src
= char_dw_8x8_prop
[ch
];
848 lcd_clearrect (lcd_x
+nx
, lcd_y
, 1, ny
);
849 lcd_bitmap (src
, lcd_x
, lcd_y
, nx
, ny
, true);
858 * Put a string at specified character position
860 void lcd_puts(int x
, int y
, unsigned char *str
)
862 #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
863 /* We make the simulator truncate the string if it reaches the right edge,
864 as otherwise it'll wrap. The real target doesn't wrap. */
867 if(strlen(str
)+x
> 11 ) {
868 strncpy(buffer
, str
, sizeof buffer
);
880 lcd_putspropxy( xmargin
+ x
*fonts
[font
],
881 ymargin
+ y
*fontheight
[font
],
886 lcd_getstringsize(str
,_font
,&w
,&h
);
887 lcd_putsldfxy( xmargin
+ x
*w
/strlen(str
), ymargin
+ y
*h
, str
);
890 lcd_putsxy( xmargin
+ x
*fonts
[font
],
891 ymargin
+ y
*fontheight
[font
],
894 #if defined(SIMULATOR) && defined(HAVE_LCD_CHARCELLS)
895 /* this function is being used when simulating a charcell LCD and
896 then we update immediately */
903 * Put a string at specified bit position
905 void lcd_putsxy(int x
, int y
, unsigned char *str
, int thisfont
)
908 lcd_putspropxy(x
,y
,str
,thisfont
);
911 int nx
= fonts
[thisfont
];
912 int ny
= fontheight
[thisfont
];
918 #ifdef LOADABLE_FONTS
920 lcd_putsldfxy(x
,y
,str
);
925 while (((ch
= *str
++) != '\0') && (lcd_x
+ nx
< LCD_WIDTH
))
927 if (lcd_y
+ ny
> LCD_HEIGHT
)
930 /* Limit to char generation table */
931 if ((ch
< ASCII_MIN
) || (ch
> ASCII_MAX
))
932 /* replace unsupported letters with question marks */
933 ch
= '?' - ASCII_MIN
;
938 src
= char_gen_12x16
[ch
];
939 else if (thisfont
== 1)
940 src
= char_gen_8x12
[ch
];
942 src
= char_gen_6x8
[ch
];
944 lcd_bitmap (src
, lcd_x
, lcd_y
, nx
-1, ny
, true);
945 lcd_bitmap (zeros
, lcd_x
+nx
-1, lcd_y
, 1, ny
, true);
954 * Display a bitmap at (x, y), size (nx, ny)
955 * clear is true to clear destination area first
957 void lcd_bitmap (unsigned char *src
, int x
, int y
, int nx
, int ny
,
958 bool clear
) __attribute__ ((section (".icode")));
959 void lcd_bitmap (unsigned char *src
, int x
, int y
, int nx
, int ny
,
964 unsigned int data
, mask
, mask2
, mask3
, mask4
;
967 if (((unsigned)x
>= LCD_WIDTH
) || ((unsigned)y
>= LCD_HEIGHT
))
969 if (((unsigned)(x
+ nx
)) >= LCD_WIDTH
)
971 if (((unsigned)(y
+ ny
)) >= LCD_HEIGHT
)
975 dst2
= &lcd_framebuffer
[x
][y
/8];
978 /* Calculate bit masks */
979 mask4
= ~(0xfe << ((ny
-1) & 7));
982 mask
= ~(0xff << shift
);
989 mask
= mask2
= mask3
= 0xff;
991 /* Loop for each column */
992 for (x
= 0; x
< nx
; x
++)
995 dst2
+= LCD_HEIGHT
/8;
1001 /* First partial row */
1002 data
= *src
++ << shift
;
1003 *dst
= (*dst
& mask
) | data
;
1007 /* Intermediate rows */
1008 for (y
= 8; y
< ny
-8; y
+= 8)
1010 data
|= *src
++ << shift
;
1011 *dst
= (*dst
& mask2
) | data
;
1017 /* Last partial row */
1019 data
|= *src
++ << shift
;
1020 *dst
= (*dst
& mask3
) | (data
& mask4
);
1025 * Draw a rectangle with point a (upper left) at (x, y)
1028 void lcd_drawrect (int x
, int y
, int nx
, int ny
)
1037 if (x
+ nx
> LCD_WIDTH
)
1039 if (y
+ ny
> LCD_HEIGHT
)
1040 ny
= LCD_HEIGHT
- y
;
1042 /* vertical lines */
1043 for (i
= 0; i
< ny
; i
++) {
1044 DRAW_PIXEL(x
, (y
+ i
));
1045 DRAW_PIXEL((x
+ nx
- 1), (y
+ i
));
1048 /* horizontal lines */
1049 for (i
= 0; i
< nx
; i
++) {
1050 DRAW_PIXEL((x
+ i
),y
);
1051 DRAW_PIXEL((x
+ i
),(y
+ ny
- 1));
1056 * Clear a rectangular area at (x, y), size (nx, ny)
1058 void lcd_clearrect (int x
, int y
, int nx
, int ny
)
1061 for (i
= 0; i
< nx
; i
++)
1062 lcd_bitmap (zeros
, x
+i
, y
, 1, ny
, true);
1066 * Fill a rectangular area at (x, y), size (nx, ny)
1068 void lcd_fillrect (int x
, int y
, int nx
, int ny
)
1071 for (i
= 0; i
< nx
; i
++)
1072 lcd_bitmap (ones
, x
+i
, y
, 1, ny
, true);
1075 /* Invert a rectangular area at (x, y), size (nx, ny) */
1076 void lcd_invertrect (int x
, int y
, int nx
, int ny
)
1085 if (x
+ nx
> LCD_WIDTH
)
1087 if (y
+ ny
> LCD_HEIGHT
)
1088 ny
= LCD_HEIGHT
- y
;
1090 for (i
= 0; i
< nx
; i
++)
1091 for (j
= 0; j
< ny
; j
++)
1092 INVERT_PIXEL((x
+ i
), (y
+ j
));
1095 void lcd_drawline( int x1
, int y1
, int x2
, int y2
)
1100 int d
, dinc1
, dinc2
;
1101 int x
, xinc1
, xinc2
;
1102 int y
, yinc1
, yinc2
;
1104 deltax
= abs(x2
- x1
);
1105 deltay
= abs(y2
- y1
);
1107 if(deltax
>= deltay
)
1110 d
= 2 * deltay
- deltax
;
1112 dinc2
= (deltay
- deltax
) * 2;
1121 d
= 2 * deltax
- deltay
;
1123 dinc2
= (deltax
- deltay
) * 2;
1129 numpixels
++; /* include endpoints */
1146 for(i
=0; i
<numpixels
; i
++)
1165 void lcd_clearline( int x1
, int y1
, int x2
, int y2
)
1170 int d
, dinc1
, dinc2
;
1171 int x
, xinc1
, xinc2
;
1172 int y
, yinc1
, yinc2
;
1174 deltax
= abs(x2
- x1
);
1175 deltay
= abs(y2
- y1
);
1177 if(deltax
>= deltay
)
1180 d
= 2 * deltay
- deltax
;
1182 dinc2
= (deltay
- deltax
) * 2;
1191 d
= 2 * deltax
- deltay
;
1193 dinc2
= (deltax
- deltay
) * 2;
1199 numpixels
++; /* include endpoints */
1216 for(i
=0; i
<numpixels
; i
++)
1236 * Set a single pixel
1238 void lcd_drawpixel(int x
, int y
)
1244 * Clear a single pixel
1246 void lcd_clearpixel(int x
, int y
)
1252 * Invert a single pixel
1254 void lcd_invertpixel(int x
, int y
)
1260 * Return width and height of a given font.
1262 void lcd_getfontsize(unsigned int font
, int *width
, int *height
)
1264 if(font
< sizeof(fonts
)) {
1265 *width
= fonts
[font
];
1266 *height
= fontheight
[font
];
1271 /* no LCD defined, no code to use */
1274 void lcd_puts_scroll(int x
, int y
, unsigned char* string
)
1276 struct scrollinfo
* s
= &scroll
;
1277 #ifdef HAVE_LCD_CHARCELLS
1281 #if defined(LCD_PROPFONTS) || defined(LOADABLE_FONTS)
1282 unsigned char ch
[2];
1286 lcd_getfontsize(font
, &width
, &height
);
1287 #if defined(LCD_PROPFONTS) || defined(LOADABLE_FONTS)
1288 ch
[1] = 0; /* zero terminate */
1293 #ifdef LCD_PROPFONTS
1294 (width
+ lcd_getstringsize(ch
, 0, &w
, &h
) <
1295 (LCD_WIDTH
- x
*8))) {
1297 (width
+ lcd_getstringsize(ch
, _font
, &w
, &h
) <
1298 (LCD_WIDTH
- x
*8))) {
1302 ch
[0]=string
[s
->space
];
1305 s
->space
= (LCD_WIDTH
- xmargin
- x
*width
) / width
;
1309 lcd_puts(x
,y
,string
);
1310 s
->textlen
= strlen(string
);
1313 #if defined(LCD_PROPFONTS)
1315 lcd_getstringsize(string
,0,&w
,&h
);
1316 if ( w
> LCD_WIDTH
- xmargin
) {
1317 #elif defined(LOADABLE_FONTS)
1319 lcd_getstringsize(string
,_font
,&w
,&h
);
1320 if ( w
> LCD_WIDTH
- xmargin
) {
1322 if ( s
->textlen
> s
->space
) {
1327 strncpy(s
->text
,string
,sizeof s
->text
);
1328 s
->text
[sizeof s
->text
- 1] = 0;
1329 memset(s
->line
, 0, sizeof s
->line
);
1330 strncpy(s
->line
,string
,
1331 s
->space
> (int)sizeof s
->line
?
1332 (int)sizeof s
->line
: s
->space
);
1333 s
->line
[sizeof s
->line
- 1] = 0;
1338 void lcd_stop_scroll(void)
1340 if ( scroll_count
) {
1341 struct scrollinfo
* s
= &scroll
;
1344 #ifdef LCD_PROPFONTS
1346 lcd_clearrect(xmargin
+ s
->startx
*fonts
[font
],
1347 ymargin
+ s
->starty
*fontheight
[font
],
1348 LCD_WIDTH
- xmargin
,
1351 #elif defined(LOADABLE_FONTS)
1354 lcd_getstringsize( s
->text
, _font
, &w
, &h
);
1355 lcd_clearrect(xmargin
+ s
->startx
*w
/s
->textlen
,
1356 ymargin
+ s
->starty
*h
,
1357 LCD_WIDTH
- xmargin
,
1364 /* restore scrolled row */
1365 lcd_puts(s
->startx
,s
->starty
,s
->text
);
1370 void lcd_scroll_pause(void)
1375 void lcd_scroll_resume(void)
1380 void lcd_scroll_speed(int speed
)
1382 scroll_speed
= speed
;
1385 static void scroll_thread(void)
1387 struct scrollinfo
* s
= &scroll
;
1390 if ( !scroll_count
) {
1394 /* wait 0.5s before starting scroll */
1395 if ( scroll_count
< scroll_speed
/2 )
1399 for ( i
=0; i
<s
->space
-1; i
++ )
1400 s
->line
[i
] = s
->line
[i
+1];
1402 if ( s
->offset
< s
->textlen
) {
1403 s
->line
[(int)s
->space
- 1] = s
->text
[(int)s
->offset
];
1407 s
->line
[s
->space
- 1] = ' ';
1408 if ( s
->offset
< s
->textlen
+ scroll_spacing
- 1 )
1414 #ifdef LCD_PROPFONTS
1415 lcd_clearrect(xmargin
+ s
->startx
*fonts
[font
],
1416 ymargin
+ s
->starty
*fontheight
[font
],
1417 LCD_WIDTH
- xmargin
,
1419 #elif defined(LOADABLE_FONTS)
1422 lcd_getstringsize( s
->text
, _font
, &w
, &h
);
1423 lcd_clearrect(xmargin
+ s
->startx
*w
/s
->textlen
,
1424 ymargin
+ s
->starty
*h
,
1425 LCD_WIDTH
- xmargin
,
1429 lcd_puts(s
->startx
,s
->starty
,s
->line
);
1432 sleep(HZ
/scroll_speed
);
1437 /* -----------------------------------------------------------------
1439 * eval: (load-file "../rockbox-mode.el")