From 369ba01afd31d021f16f5c8b68e773f043101ca0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 11 Apr 2002 12:37:49 +0000 Subject: [PATCH] incorporated Gary's bitmap LCD code, supports SIMULATOR. Seems to work. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@77 a1c6a512-1295-4272-9138-f99709370657 --- firmware/lcd.c | 362 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 323 insertions(+), 39 deletions(-) diff --git a/firmware/lcd.c b/firmware/lcd.c index 5563bbe881..e8716a95fc 100644 --- a/firmware/lcd.c +++ b/firmware/lcd.c @@ -20,26 +20,41 @@ #include "lcd.h" void lcd_data (int data) - { lcd_byte (data,1); } +{ + lcd_byte (data,1); +} void lcd_instruction (int instruction) - { lcd_byte (instruction,0); } +{ + lcd_byte (instruction,0); +} void lcd_zero (int length) - { length *= 8; while (--length >= 0) lcd_data (0); } +{ + length *= 8; + while (--length >= 0) + lcd_data (0); +} void lcd_fill (int data,int length) - { length *= 8; while (--length >= 0) lcd_data (data); } +{ + length *= 8; + while (--length >= 0) + lcd_data (data); +} void lcd_copy (void *data,int count) - { while (--count >= 0) lcd_data (*((char *)data)++); } +{ + while (--count >= 0) + lcd_data (*((char *)data)++); +} -#ifdef JBP +#ifdef HAVE_LCD_CHARCELLS # ifndef JBP_OLD static char const lcd_ascii[] = - { +{ /*****************************************************************************************/ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ /* ************************************************************************************/ @@ -91,45 +106,314 @@ static char const lcd_ascii[] = # endif void lcd_puts (char const *string) - { - while (*string) - lcd_data (LCD_ASCII(*string++)); - } +{ + while (*string) + lcd_data (LCD_ASCII(*string++)); +} void lcd_putns (char const *string,int n) - { - while (n--) - lcd_data (LCD_ASCII(*string++)); - } +{ + while (n--) + lcd_data (LCD_ASCII(*string++)); +} void lcd_putc (int character) - { - lcd_data (LCD_ASCII(character)); - } +{ + lcd_data (LCD_ASCII(character)); +} void lcd_pattern (int which,char const *pattern,int count) - { - lcd_instruction (LCD_PRAM|which); - lcd_copy ((void *)pattern,count); - } - -#else -# error "JBR : FIX ME" -#endif +{ + lcd_instruction (LCD_PRAM|which); + lcd_copy ((void *)pattern,count); +} void lcd_puthex (unsigned int value,int digits) - { - switch (digits) - { - case 8: - lcd_puthex (value >> 16,4); - case 4: - lcd_puthex (value >> 8,2); - case 2: - lcd_puthex (value >> 4,1); - case 1: - value &= 15; - lcd_putc (value+((value < 10) ? '0' : ('A'-10))); - } +{ + switch (digits) { + case 8: + lcd_puthex (value >> 16,4); + case 4: + lcd_puthex (value >> 8,2); + case 2: + lcd_puthex (value >> 4,1); + case 1: + value &= 15; + lcd_putc (value+((value < 10) ? '0' : ('A'-10))); } +} + + +/* HAVE_LCD_CHARCELLS */ +#elif defined(HAVE_LCD_BITMAP) + +/* + * All bitmaps have this format: + * Bits within a byte are arranged veritcally, LSB at top. + * Bytes are stored in column-major format, with byte 0 at top left, + * byte 1 is 2nd from top, etc. Bytes following left-most column + * starts 2nd left column, etc. + * + * Note: The HW takes bitmap bytes in row-major order. + * + * Memory copy of display bitmap + */ +unsigned char display[DISP_X][DISP_Y/8]; + +// +// ASCII character generation tables +// +// This contains only the printable characters (0x20-0x7f). +// Each element in this table is a character pattern bitmap. +// +#define ASCII_MIN 0x20 // First char in table +#define ASCII_MAX 0x7f // Last char in table + +extern const unsigned char char_gen_6x8[][5][1]; +extern const unsigned char char_gen_8x12[][7][2]; +extern const unsigned char char_gen_12x16[][11][2]; + + +/* All zeros and ones bitmaps for area filling */ +static const unsigned char zeros[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; +static const unsigned char ones[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff }; + +static int lcd_y; /* Current pixel row */ +static int lcd_x; /* Current pixel column */ +static int lcd_size; /* Current font width */ + +#ifndef SIMULATOR + +/* + * Initialize LCD + */ +void lcd_init (void) +{ + // Initialize PB0-3 as output pins + PBCR2 &= 0xff00; // MD = 00 + PBIOR |= 0x000f; // IOR = 1 + + // Initialize LCD + lcd_write (TRUE, LCD_CNTL_RESET); + lcd_write (TRUE, LCD_CNTL_POWER); + lcd_write (TRUE, LCD_CNTL_SEGREMAP); + lcd_write (TRUE, LCD_CNTL_OUTSCAN); + lcd_write (TRUE, LCD_CNTL_CONTRAST); + lcd_write (TRUE, 0x30); // Contrast parameter + lcd_write (TRUE, LCD_CNTL_DISPON); + + lcd_clear_display(); + lcd_update(); +} + +/* + * Update the display. + * This must be called after all other LCD funtions that change the display. + */ +void lcd_update (void) +{ + int x, y; + + /* Copy display bitmap to hardware */ + for (y = 0; y < DISP_Y/8; y++) + { + lcd_write (TRUE, LCD_CNTL_PAGE | (y & 0xf)); + lcd_write (TRUE, LCD_CNTL_HIGHCOL); + lcd_write (TRUE, LCD_CNTL_LOWCOL); + + for (x = 0; x < DISP_X; x++) + lcd_write (FALSE, display[x][y]); + } +} + +static void lcd_write (BOOL command, int value) +{ + int bit; + + /* Enable chip select, set DC if data */ + PBDR &= ~(PBDR_LCD_CS1|PBDR_LCD_DC); + if (!command) + PBDR |= PBDR_LCD_DC; + + /* Send each bit, starting with MSB */ + for (bit = 0x80; bit > 0; bit >>= 1) + { + PBDR &= ~(PBDR_LCD_SDA|PBDR_LCD_SCK); + if (value & bit) + PBDR |= PBDR_LCD_SDA; + PBDR |= PBDR_LCD_SCK; + } + + /* Disable chip select */ + PBDR |= PBDR_LCD_CS1; +} + +#endif /* SIMULATOR */ + +/* + * Clear the display + */ +void lcd_clear_display (void) +{ + lcd_position (0, 0, 8); + memset (display, 0, sizeof display); +} + +/* + * Set current x,y position and font size + */ +void lcd_position (int x, int y, int size) +{ + if (x >= 0 && x < DISP_X && y >= 0 && y < DISP_Y) + { + lcd_x = x; + lcd_y = y; + } + + lcd_size = size; +} + +/* + * Display a string at current position and size + */ +void lcd_string (const char *str) +{ + int x = lcd_x; + int nx = lcd_size; + int ny, ch; + const unsigned char *src; + + if (nx == 12) + ny = 16; + else if (nx == 8) + ny = 12; + else + { + nx = 6; + ny = 8; + } + + while ((ch = *str++) != '\0') + { + if (ch == '\n' || lcd_x + nx > DISP_X) + { + /* Wrap to next line */ + lcd_x = x; + lcd_y += ny; + } + + if (lcd_y + ny > DISP_Y) + return; + + /* Limit to char generation table */ + if (ch >= ASCII_MIN && ch <= ASCII_MAX) + { + if (nx == 12) + src = char_gen_12x16[ch-ASCII_MIN][0]; + else if (nx == 8) + src = char_gen_8x12[ch-ASCII_MIN][0]; + else + src = char_gen_6x8[ch-ASCII_MIN][0]; + + lcd_bitmap (src, lcd_x, lcd_y, nx-1, ny, TRUE); + lcd_bitmap (zeros, lcd_x+nx-1, lcd_y, 1, ny, TRUE); + + lcd_x += nx; + } + } +} + +/* + * Display a bitmap at (x, y), size (nx, ny) + * clear is TRUE to clear destination area first + */ +void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, + bool clear) +{ + unsigned char *dst; + unsigned char *dst2 = &display[x][y/8]; + unsigned int data, mask, mask2, mask3, mask4; + int shift = y & 7; + + ny += shift; + + /* Calculate bit masks */ + mask4 = ~(0xfe << ((ny-1) & 7)); + if (clear) + { + mask = ~(0xff << shift); + mask2 = 0; + mask3 = ~mask4; + if (ny <= 8) + mask3 |= mask; + } + else + mask = mask2 = mask3 = 0xff; + + /* Loop for each column */ + for (x = 0; x < nx; x++) + { + dst = dst2; + dst2 += DISP_Y/8; + data = 0; + y = 0; + + if (ny > 8) + { + /* First partial row */ + data = *src++ << shift; + *dst = (*dst & mask) ^ data; + data >>= 8; + dst++; + + /* Intermediate rows */ + for (y = 8; y < ny-8; y += 8) + { + data |= *src++ << shift; + *dst = (*dst & mask2) ^ data; + data >>= 8; + dst++; + } + } + + /* Last partial row */ + if (y + shift < ny) + data |= *src++ << shift; + *dst = (*dst & mask3) ^ (data & mask4); + } +} + +/* + * Clear a rectangular area at (x, y), size (nx, ny) + */ +void lcd_clearrect (int x, int y, int nx, int ny) +{ + int i; + for (i = 0; i < nx; i++) + lcd_bitmap (zeros, x+i, y, 1, ny, TRUE); +} + +/* + * Fill a rectangular area at (x, y), size (nx, ny) + */ +void lcd_fillrect (int x, int y, int nx, int ny) +{ + int i; + for (i = 0; i < nx; i++) + lcd_bitmap (ones, x+i, y, 1, ny, TRUE); +} + +/* Invert a rectangular area at (x, y), size (nx, ny) */ +void lcd_invertrect (int x, int y, int nx, int ny) +{ + int i; + for (i = 0; i < nx; i++) + lcd_bitmap (ones, x+i, y, 1, ny, FALSE); +} + +#else +/* no LCD defined, no code to use */ +#endif