Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2004 by Linus Nielsen Feltzing |
| 11 | * |
| 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. |
| 14 | * |
| 15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 16 | * KIND, either express or implied. |
| 17 | * |
| 18 | ****************************************************************************/ |
| 19 | #include "config.h" |
| 20 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 21 | #include "cpu.h" |
| 22 | #include "lcd.h" |
| 23 | #include "kernel.h" |
| 24 | #include "thread.h" |
| 25 | #include <string.h> |
| 26 | #include <stdlib.h> |
| 27 | #include "file.h" |
| 28 | #include "debug.h" |
| 29 | #include "system.h" |
| 30 | #include "font.h" |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 31 | #include "rbunicode.h" |
Linus Nielsen Feltzing | 41a53d2 | 2005-08-08 19:23:28 +0000 | [diff] [blame] | 32 | #include "bidi.h" |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 33 | |
| 34 | /*** definitions ***/ |
| 35 | |
| 36 | /* LCD command codes */ |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 37 | #define LCD_CNTL_POWER_CONTROL 0x25 |
| 38 | #define LCD_CNTL_VOLTAGE_SELECT 0x2b |
| 39 | #define LCD_CNTL_LINE_INVERT_DRIVE 0x36 |
| 40 | #define LCD_CNTL_GRAY_SCALE_PATTERN 0x39 |
| 41 | #define LCD_CNTL_TEMP_GRADIENT_SELECT 0x4e |
| 42 | #define LCD_CNTL_OSC_FREQUENCY 0x5f |
| 43 | #define LCD_CNTL_ON_OFF 0xae |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 44 | #define LCD_CNTL_OSC_ON_OFF 0xaa |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 45 | #define LCD_CNTL_OFF_MODE 0xbe |
| 46 | #define LCD_CNTL_REVERSE 0xa6 |
| 47 | #define LCD_CNTL_ALL_LIGHTING 0xa4 |
| 48 | #define LCD_CNTL_COMMON_OUTPUT_STATUS 0xc4 |
| 49 | #define LCD_CNTL_COLUMN_ADDRESS_DIR 0xa0 |
| 50 | #define LCD_CNTL_NLINE_ON_OFF 0xe4 |
| 51 | #define LCD_CNTL_DISPLAY_MODE 0x66 |
| 52 | #define LCD_CNTL_DUTY_SET 0x6d |
| 53 | #define LCD_CNTL_ELECTRONIC_VOLUME 0x81 |
| 54 | #define LCD_CNTL_DATA_INPUT_DIR 0x84 |
| 55 | #define LCD_CNTL_DISPLAY_START_LINE 0x8a |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 56 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 57 | #define LCD_CNTL_PAGE 0xb1 |
| 58 | #define LCD_CNTL_COLUMN 0x13 |
| 59 | #define LCD_CNTL_DATA_WRITE 0x1d |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 60 | |
Jens Arnold | a048ff4 | 2005-02-07 11:15:56 +0000 | [diff] [blame] | 61 | #define SCROLLABLE_LINES 26 |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 62 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 63 | /*** globals ***/ |
| 64 | |
Jens Arnold | abd9f83 | 2005-10-19 19:35:24 +0000 | [diff] [blame] | 65 | unsigned char lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH] IBSS_ATTR; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 66 | |
Jens Arnold | abd9f83 | 2005-10-19 19:35:24 +0000 | [diff] [blame] | 67 | static const unsigned char dibits[16] ICONST_ATTR = { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 68 | 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, |
| 69 | 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF |
| 70 | }; |
| 71 | |
| 72 | static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ |
| 73 | static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 74 | static int drawmode = DRMODE_SOLID; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 75 | static int xmargin = 0; |
| 76 | static int ymargin = 0; |
| 77 | static int curfont = FONT_SYSFIXED; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 78 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 79 | /* scrolling */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 80 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 81 | static void scroll_thread(void); |
Linus Nielsen Feltzing | 23756ed | 2005-02-06 02:31:46 +0000 | [diff] [blame] | 82 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 83 | static const char scroll_name[] = "scroll"; |
Jens Arnold | 05af280 | 2005-07-28 08:36:24 +0000 | [diff] [blame] | 84 | static int scroll_ticks = 12; /* # of ticks between updates*/ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 85 | static int scroll_delay = HZ/2; /* ticks delay before start */ |
Jens Arnold | 05af280 | 2005-07-28 08:36:24 +0000 | [diff] [blame] | 86 | static int scroll_step = 6; /* pixels per scroll step */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 87 | static int bidir_limit = 50; /* percent */ |
| 88 | static struct scrollinfo scroll[SCROLLABLE_LINES]; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 89 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 90 | static const char scroll_tick_table[16] = { |
| 91 | /* Hz values: |
| 92 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ |
| 93 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 |
| 94 | }; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 95 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 96 | /*** driver code is in lcd.S ***/ |
| 97 | |
| 98 | /*** hardware configuration ***/ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 99 | |
| 100 | int lcd_default_contrast(void) |
| 101 | { |
Linus Nielsen Feltzing | 23756ed | 2005-02-06 02:31:46 +0000 | [diff] [blame] | 102 | return 28; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 103 | } |
| 104 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 105 | #ifndef SIMULATOR |
| 106 | |
| 107 | void lcd_set_contrast(int val) |
| 108 | { |
| 109 | lcd_write_command_ex(LCD_CNTL_ELECTRONIC_VOLUME, val, -1); |
| 110 | } |
| 111 | |
| 112 | void lcd_set_invert_display(bool yesno) |
| 113 | { |
| 114 | lcd_write_command(LCD_CNTL_REVERSE | (yesno?1:0)); |
| 115 | } |
| 116 | |
| 117 | /* turn the display upside down (call lcd_update() afterwards) */ |
| 118 | void lcd_set_flip(bool yesno) |
| 119 | { |
| 120 | if (yesno) |
| 121 | { |
| 122 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 1); |
| 123 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 0); |
| 124 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 0); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 125 | } |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 126 | else |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 127 | { |
| 128 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); |
| 129 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); |
| 130 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | |
| 134 | /* Rolls up the lcd display by the specified amount of lines. |
| 135 | * Lines that are rolled out over the top of the screen are |
| 136 | * rolled in from the bottom again. This is a hardware |
| 137 | * remapping only and all operations on the lcd are affected. |
| 138 | * -> |
| 139 | * @param int lines - The number of lines that are rolled. |
| 140 | * The value must be 0 <= pixels < LCD_HEIGHT. */ |
| 141 | void lcd_roll(int lines) |
| 142 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 143 | lines &= LCD_HEIGHT-1; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 144 | lcd_write_command_ex(LCD_CNTL_DISPLAY_START_LINE, lines, -1); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | #endif /* !SIMULATOR */ |
| 148 | |
| 149 | /* LCD init */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 150 | #ifdef SIMULATOR |
| 151 | |
| 152 | void lcd_init(void) |
| 153 | { |
| 154 | create_thread(scroll_thread, scroll_stack, |
| 155 | sizeof(scroll_stack), scroll_name); |
| 156 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 157 | #else |
| 158 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 159 | void lcd_init(void) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 160 | { |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 161 | /* GPO35 is the LCD A0 pin |
| 162 | GPO46 is LCD RESET */ |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 163 | or_l(0x00004008, &GPIO1_OUT); |
| 164 | or_l(0x00004008, &GPIO1_ENABLE); |
| 165 | or_l(0x00004008, &GPIO1_FUNCTION); |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 166 | |
| 167 | /* Reset LCD */ |
| 168 | sleep(1); |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 169 | and_l(~0x00004000, &GPIO1_OUT); |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 170 | sleep(1); |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 171 | or_l(0x00004000, &GPIO1_OUT); |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 172 | sleep(1); |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 173 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 174 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); /* Normal */ |
| 175 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); /* Reverse dir */ |
| 176 | lcd_write_command(LCD_CNTL_REVERSE | 0); /* Reverse OFF */ |
| 177 | lcd_write_command(LCD_CNTL_ALL_LIGHTING | 0); /* Normal */ |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 178 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 179 | lcd_write_command(LCD_CNTL_OFF_MODE | 1); /* OFF -> VCC on drivers */ |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 180 | lcd_write_command_ex(LCD_CNTL_VOLTAGE_SELECT, 3, -1); |
| 181 | lcd_write_command_ex(LCD_CNTL_ELECTRONIC_VOLUME, 0x1c, -1); |
| 182 | lcd_write_command_ex(LCD_CNTL_TEMP_GRADIENT_SELECT, 0, -1); |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 183 | |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 184 | lcd_write_command_ex(LCD_CNTL_LINE_INVERT_DRIVE, 0x10, -1); |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 185 | lcd_write_command(LCD_CNTL_NLINE_ON_OFF | 1); /* N-line ON */ |
| 186 | |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 187 | lcd_write_command_ex(LCD_CNTL_OSC_FREQUENCY, 3, -1); |
| 188 | lcd_write_command(LCD_CNTL_OSC_ON_OFF | 1); /* Oscillator ON */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 189 | |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 190 | lcd_write_command_ex(LCD_CNTL_POWER_CONTROL, 0x16, -1); |
| 191 | sleep(HZ/10); /* 100 ms pause */ |
| 192 | lcd_write_command_ex(LCD_CNTL_POWER_CONTROL, 0x17, -1); |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 193 | |
| 194 | lcd_write_command_ex(LCD_CNTL_DISPLAY_START_LINE, 0, -1); |
| 195 | lcd_write_command_ex(LCD_CNTL_GRAY_SCALE_PATTERN, 0x42, -1); |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 196 | lcd_write_command_ex(LCD_CNTL_DISPLAY_MODE, 0, -1); /* Greyscale mode */ |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 197 | lcd_write_command(LCD_CNTL_DATA_INPUT_DIR | 0); /* Column mode */ |
| 198 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 199 | lcd_clear_display(); |
| 200 | lcd_update(); |
Jens Arnold | 492424b | 2005-06-27 19:28:55 +0000 | [diff] [blame] | 201 | lcd_write_command(LCD_CNTL_ON_OFF | 1); /* LCD ON */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 202 | |
| 203 | create_thread(scroll_thread, scroll_stack, |
| 204 | sizeof(scroll_stack), scroll_name); |
| 205 | } |
| 206 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 207 | /*** update functions ***/ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 208 | |
| 209 | /* Performance function that works with an external buffer |
Jens Arnold | a1de081 | 2005-09-30 20:11:31 +0000 | [diff] [blame] | 210 | note that by and bheight are in 8-pixel units! */ |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 211 | void lcd_blit(const unsigned char* data, int x, int by, int width, |
| 212 | int bheight, int stride) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 213 | { |
Jens Arnold | 1a40e10 | 2005-09-30 20:10:27 +0000 | [diff] [blame] | 214 | const unsigned char *src, *src_end; |
| 215 | unsigned char *dst_u, *dst_l; |
Jens Arnold | bfe28d9 | 2005-11-09 23:24:33 +0000 | [diff] [blame] | 216 | static unsigned char upper[LCD_WIDTH] IBSS_ATTR; |
| 217 | static unsigned char lower[LCD_WIDTH] IBSS_ATTR; |
Jens Arnold | 1a40e10 | 2005-09-30 20:10:27 +0000 | [diff] [blame] | 218 | unsigned int byte; |
| 219 | |
| 220 | by *= 2; |
| 221 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 222 | while (bheight--) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 223 | { |
Jens Arnold | 1a40e10 | 2005-09-30 20:10:27 +0000 | [diff] [blame] | 224 | src = data; |
| 225 | src_end = data + width; |
| 226 | dst_u = upper; |
| 227 | dst_l = lower; |
| 228 | do |
| 229 | { |
| 230 | byte = *src++; |
| 231 | *dst_u++ = dibits[byte & 0x0F]; |
| 232 | byte >>= 4; |
| 233 | *dst_l++ = dibits[byte & 0x0F]; |
| 234 | } |
| 235 | while (src < src_end); |
| 236 | |
Jens Arnold | 2ef8a87 | 2005-07-16 02:09:22 +0000 | [diff] [blame] | 237 | lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 238 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 239 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
Jens Arnold | 1a40e10 | 2005-09-30 20:10:27 +0000 | [diff] [blame] | 240 | lcd_write_data(upper, width); |
| 241 | |
| 242 | lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); |
| 243 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); |
| 244 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
| 245 | lcd_write_data(lower, width); |
| 246 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 247 | data += stride; |
Jens Arnold | 1a40e10 | 2005-09-30 20:10:27 +0000 | [diff] [blame] | 248 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 249 | } |
| 250 | |
| 251 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 252 | /* Update the display. |
| 253 | This must be called after all other LCD functions that change the display. */ |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 254 | void lcd_update(void) ICODE_ATTR; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 255 | void lcd_update(void) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 256 | { |
| 257 | int y; |
| 258 | |
| 259 | /* Copy display bitmap to hardware */ |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 260 | for (y = 0; y < LCD_HEIGHT/4; y++) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 261 | { |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 262 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); |
| 263 | lcd_write_command_ex(LCD_CNTL_COLUMN, 0, -1); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 264 | |
| 265 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
| 266 | lcd_write_data (lcd_framebuffer[y], LCD_WIDTH); |
| 267 | } |
| 268 | } |
| 269 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 270 | /* Update a fraction of the display. */ |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 271 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 272 | void lcd_update_rect(int x, int y, int width, int height) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 273 | { |
| 274 | int ymax; |
| 275 | |
| 276 | /* The Y coordinates have to work on even 8 pixel rows */ |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 277 | ymax = (y + height-1) >> 2; |
| 278 | y >>= 2; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 279 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 280 | if(x + width > LCD_WIDTH) |
| 281 | width = LCD_WIDTH - x; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 282 | if (width <= 0) |
| 283 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 284 | if(ymax >= LCD_HEIGHT/4) |
| 285 | ymax = LCD_HEIGHT/4-1; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 286 | |
| 287 | /* Copy specified rectange bitmap to hardware */ |
| 288 | for (; y <= ymax; y++) |
| 289 | { |
Linus Nielsen Feltzing | f470204 | 2005-01-27 00:00:55 +0000 | [diff] [blame] | 290 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 291 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 292 | |
| 293 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 294 | lcd_write_data (&lcd_framebuffer[y][x], width); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 295 | } |
| 296 | } |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 297 | #endif /* !SIMULATOR */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 298 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 299 | /*** parameter handling ***/ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 300 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 301 | void lcd_set_drawmode(int mode) |
| 302 | { |
| 303 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
| 304 | } |
| 305 | |
| 306 | int lcd_get_drawmode(void) |
| 307 | { |
| 308 | return drawmode; |
| 309 | } |
| 310 | |
Jens Arnold | 5b2cba1 | 2005-11-16 21:09:23 +0000 | [diff] [blame] | 311 | void lcd_set_foreground(unsigned brightness) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 312 | { |
| 313 | fg_pattern = 0x55 * (~brightness & 3); |
| 314 | } |
| 315 | |
Jens Arnold | 5b2cba1 | 2005-11-16 21:09:23 +0000 | [diff] [blame] | 316 | unsigned lcd_get_foreground(void) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 317 | { |
| 318 | return ~fg_pattern & 3; |
| 319 | } |
| 320 | |
Jens Arnold | 5b2cba1 | 2005-11-16 21:09:23 +0000 | [diff] [blame] | 321 | void lcd_set_background(unsigned brightness) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 322 | { |
| 323 | bg_pattern = 0x55 * (~brightness & 3); |
| 324 | } |
| 325 | |
Jens Arnold | 5b2cba1 | 2005-11-16 21:09:23 +0000 | [diff] [blame] | 326 | unsigned lcd_get_background(void) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 327 | { |
| 328 | return ~bg_pattern & 3; |
| 329 | } |
| 330 | |
Jens Arnold | 5b2cba1 | 2005-11-16 21:09:23 +0000 | [diff] [blame] | 331 | void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) |
Jens Arnold | bf9f28b | 2005-07-14 18:11:36 +0000 | [diff] [blame] | 332 | { |
| 333 | lcd_set_drawmode(mode); |
| 334 | lcd_set_foreground(fg_brightness); |
| 335 | lcd_set_background(bg_brightness); |
| 336 | } |
| 337 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 338 | void lcd_setmargins(int x, int y) |
| 339 | { |
| 340 | xmargin = x; |
| 341 | ymargin = y; |
| 342 | } |
| 343 | |
| 344 | int lcd_getxmargin(void) |
| 345 | { |
| 346 | return xmargin; |
| 347 | } |
| 348 | |
| 349 | int lcd_getymargin(void) |
| 350 | { |
| 351 | return ymargin; |
| 352 | } |
| 353 | |
| 354 | void lcd_setfont(int newfont) |
| 355 | { |
| 356 | curfont = newfont; |
| 357 | } |
| 358 | |
| 359 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
| 360 | { |
Christian Gmeiner | c6ec0f4 | 2005-04-19 12:47:16 +0000 | [diff] [blame] | 361 | return font_getstringsize(str, w, h, curfont); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 362 | } |
| 363 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 364 | /*** low-level drawing functions ***/ |
| 365 | |
| 366 | static void setpixel(int x, int y) |
| 367 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 368 | unsigned char *data = &lcd_framebuffer[y>>2][x]; |
| 369 | unsigned mask = 3 << (2 * (y & 3)); |
| 370 | *data = (*data & ~mask) | (fg_pattern & mask); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 371 | } |
| 372 | |
| 373 | static void clearpixel(int x, int y) |
| 374 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 375 | unsigned char *data = &lcd_framebuffer[y>>2][x]; |
| 376 | unsigned mask = 3 << (2 * (y & 3)); |
| 377 | *data = (*data & ~mask) | (bg_pattern & mask); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 378 | } |
| 379 | |
| 380 | static void flippixel(int x, int y) |
| 381 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 382 | lcd_framebuffer[y>>2][x] ^= 3 << (2 * (y & 3)); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 383 | } |
| 384 | |
| 385 | static void nopixel(int x, int y) |
| 386 | { |
| 387 | (void)x; |
| 388 | (void)y; |
| 389 | } |
| 390 | |
Jens Arnold | 71bc504 | 2005-11-06 23:49:29 +0000 | [diff] [blame] | 391 | lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 392 | flippixel, nopixel, setpixel, setpixel, |
| 393 | nopixel, clearpixel, nopixel, clearpixel |
| 394 | }; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 395 | |
| 396 | /* 'mask' and 'bits' contain 2 bits per pixel */ |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 397 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 398 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 399 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 400 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 401 | *address ^= bits & mask; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 402 | } |
| 403 | |
| 404 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 405 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 406 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 407 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 408 | mask &= ~bits; |
| 409 | *address = (*address & ~mask) | (bg_pattern & mask); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 410 | } |
| 411 | |
| 412 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 413 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 414 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 415 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 416 | mask &= bits; |
| 417 | *address = (*address & ~mask) | (fg_pattern & mask); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 421 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 422 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 423 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 424 | *address = (*address & ~mask) | (bits & mask & fg_pattern) |
| 425 | | (~bits & mask & bg_pattern); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 426 | } |
| 427 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 428 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 429 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 430 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 431 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 432 | *address ^= ~bits & mask; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 433 | } |
| 434 | |
| 435 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 436 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 437 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 438 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 439 | mask &= bits; |
| 440 | *address = (*address & ~mask) | (bg_pattern & mask); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 441 | } |
| 442 | |
| 443 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 444 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 445 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 446 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 447 | mask &= ~bits; |
| 448 | *address = (*address & ~mask) | (fg_pattern & mask); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 449 | } |
| 450 | |
| 451 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 452 | ICODE_ATTR; |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 453 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 454 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 455 | *address = (*address & ~mask) | (~bits & mask & fg_pattern) |
| 456 | | (bits & mask & bg_pattern); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 457 | } |
| 458 | |
Jens Arnold | 71bc504 | 2005-11-06 23:49:29 +0000 | [diff] [blame] | 459 | lcd_blockfunc_type* const lcd_blockfuncs[8] = { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 460 | flipblock, bgblock, fgblock, solidblock, |
| 461 | flipinvblock, bginvblock, fginvblock, solidinvblock |
| 462 | }; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 463 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 464 | /*** drawing functions ***/ |
| 465 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 466 | /* Clear the whole display */ |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 467 | void lcd_clear_display(void) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 468 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 469 | unsigned bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; |
Jens Arnold | 9349412 | 2005-06-25 00:28:09 +0000 | [diff] [blame] | 470 | |
| 471 | memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 472 | scrolling_lines = 0; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 473 | } |
| 474 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 475 | /* Set a single pixel */ |
| 476 | void lcd_drawpixel(int x, int y) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 477 | { |
Jens Arnold | 7f8cc3f | 2005-06-29 21:33:36 +0000 | [diff] [blame] | 478 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 479 | lcd_pixelfuncs[drawmode](x, y); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 480 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 481 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 482 | /* Draw a line */ |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 483 | void lcd_drawline(int x1, int y1, int x2, int y2) |
| 484 | { |
| 485 | int numpixels; |
| 486 | int i; |
| 487 | int deltax, deltay; |
| 488 | int d, dinc1, dinc2; |
| 489 | int x, xinc1, xinc2; |
| 490 | int y, yinc1, yinc2; |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 491 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 492 | |
| 493 | deltax = abs(x2 - x1); |
| 494 | deltay = abs(y2 - y1); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 495 | xinc2 = 1; |
| 496 | yinc2 = 1; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 497 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 498 | if (deltax >= deltay) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 499 | { |
| 500 | numpixels = deltax; |
| 501 | d = 2 * deltay - deltax; |
| 502 | dinc1 = deltay * 2; |
| 503 | dinc2 = (deltay - deltax) * 2; |
| 504 | xinc1 = 1; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 505 | yinc1 = 0; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 506 | } |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 507 | else |
| 508 | { |
| 509 | numpixels = deltay; |
| 510 | d = 2 * deltax - deltay; |
| 511 | dinc1 = deltax * 2; |
| 512 | dinc2 = (deltax - deltay) * 2; |
| 513 | xinc1 = 0; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 514 | yinc1 = 1; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 515 | } |
| 516 | numpixels++; /* include endpoints */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 517 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 518 | if (x1 > x2) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 519 | { |
| 520 | xinc1 = -xinc1; |
| 521 | xinc2 = -xinc2; |
| 522 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 523 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 524 | if (y1 > y2) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 525 | { |
| 526 | yinc1 = -yinc1; |
| 527 | yinc2 = -yinc2; |
| 528 | } |
| 529 | |
| 530 | x = x1; |
| 531 | y = y1; |
| 532 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 533 | for (i = 0; i < numpixels; i++) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 534 | { |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 535 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) |
| 536 | pfunc(x, y); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 537 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 538 | if (d < 0) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 539 | { |
| 540 | d += dinc1; |
| 541 | x += xinc1; |
| 542 | y += yinc1; |
| 543 | } |
| 544 | else |
| 545 | { |
| 546 | d += dinc2; |
| 547 | x += xinc2; |
| 548 | y += yinc2; |
| 549 | } |
| 550 | } |
| 551 | } |
| 552 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 553 | /* Draw a horizontal line (optimised) */ |
| 554 | void lcd_hline(int x1, int x2, int y) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 555 | { |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 556 | int x; |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 557 | unsigned char *dst, *dst_end; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 558 | unsigned mask; |
Jens Arnold | 24a1f94 | 2005-06-24 23:06:06 +0000 | [diff] [blame] | 559 | lcd_blockfunc_type *bfunc; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 560 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 561 | /* direction flip */ |
| 562 | if (x2 < x1) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 563 | { |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 564 | x = x1; |
| 565 | x1 = x2; |
| 566 | x2 = x; |
| 567 | } |
| 568 | |
| 569 | /* nothing to draw? */ |
| 570 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) |
| 571 | return; |
| 572 | |
| 573 | /* clipping */ |
| 574 | if (x1 < 0) |
| 575 | x1 = 0; |
| 576 | if (x2 >= LCD_WIDTH) |
| 577 | x2 = LCD_WIDTH-1; |
| 578 | |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 579 | bfunc = lcd_blockfuncs[drawmode]; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 580 | dst = &lcd_framebuffer[y>>2][x1]; |
| 581 | mask = 3 << (2 * (y & 3)); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 582 | |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 583 | dst_end = dst + x2 - x1; |
| 584 | do |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 585 | bfunc(dst++, mask, 0xFFu); |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 586 | while (dst <= dst_end); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 587 | } |
| 588 | |
| 589 | /* Draw a vertical line (optimised) */ |
| 590 | void lcd_vline(int x, int y1, int y2) |
| 591 | { |
| 592 | int ny; |
| 593 | unsigned char *dst; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 594 | unsigned mask, mask_bottom; |
Jens Arnold | 24a1f94 | 2005-06-24 23:06:06 +0000 | [diff] [blame] | 595 | lcd_blockfunc_type *bfunc; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 596 | |
| 597 | /* direction flip */ |
| 598 | if (y2 < y1) |
| 599 | { |
| 600 | ny = y1; |
| 601 | y1 = y2; |
| 602 | y2 = ny; |
| 603 | } |
| 604 | |
| 605 | /* nothing to draw? */ |
| 606 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) |
| 607 | return; |
| 608 | |
| 609 | /* clipping */ |
| 610 | if (y1 < 0) |
| 611 | y1 = 0; |
| 612 | if (y2 >= LCD_HEIGHT) |
| 613 | y2 = LCD_HEIGHT-1; |
| 614 | |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 615 | bfunc = lcd_blockfuncs[drawmode]; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 616 | dst = &lcd_framebuffer[y1>>2][x]; |
| 617 | ny = y2 - (y1 & ~3); |
| 618 | mask = 0xFFu << (2 * (y1 & 3)); |
| 619 | mask_bottom = 0xFFu >> (2 * (~ny & 3)); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 620 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 621 | for (; ny >= 4; ny -= 4) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 622 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 623 | bfunc(dst, mask, 0xFFu); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 624 | dst += LCD_WIDTH; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 625 | mask = 0xFFu; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 626 | } |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 627 | mask &= mask_bottom; |
| 628 | bfunc(dst, mask, 0xFFu); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 629 | } |
| 630 | |
| 631 | /* Draw a rectangular box */ |
| 632 | void lcd_drawrect(int x, int y, int width, int height) |
| 633 | { |
| 634 | if ((width <= 0) || (height <= 0)) |
| 635 | return; |
| 636 | |
| 637 | int x2 = x + width - 1; |
| 638 | int y2 = y + height - 1; |
| 639 | |
| 640 | lcd_vline(x, y, y2); |
| 641 | lcd_vline(x2, y, y2); |
| 642 | lcd_hline(x, x2, y); |
| 643 | lcd_hline(x, x2, y2); |
| 644 | } |
| 645 | |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 646 | /* Fill a rectangular area */ |
| 647 | void lcd_fillrect(int x, int y, int width, int height) |
| 648 | { |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 649 | int ny; |
| 650 | unsigned char *dst, *dst_end; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 651 | unsigned mask, mask_bottom; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 652 | unsigned bits = fg_pattern; |
Jens Arnold | 24a1f94 | 2005-06-24 23:06:06 +0000 | [diff] [blame] | 653 | lcd_blockfunc_type *bfunc; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 654 | bool fillopt; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 655 | |
| 656 | /* nothing to draw? */ |
| 657 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 658 | || (x + width <= 0) || (y + height <= 0)) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 659 | return; |
| 660 | |
| 661 | /* clipping */ |
| 662 | if (x < 0) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 663 | { |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 664 | width += x; |
| 665 | x = 0; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 666 | } |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 667 | if (y < 0) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 668 | { |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 669 | height += y; |
| 670 | y = 0; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 671 | } |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 672 | if (x + width > LCD_WIDTH) |
| 673 | width = LCD_WIDTH - x; |
| 674 | if (y + height > LCD_HEIGHT) |
| 675 | height = LCD_HEIGHT - y; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 676 | |
| 677 | fillopt = (drawmode & DRMODE_INVERSEVID) ? |
| 678 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); |
| 679 | if (fillopt &&(drawmode & DRMODE_INVERSEVID)) |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 680 | bits = bg_pattern; |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 681 | bfunc = lcd_blockfuncs[drawmode]; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 682 | dst = &lcd_framebuffer[y>>2][x]; |
| 683 | ny = height - 1 + (y & 3); |
| 684 | mask = 0xFFu << (2 * (y & 3)); |
| 685 | mask_bottom = 0xFFu >> (2 * (~ny & 3)); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 686 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 687 | for (; ny >= 4; ny -= 4) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 688 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 689 | if (fillopt && (mask == 0xFFu)) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 690 | memset(dst, bits, width); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 691 | else |
| 692 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 693 | unsigned char *dst_row = dst; |
| 694 | |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 695 | dst_end = dst_row + width; |
| 696 | do |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 697 | bfunc(dst_row++, mask, 0xFFu); |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 698 | while (dst_row < dst_end); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 699 | } |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 700 | |
| 701 | dst += LCD_WIDTH; |
| 702 | mask = 0xFFu; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 703 | } |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 704 | mask &= mask_bottom; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 705 | |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 706 | if (fillopt && (mask == 0xFFu)) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 707 | memset(dst, bits, width); |
| 708 | else |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 709 | { |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 710 | dst_end = dst + width; |
| 711 | do |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 712 | bfunc(dst++, mask, 0xFFu); |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 713 | while (dst < dst_end); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 714 | } |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 715 | } |
| 716 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 717 | /* About Rockbox' internal monochrome bitmap format: |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 718 | * |
| 719 | * A bitmap contains one bit for every pixel that defines if that pixel is |
| 720 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB |
| 721 | * at top. |
| 722 | * The bytes are stored in row-major order, with byte 0 being top left, |
| 723 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows |
| 724 | * 0..7, the second row defines pixel row 8..15 etc. |
| 725 | * |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 726 | * This is similar to the internal lcd hw format. */ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 727 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 728 | /* Draw a partial monochrome bitmap */ |
| 729 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, |
| 730 | int stride, int x, int y, int width, int height) |
| 731 | ICODE_ATTR; |
| 732 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, |
| 733 | int stride, int x, int y, int width, int height) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 734 | { |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 735 | int shift, ny; |
| 736 | unsigned char *dst, *dst_end; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 737 | unsigned mask, mask_bottom; |
| 738 | lcd_blockfunc_type *bfunc; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 739 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 740 | /* nothing to draw? */ |
| 741 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
| 742 | || (x + width <= 0) || (y + height <= 0)) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 743 | return; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 744 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 745 | /* clipping */ |
| 746 | if (x < 0) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 747 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 748 | width += x; |
| 749 | src_x -= x; |
| 750 | x = 0; |
| 751 | } |
| 752 | if (y < 0) |
| 753 | { |
| 754 | height += y; |
| 755 | src_y -= y; |
| 756 | y = 0; |
| 757 | } |
| 758 | if (x + width > LCD_WIDTH) |
| 759 | width = LCD_WIDTH - x; |
| 760 | if (y + height > LCD_HEIGHT) |
| 761 | height = LCD_HEIGHT - y; |
| 762 | |
| 763 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
| 764 | src_y &= 7; |
| 765 | y -= src_y; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 766 | dst = &lcd_framebuffer[y>>2][x]; |
| 767 | shift = y & 3; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 768 | ny = height - 1 + shift + src_y; |
| 769 | |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 770 | bfunc = lcd_blockfuncs[drawmode]; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 771 | mask = 0xFFu << (shift + src_y); |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 772 | mask_bottom = 0xFFu >> (~ny & 7); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 773 | |
| 774 | if (shift == 0) |
| 775 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 776 | unsigned dmask1, dmask2, data; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 777 | |
| 778 | for (; ny >= 8; ny -= 8) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 779 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 780 | const unsigned char *src_row = src; |
| 781 | unsigned char *dst_row = dst + LCD_WIDTH; |
| 782 | |
| 783 | dmask1 = dibits[mask&0x0F]; |
| 784 | dmask2 = dibits[(mask>>4)&0x0F]; |
| 785 | dst_end = dst_row + width; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 786 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 787 | if (dmask1 != 0) |
| 788 | { |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 789 | do |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 790 | { |
| 791 | data = *src_row++; |
| 792 | bfunc(dst_row - LCD_WIDTH, dmask1, dibits[data&0x0F]); |
| 793 | bfunc(dst_row++, dmask2, dibits[(data>>4)&0x0F]); |
| 794 | } |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 795 | while (dst_row < dst_end); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 796 | } |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 797 | else |
| 798 | { |
| 799 | do |
| 800 | bfunc(dst_row++, dmask2, dibits[((*src_row++)>>4)&0x0F]); |
| 801 | while (dst_row < dst_end); |
| 802 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 803 | src += stride; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 804 | dst += 2*LCD_WIDTH; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 805 | mask = 0xFFu; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 806 | } |
Jens Arnold | a142d4d | 2005-06-30 18:42:24 +0000 | [diff] [blame] | 807 | mask &= mask_bottom; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 808 | dmask1 = dibits[mask&0x0F]; |
| 809 | dmask2 = dibits[(mask>>4)&0x0F]; |
| 810 | dst_end = dst + width; |
| 811 | |
| 812 | if (dmask1 != 0) |
| 813 | { |
| 814 | if (dmask2 != 0) |
| 815 | { |
| 816 | do |
| 817 | { |
| 818 | data = *src++; |
| 819 | bfunc(dst, dmask1, dibits[data&0x0F]); |
| 820 | bfunc((dst++) + LCD_WIDTH, dmask2, dibits[(data>>4)&0x0F]); |
| 821 | } |
| 822 | while (dst < dst_end); |
| 823 | } |
| 824 | else |
| 825 | { |
| 826 | do |
| 827 | bfunc(dst++, dmask1, dibits[(*src++)&0x0F]); |
| 828 | while (dst < dst_end); |
| 829 | } |
| 830 | } |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 831 | else |
| 832 | { |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 833 | do |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 834 | bfunc((dst++) + LCD_WIDTH, dmask2, dibits[((*src++)>>4)&0x0F]); |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 835 | while (dst < dst_end); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 836 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 837 | } |
| 838 | else |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 839 | { |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 840 | dst_end = dst + width; |
| 841 | do |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 842 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 843 | const unsigned char *src_col = src++; |
| 844 | unsigned char *dst_col = dst++; |
| 845 | unsigned mask_col = mask; |
| 846 | unsigned data = 0; |
| 847 | |
| 848 | for (y = ny; y >= 8; y -= 8) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 849 | { |
| 850 | data |= *src_col << shift; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 851 | |
| 852 | if (mask_col & 0xFFu) |
| 853 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 854 | if (mask_col & 0x0F) |
| 855 | bfunc(dst_col, dibits[mask_col&0x0F], dibits[data&0x0F]); |
| 856 | bfunc(dst_col + LCD_WIDTH, dibits[(mask_col>>4)&0x0F], |
| 857 | dibits[(data>>4)&0x0F]); |
| 858 | mask_col = 0xFFu; |
| 859 | } |
| 860 | else |
| 861 | mask_col >>= 8; |
| 862 | |
| 863 | src_col += stride; |
| 864 | dst_col += 2*LCD_WIDTH; |
| 865 | data >>= 8; |
| 866 | } |
| 867 | data |= *src_col << shift; |
| 868 | mask_bottom &= mask_col; |
| 869 | if (mask_bottom & 0x0F) |
| 870 | bfunc(dst_col, dibits[mask_bottom&0x0F], dibits[data&0x0F]); |
| 871 | if (mask_bottom & 0xF0) |
| 872 | bfunc(dst_col + LCD_WIDTH, dibits[(mask_bottom&0xF0)>>4], |
| 873 | dibits[(data>>4)&0x0F]); |
| 874 | } |
| 875 | while (dst < dst_end); |
| 876 | } |
| 877 | } |
| 878 | |
| 879 | /* Draw a full monochrome bitmap */ |
| 880 | void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) |
| 881 | { |
| 882 | lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); |
| 883 | } |
| 884 | |
| 885 | /* About Rockbox' internal native bitmap format: |
| 886 | * |
| 887 | * A bitmap contains two bits for every pixel. 00 = white, 01 = light grey, |
| 888 | * 10 = dark grey, 11 = black. Bits within a byte are arranged vertically, LSB |
| 889 | * at top. |
| 890 | * The bytes are stored in row-major order, with byte 0 being top left, |
| 891 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows |
| 892 | * 0..3, the second row defines pixel row 4..7 etc. |
| 893 | * |
| 894 | * This is the same as the internal lcd hw format. */ |
| 895 | |
| 896 | /* Draw a partial native bitmap */ |
| 897 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, |
| 898 | int stride, int x, int y, int width, int height) |
| 899 | ICODE_ATTR; |
| 900 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, |
| 901 | int stride, int x, int y, int width, int height) |
| 902 | { |
| 903 | int shift, ny; |
| 904 | unsigned char *dst, *dst_end; |
| 905 | unsigned mask, mask_bottom; |
| 906 | lcd_blockfunc_type *bfunc; |
| 907 | |
| 908 | /* nothing to draw? */ |
| 909 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
| 910 | || (x + width <= 0) || (y + height <= 0)) |
| 911 | return; |
| 912 | |
| 913 | /* clipping */ |
| 914 | if (x < 0) |
| 915 | { |
| 916 | width += x; |
| 917 | src_x -= x; |
| 918 | x = 0; |
| 919 | } |
| 920 | if (y < 0) |
| 921 | { |
| 922 | height += y; |
| 923 | src_y -= y; |
| 924 | y = 0; |
| 925 | } |
| 926 | if (x + width > LCD_WIDTH) |
| 927 | width = LCD_WIDTH - x; |
| 928 | if (y + height > LCD_HEIGHT) |
| 929 | height = LCD_HEIGHT - y; |
| 930 | |
| 931 | src += stride * (src_y >> 2) + src_x; /* move starting point */ |
| 932 | src_y &= 3; |
| 933 | y -= src_y; |
| 934 | dst = &lcd_framebuffer[y>>2][x]; |
| 935 | shift = y & 3; |
| 936 | ny = height - 1 + shift + src_y; |
| 937 | |
| 938 | bfunc = lcd_blockfuncs[drawmode]; |
| 939 | mask = 0xFFu << (2 * (shift + src_y)); |
| 940 | mask_bottom = 0xFFu >> (2 * (~ny & 3)); |
| 941 | |
| 942 | if (shift == 0) |
| 943 | { |
| 944 | for (; ny >= 4; ny -= 4) |
| 945 | { |
| 946 | if (mask == 0xFFu) |
| 947 | memcpy(dst, src, width); |
| 948 | else |
| 949 | { |
| 950 | const unsigned char *src_row = src; |
| 951 | unsigned char *dst_row = dst; |
| 952 | |
| 953 | dst_end = dst_row + width; |
| 954 | do |
| 955 | bfunc(dst_row++, mask, *src_row++); |
| 956 | while (dst_row < dst_end); |
| 957 | } |
| 958 | |
| 959 | src += stride; |
| 960 | dst += LCD_WIDTH; |
| 961 | mask = 0xFFu; |
| 962 | } |
| 963 | mask &= mask_bottom; |
| 964 | |
| 965 | if (mask == 0xFFu) |
| 966 | memcpy(dst, src, width); |
| 967 | else |
| 968 | { |
| 969 | dst_end = dst + width; |
| 970 | do |
| 971 | bfunc(dst++, mask, *src++); |
| 972 | while (dst < dst_end); |
| 973 | } |
| 974 | } |
| 975 | else |
| 976 | { |
| 977 | shift *= 2; |
| 978 | dst_end = dst + width; |
| 979 | do |
| 980 | { |
| 981 | const unsigned char *src_col = src++; |
| 982 | unsigned char *dst_col = dst++; |
| 983 | unsigned mask_col = mask; |
| 984 | unsigned data = 0; |
| 985 | |
| 986 | for (y = ny; y >= 4; y -= 4) |
| 987 | { |
| 988 | data |= *src_col << shift; |
| 989 | |
| 990 | if (mask_col & 0xFFu) |
| 991 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 992 | bfunc(dst_col, mask_col, data); |
| 993 | mask_col = 0xFFu; |
| 994 | } |
| 995 | else |
| 996 | mask_col >>= 8; |
| 997 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 998 | src_col += stride; |
| 999 | dst_col += LCD_WIDTH; |
| 1000 | data >>= 8; |
| 1001 | } |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1002 | data |= *src_col << shift; |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 1003 | bfunc(dst_col, mask_col & mask_bottom, data); |
| 1004 | } |
Jens Arnold | 3291ae6 | 2005-07-02 07:21:21 +0000 | [diff] [blame] | 1005 | while (dst < dst_end); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1006 | } |
| 1007 | } |
| 1008 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1009 | /* Draw a full native bitmap */ |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 1010 | void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) |
| 1011 | { |
| 1012 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); |
| 1013 | } |
| 1014 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1015 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
| 1016 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1017 | { |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1018 | unsigned short ch; |
| 1019 | unsigned short *ucs; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1020 | struct font* pf = font_get(curfont); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1021 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1022 | ucs = bidi_l2v(str, 1); |
Linus Nielsen Feltzing | 41a53d2 | 2005-08-08 19:23:28 +0000 | [diff] [blame] | 1023 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1024 | while ((ch = *ucs++) != 0 && x < LCD_WIDTH) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1025 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 1026 | int width; |
| 1027 | const unsigned char *bits; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1028 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1029 | /* check input range */ |
| 1030 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) |
| 1031 | ch = pf->defaultchar; |
| 1032 | ch -= pf->firstchar; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1033 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1034 | /* get proportional width and glyph bits */ |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1035 | width = font_get_width(pf,ch); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1036 | |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 1037 | if (ofs > width) |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1038 | { |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 1039 | ofs -= width; |
| 1040 | continue; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1041 | } |
Jens Arnold | 576908d | 2005-06-29 01:39:50 +0000 | [diff] [blame] | 1042 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1043 | bits = font_get_bits(pf, ch); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1044 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1045 | lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); |
Jens Arnold | 7e11acb | 2005-06-28 23:15:47 +0000 | [diff] [blame] | 1046 | |
| 1047 | x += width - ofs; |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1048 | ofs = 0; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1049 | } |
| 1050 | } |
| 1051 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1052 | /* put a string at a given pixel position */ |
| 1053 | void lcd_putsxy(int x, int y, const unsigned char *str) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1054 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1055 | lcd_putsxyofs(x, y, 0, str); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1056 | } |
| 1057 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1058 | /*** line oriented text output ***/ |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1059 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1060 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1061 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1062 | int xpos,ypos,w,h; |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1063 | int lastmode = drawmode; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1064 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1065 | /* make sure scrolling is turned off on the line we are updating */ |
| 1066 | scrolling_lines &= ~(1 << y); |
| 1067 | |
| 1068 | if(!str || !str[0]) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1069 | return; |
| 1070 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1071 | lcd_getstringsize(str, &w, &h); |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1072 | xpos = xmargin + x*w / utf8length((char *)str); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1073 | ypos = ymargin + y*h; |
| 1074 | lcd_putsxy(xpos, ypos, str); |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1075 | drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1076 | lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1077 | if (style & STYLE_INVERT) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1078 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1079 | drawmode = DRMODE_COMPLEMENT; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1080 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); |
| 1081 | } |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1082 | drawmode = lastmode; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1083 | } |
| 1084 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1085 | /* put a string at a given char position */ |
| 1086 | void lcd_puts(int x, int y, const unsigned char *str) |
| 1087 | { |
| 1088 | lcd_puts_style(x, y, str, STYLE_DEFAULT); |
| 1089 | } |
| 1090 | |
| 1091 | /*** scrolling ***/ |
| 1092 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1093 | /* Reverse the invert setting of the scrolling line (if any) at given char |
| 1094 | position. Setting will go into affect next time line scrolls. */ |
| 1095 | void lcd_invertscroll(int x, int y) |
| 1096 | { |
| 1097 | struct scrollinfo* s; |
| 1098 | |
| 1099 | (void)x; |
| 1100 | |
| 1101 | s = &scroll[y]; |
| 1102 | s->invert = !s->invert; |
| 1103 | } |
| 1104 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1105 | void lcd_stop_scroll(void) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1106 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1107 | scrolling_lines=0; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1108 | } |
| 1109 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1110 | void lcd_scroll_speed(int speed) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1111 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1112 | scroll_ticks = scroll_tick_table[speed]; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1113 | } |
| 1114 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1115 | void lcd_scroll_step(int step) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1116 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1117 | scroll_step = step; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1118 | } |
| 1119 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1120 | void lcd_scroll_delay(int ms) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1121 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1122 | scroll_delay = ms / (HZ / 10); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1123 | } |
| 1124 | |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1125 | void lcd_bidir_scroll(int percent) |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1126 | { |
Jens Arnold | 6a556c1 | 2005-06-23 16:53:54 +0000 | [diff] [blame] | 1127 | bidir_limit = percent; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1128 | } |
| 1129 | |
| 1130 | void lcd_puts_scroll(int x, int y, const unsigned char *string) |
| 1131 | { |
| 1132 | lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); |
| 1133 | } |
| 1134 | |
| 1135 | void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) |
| 1136 | { |
| 1137 | struct scrollinfo* s; |
| 1138 | int w, h; |
| 1139 | |
| 1140 | s = &scroll[y]; |
| 1141 | |
| 1142 | s->start_tick = current_tick + scroll_delay; |
| 1143 | s->invert = false; |
| 1144 | if (style & STYLE_INVERT) { |
| 1145 | s->invert = true; |
| 1146 | lcd_puts_style(x,y,string,STYLE_INVERT); |
| 1147 | } |
| 1148 | else |
| 1149 | lcd_puts(x,y,string); |
| 1150 | |
| 1151 | lcd_getstringsize(string, &w, &h); |
| 1152 | |
| 1153 | if (LCD_WIDTH - x * 8 - xmargin < w) { |
| 1154 | /* prepare scroll line */ |
| 1155 | char *end; |
| 1156 | |
| 1157 | memset(s->line, 0, sizeof s->line); |
Daniel Stenberg | 1a29cfb | 2005-11-25 00:10:12 +0000 | [diff] [blame] | 1158 | strcpy(s->line, (char *)string); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1159 | |
| 1160 | /* get width */ |
Daniel Stenberg | 1a29cfb | 2005-11-25 00:10:12 +0000 | [diff] [blame] | 1161 | s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1162 | |
| 1163 | /* scroll bidirectional or forward only depending on the string |
| 1164 | width */ |
| 1165 | if ( bidir_limit ) { |
| 1166 | s->bidir = s->width < (LCD_WIDTH - xmargin) * |
| 1167 | (100 + bidir_limit) / 100; |
| 1168 | } |
| 1169 | else |
| 1170 | s->bidir = false; |
| 1171 | |
| 1172 | if (!s->bidir) { /* add spaces if scrolling in the round */ |
| 1173 | strcat(s->line, " "); |
| 1174 | /* get new width incl. spaces */ |
Daniel Stenberg | 1a29cfb | 2005-11-25 00:10:12 +0000 | [diff] [blame] | 1175 | s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1176 | } |
| 1177 | |
| 1178 | end = strchr(s->line, '\0'); |
Daniel Stenberg | 1a29cfb | 2005-11-25 00:10:12 +0000 | [diff] [blame] | 1179 | strncpy(end, (char *)string, LCD_WIDTH/2); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1180 | |
Marcoen Hirschberg | b0fee17 | 2005-12-06 13:27:15 +0000 | [diff] [blame^] | 1181 | s->len = utf8length((char *)string); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1182 | s->offset = 0; |
| 1183 | s->startx = x; |
| 1184 | s->backward = false; |
| 1185 | scrolling_lines |= (1<<y); |
| 1186 | } |
| 1187 | else |
| 1188 | /* force a bit switch-off since it doesn't scroll */ |
| 1189 | scrolling_lines &= ~(1<<y); |
| 1190 | } |
| 1191 | |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1192 | static void scroll_thread(void) |
| 1193 | { |
| 1194 | struct font* pf; |
| 1195 | struct scrollinfo* s; |
| 1196 | int index; |
| 1197 | int xpos, ypos; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1198 | int lastmode; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1199 | |
| 1200 | /* initialize scroll struct array */ |
| 1201 | scrolling_lines = 0; |
| 1202 | |
| 1203 | while ( 1 ) { |
| 1204 | for ( index = 0; index < SCROLLABLE_LINES; index++ ) { |
| 1205 | /* really scroll? */ |
| 1206 | if ( !(scrolling_lines&(1<<index)) ) |
| 1207 | continue; |
| 1208 | |
| 1209 | s = &scroll[index]; |
| 1210 | |
| 1211 | /* check pause */ |
| 1212 | if (TIME_BEFORE(current_tick, s->start_tick)) |
| 1213 | continue; |
| 1214 | |
| 1215 | if (s->backward) |
| 1216 | s->offset -= scroll_step; |
| 1217 | else |
| 1218 | s->offset += scroll_step; |
| 1219 | |
| 1220 | pf = font_get(curfont); |
| 1221 | xpos = xmargin + s->startx * s->width / s->len; |
| 1222 | ypos = ymargin + index * pf->height; |
| 1223 | |
| 1224 | if (s->bidir) { /* scroll bidirectional */ |
| 1225 | if (s->offset <= 0) { |
| 1226 | /* at beginning of line */ |
| 1227 | s->offset = 0; |
| 1228 | s->backward = false; |
| 1229 | s->start_tick = current_tick + scroll_delay * 2; |
| 1230 | } |
| 1231 | if (s->offset >= s->width - (LCD_WIDTH - xpos)) { |
| 1232 | /* at end of line */ |
| 1233 | s->offset = s->width - (LCD_WIDTH - xpos); |
| 1234 | s->backward = true; |
| 1235 | s->start_tick = current_tick + scroll_delay * 2; |
| 1236 | } |
| 1237 | } |
| 1238 | else { |
Marcoen Hirschberg | 40d2209 | 2005-11-30 15:37:48 +0000 | [diff] [blame] | 1239 | /* scroll forward the whole time */ |
| 1240 | if (s->offset >= s->width) |
| 1241 | s->offset %= s->width; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1242 | } |
| 1243 | |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1244 | lastmode = drawmode; |
| 1245 | drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1246 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1247 | drawmode = DRMODE_SOLID; |
Daniel Stenberg | 1a29cfb | 2005-11-25 00:10:12 +0000 | [diff] [blame] | 1248 | lcd_putsxyofs(xpos, ypos, s->offset, (unsigned char *)s->line); |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1249 | if (s->invert) |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1250 | { |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1251 | drawmode = DRMODE_COMPLEMENT; |
Jens Arnold | 04daef1 | 2005-06-24 22:33:21 +0000 | [diff] [blame] | 1252 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); |
| 1253 | } |
Jens Arnold | f894a4c | 2005-07-06 22:58:02 +0000 | [diff] [blame] | 1254 | drawmode = lastmode; |
Linus Nielsen Feltzing | 2a83ce5 | 2004-10-26 06:54:03 +0000 | [diff] [blame] | 1255 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); |
| 1256 | } |
| 1257 | |
| 1258 | sleep(scroll_ticks); |
| 1259 | } |
| 1260 | } |
| 1261 | |