summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/backlight.c2
-rw-r--r--firmware/export/config-player.h2
-rw-r--r--firmware/export/id3.h1
-rw-r--r--firmware/id3.c3
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10_5gb.c114
-rw-r--r--firmware/target/coldfire/iaudio/lcd-remote-iaudio.c125
-rw-r--r--firmware/target/coldfire/iaudio/m3/button-m3.c2
-rw-r--r--firmware/target/coldfire/iaudio/m3/lcd-m3.c303
9 files changed, 152 insertions, 401 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 0a8ac2a8e3..1d60ea1016 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -513,6 +513,7 @@ target/coldfire/iaudio/m3/backlight-m3.c
513target/coldfire/iaudio/m3/button-m3.c 513target/coldfire/iaudio/m3/button-m3.c
514target/coldfire/iaudio/m3/fmradio_i2c-m3.c 514target/coldfire/iaudio/m3/fmradio_i2c-m3.c
515target/coldfire/iaudio/m3/lcd-m3.c 515target/coldfire/iaudio/m3/lcd-m3.c
516target/coldfire/iaudio/m3/lcd-as-m3.S
516target/coldfire/iaudio/m3/power-m3.c 517target/coldfire/iaudio/m3/power-m3.c
517target/coldfire/iaudio/m3/powermgmt-m3.c 518target/coldfire/iaudio/m3/powermgmt-m3.c
518target/coldfire/iaudio/m3/system-m3.c 519target/coldfire/iaudio/m3/system-m3.c
diff --git a/firmware/backlight.c b/firmware/backlight.c
index 0f66fbf574..4c4471ace6 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -468,7 +468,7 @@ void backlight_thread(void)
468 lcd_remote_off(); 468 lcd_remote_off();
469 break; 469 break;
470#elif defined HAVE_REMOTE_LCD_AS_MAIN 470#elif defined HAVE_REMOTE_LCD_AS_MAIN
471 case SYS_REMOTE_PLUGGED: 471 case SYS_REMOTE_PLUGGED:
472 lcd_on(); 472 lcd_on();
473 lcd_update(); 473 lcd_update();
474 break; 474 break;
diff --git a/firmware/export/config-player.h b/firmware/export/config-player.h
index b9e3035951..c69fe8cfcb 100644
--- a/firmware/export/config-player.h
+++ b/firmware/export/config-player.h
@@ -46,7 +46,7 @@
46 46
47/* Uncomment this if you want to enable ATA power-off control. 47/* Uncomment this if you want to enable ATA power-off control.
48 * Attention, some players crash when ATA power-off is enabled! */ 48 * Attention, some players crash when ATA power-off is enabled! */
49//#define HAVE_ATA_POWER_OFF 49#define HAVE_ATA_POWER_OFF
50 50
51/* Define this if you control ata power player style 51/* Define this if you control ata power player style
52 (with PB4, new player only) */ 52 (with PB4, new player only) */
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index bb3b6a6fe5..267f1b4afa 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -49,6 +49,7 @@ enum
49 AFMT_WAVPACK, /* WavPack */ 49 AFMT_WAVPACK, /* WavPack */
50 AFMT_ALAC, /* Apple Lossless Audio Codec */ 50 AFMT_ALAC, /* Apple Lossless Audio Codec */
51 AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */ 51 AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */
52 AFMT_MOD, /* MOD File Format */
52 AFMT_SHN, /* Shorten */ 53 AFMT_SHN, /* Shorten */
53 AFMT_SID, /* SID File Format */ 54 AFMT_SID, /* SID File Format */
54 AFMT_ADX, /* ADX File Format */ 55 AFMT_ADX, /* ADX File Format */
diff --git a/firmware/id3.c b/firmware/id3.c
index f594528910..87b4ce9d31 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -90,6 +90,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
90 [AFMT_AAC] = 90 [AFMT_AAC] =
91 AFMT_ENTRY("AAC", "aac", NULL, "mp4\0" ), 91 AFMT_ENTRY("AAC", "aac", NULL, "mp4\0" ),
92 /* Shorten */ 92 /* Shorten */
93 [AFMT_MOD] =
94 AFMT_ENTRY("MOD", "mod", NULL, "mod\0" ),
95 /* Shorten */
93 [AFMT_SHN] = 96 [AFMT_SHN] =
94 AFMT_ENTRY("SHN", "shorten", NULL, "shn\0" ), 97 AFMT_ENTRY("SHN", "shorten", NULL, "shn\0" ),
95 /* SID File Format */ 98 /* SID File Format */
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
index 5b022e09c5..669654f5c3 100644
--- a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
+++ b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
@@ -108,6 +108,7 @@ void lcd_init_device(void)
108{ 108{
109 CLCD_CLOCK_SRC |= 0xc0000000; /* Set LCD interface clock to PLL */ 109 CLCD_CLOCK_SRC |= 0xc0000000; /* Set LCD interface clock to PLL */
110 /* H10 LCD is initialised by the bootloader */ 110 /* H10 LCD is initialised by the bootloader */
111 lcd_write_reg(R_ENTRY_MODE, 0x1030); /* BGR =1, ID1 = 1, ID0 = 1 */
111} 112}
112 113
113/*** update functions ***/ 114/*** update functions ***/
@@ -275,88 +276,51 @@ void lcd_blit_yuv(unsigned char * const src[3],
275 276
276 277
277/* Update a fraction of the display. */ 278/* Update a fraction of the display. */
278void lcd_update_rect(int x0, int y0, int width, int height) 279void lcd_update_rect(int x, int y, int width, int height)
279{ 280{
280 int x1, y1; 281 const fb_data *addr;
281 int newx,newwidth; 282 int bytes_to_write;
282 unsigned long *addr; 283
284 if (x + width >= LCD_WIDTH)
285 width = LCD_WIDTH - x;
286 if (y + height >= LCD_HEIGHT)
287 height = LCD_HEIGHT - y;
288
289 if ((width <= 0) || (height <= 0))
290 return; /* Nothing left to do. 0 would hang the transfer. */
291
292 /* Ensure x and width are both even, so we can read
293 * 32-bit aligned data from the framebuffer */
294 width = (width + (x & 1) + 1) & ~1;
295 x &= ~1;
296
297 lcd_write_reg(R_VERT_RAM_ADDR_POS, (LCD_HEIGHT-1) << 8);
298 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, ((x + width - 1) << 8) | x);
299 lcd_write_reg(R_RAM_ADDR_SET, (y << 8) | x);
283 300
284 /* Ensure x and width are both even - so we can read 32-bit aligned
285 data from lcd_framebuffer */
286 newx=x0&~1;
287 newwidth=width&~1;
288 if (newx+newwidth < x0+width) { newwidth+=2; }
289 x0=newx; width=newwidth;
290
291 /* calculate the drawing region */
292 y1 = (y0 + height) - 1; /* max vert */
293 x1 = (x0 + width) - 1; /* max horiz */
294
295
296 /* swap max horiz < start horiz */
297 if (y1 < y0) {
298 int t;
299 t = y0;
300 y0 = y1;
301 y1 = t;
302 }
303
304 /* swap max vert < start vert */
305 if (x1 < x0) {
306 int t;
307 t = x0;
308 x0 = x1;
309 x1 = t;
310 }
311
312 /* max horiz << 8 | start horiz */
313 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (x1 << 8) | x0);
314
315 /* max vert << 8 | start vert */
316 lcd_write_reg(R_VERT_RAM_ADDR_POS, (y1 << 8) | y0);
317
318 /* start vert << 8 | start horiz */
319 lcd_write_reg(R_RAM_ADDR_SET, (y0 << 8) | x0);
320
321 /* start drawing */
322 lcd_send_cmd(R_WRITE_DATA_2_GRAM); 301 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
323 302
324 addr = (unsigned long*)&lcd_framebuffer[y0][x0]; 303 addr = &lcd_framebuffer[y][x];
325 304 bytes_to_write = width * height * sizeof(fb_data);
326 while (height > 0) { 305 /* must be <= 0x10000, but that's guaranteed on H10. */
327 int c, r;
328 int h, pixels_to_write;
329
330 pixels_to_write = (width * height) * 2;
331 h = height;
332
333 /* calculate how much we can do in one go */
334 if (pixels_to_write > 0x10000) {
335 h = (0x10000/2) / width;
336 pixels_to_write = (width * h) * 2;
337 }
338
339 LCD2_BLOCK_CTRL = 0x10000080;
340 LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
341 LCD2_BLOCK_CTRL = 0x34000000;
342 306
343 /* for each row */ 307 LCD2_BLOCK_CTRL = 0x10000080;
344 for (r = 0; r < h; r++) { 308 LCD2_BLOCK_CONFIG = 0xc0010000 | (bytes_to_write - 1);
345 /* for each column */ 309 LCD2_BLOCK_CTRL = 0x34000000;
346 for (c = 0; c < width; c += 2) { 310
347 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); 311 do
348 312 {
349 /* output 2 pixels */ 313 int w = width >> 1;
350 LCD2_BLOCK_DATA = *addr++; 314 do
351 } 315 {
352 addr += (LCD_WIDTH - width)/2; 316 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));
317 LCD2_BLOCK_DATA = *(unsigned long*)addr; /* output 2 pixels */
318 addr += 2;
353 } 319 }
354 320 while (--w > 0);
355 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY)); 321 addr += LCD_WIDTH - width;
356 LCD2_BLOCK_CONFIG = 0;
357
358 height -= h;
359 } 322 }
323 while (--height > 0);
360} 324}
361 325
362/* Update the display. 326/* Update the display.
diff --git a/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c b/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c
index 5a03dc6180..6565d3088d 100644
--- a/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c
+++ b/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c
@@ -64,83 +64,106 @@ bool remote_initialized = false;
64static inline void _write_byte(unsigned data) 64static inline void _write_byte(unsigned data)
65{ 65{
66 asm volatile ( 66 asm volatile (
67 "move.l (%[gpo0]), %%d0 \n" /* Get current state of data line */ 67 "move.w %%sr,%%d2 \n" /* Get current interrupt level */
68 "and.l %[dbit], %%d0 \n" 68 "move.w #0x2700,%%sr \n" /* Disable interrupts */
69
70 "move.l (%[gpo0]), %%d0 \n" /* Get current state of data port */
71 "move.l %%d0, %%d1 \n"
72 "and.l %[dbit], %%d1 \n" /* Check current state of data line */
69 "beq.s 1f \n" /* and set it as previous-state bit */ 73 "beq.s 1f \n" /* and set it as previous-state bit */
70 "bset #8, %[data] \n" 74 "bset #8, %[data] \n"
71 "1: \n" 75 "1: \n"
72 "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */ 76 "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */
73 "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */ 77 "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */
74 "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */ 78 "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */
75 "swap %[data] \n" /* Shift data to upper byte */ 79 "swap %[data] \n" /* Shift data to upper byte */
76 "lsl.l #8, %[data] \n" 80 "lsl.l #8, %[data] \n"
77 81
78 "move.l %[cbit], %%d1 \n" /* Prepare mask for flipping CLK */ 82 "eor.l %[cbit], %%d0 \n" /* precalculate opposite state of clock line */
79 "or.l %[dbit], %%d1 \n" /* and DATA at once */ 83
80
81 "lsl.l #1,%[data] \n" /* Shift out MSB */ 84 "lsl.l #1,%[data] \n" /* Shift out MSB */
82 "bcc.s 1f \n" 85 "bcc.s 1f \n"
83 "eor.l %%d1, (%[gpo0]) \n" /* 1: Flip both CLK and DATA */ 86 "eor.l %[dbit], %%d0 \n" /* 1: Flip data bit */
84 ".word 0x51fa \n" /* (trapf.w - shadow next insn) */
85 "1: \n" 87 "1: \n"
86 "eor.l %[cbit], (%[gpo0]) \n" /* else flip CLK only */ 88 "move.l %%d0, %%d1 \n"
87 "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK again */ 89 "move.l %%d0, (%[gpo0]) \n" /* Output new state and set CLK = 0*/
90 "eor.l %[cbit], %%d1 \n"
91 "nop \n"
88 92
89 "lsl.l #1,%[data] \n" /* ..unrolled.. */ 93 "lsl.l #1,%[data] \n" /* ..unrolled.. */
90 "bcc.s 1f \n" 94 "bcc.s 1f \n"
91 "eor.l %%d1, (%[gpo0]) \n" 95 "eor.l %[dbit], %%d0 \n"
92 ".word 0x51fa \n"
93 "1: \n" 96 "1: \n"
94 "eor.l %[cbit], (%[gpo0]) \n" 97 "move.l %%d1, (%[gpo0]) \n" /* set CLK = 1 (delayed) */
95 "eor.l %[cbit], (%[gpo0]) \n" 98 "move.l %%d0, %%d1 \n"
99 "move.l %%d0, (%[gpo0]) \n"
100 "eor.l %[cbit], %%d1 \n"
101 "nop \n"
96 102
97 "lsl.l #1,%[data] \n" 103 "lsl.l #1,%[data] \n" /* ..unrolled.. */
98 "bcc.s 1f \n" 104 "bcc.s 1f \n"
99 "eor.l %%d1, (%[gpo0]) \n" 105 "eor.l %[dbit], %%d0 \n"
100 ".word 0x51fa \n"
101 "1: \n" 106 "1: \n"
102 "eor.l %[cbit], (%[gpo0]) \n" 107 "move.l %%d1, (%[gpo0]) \n"
103 "eor.l %[cbit], (%[gpo0]) \n" 108 "move.l %%d0, %%d1 \n"
109 "move.l %%d0, (%[gpo0]) \n"
110 "eor.l %[cbit], %%d1 \n"
111 "nop \n"
104 112
105 "lsl.l #1,%[data] \n" 113 "lsl.l #1,%[data] \n" /* ..unrolled.. */
106 "bcc.s 1f \n" 114 "bcc.s 1f \n"
107 "eor.l %%d1, (%[gpo0]) \n" 115 "eor.l %[dbit], %%d0 \n"
108 ".word 0x51fa \n"
109 "1: \n" 116 "1: \n"
110 "eor.l %[cbit], (%[gpo0]) \n" 117 "move.l %%d1, (%[gpo0]) \n"
111 "eor.l %[cbit], (%[gpo0]) \n" 118 "move.l %%d0, %%d1 \n"
119 "move.l %%d0, (%[gpo0]) \n"
120 "eor.l %[cbit], %%d1 \n"
121 "nop \n"
112 122
113 "lsl.l #1,%[data] \n" 123 "lsl.l #1,%[data] \n" /* ..unrolled.. */
114 "bcc.s 1f \n" 124 "bcc.s 1f \n"
115 "eor.l %%d1, (%[gpo0]) \n" 125 "eor.l %[dbit], %%d0 \n"
116 ".word 0x51fa \n"
117 "1: \n" 126 "1: \n"
118 "eor.l %[cbit], (%[gpo0]) \n" 127 "move.l %%d1, (%[gpo0]) \n"
119 "eor.l %[cbit], (%[gpo0]) \n" 128 "move.l %%d0, %%d1 \n"
129 "move.l %%d0, (%[gpo0]) \n"
130 "eor.l %[cbit], %%d1 \n"
131 "nop \n"
120 132
121 "lsl.l #1,%[data] \n" 133 "lsl.l #1,%[data] \n" /* ..unrolled.. */
122 "bcc.s 1f \n" 134 "bcc.s 1f \n"
123 "eor.l %%d1, (%[gpo0]) \n" 135 "eor.l %[dbit], %%d0 \n"
124 ".word 0x51fa \n"
125 "1: \n" 136 "1: \n"
126 "eor.l %[cbit], (%[gpo0]) \n" 137 "move.l %%d1, (%[gpo0]) \n"
127 "eor.l %[cbit], (%[gpo0]) \n" 138 "move.l %%d0, %%d1 \n"
139 "move.l %%d0, (%[gpo0]) \n"
140 "eor.l %[cbit], %%d1 \n"
141 "nop \n"
128 142
129 "lsl.l #1,%[data] \n" 143 "lsl.l #1,%[data] \n" /* ..unrolled.. */
130 "bcc.s 1f \n" 144 "bcc.s 1f \n"
131 "eor.l %%d1, (%[gpo0]) \n" 145 "eor.l %[dbit], %%d0 \n"
132 ".word 0x51fa \n"
133 "1: \n" 146 "1: \n"
134 "eor.l %[cbit], (%[gpo0]) \n" 147 "move.l %%d1, (%[gpo0]) \n"
135 "eor.l %[cbit], (%[gpo0]) \n" 148 "move.l %%d0, %%d1 \n"
149 "move.l %%d0, (%[gpo0]) \n"
150 "eor.l %[cbit], %%d1 \n"
151 "nop \n"
136 152
137 "lsl.l #1,%[data] \n" 153 "lsl.l #1,%[data] \n" /* ..unrolled.. */
138 "bcc.s 1f \n" 154 "bcc.s 1f \n"
139 "eor.l %%d1, (%[gpo0]) \n" 155 "eor.l %[dbit], %%d0 \n"
140 ".word 0x51fa \n"
141 "1: \n" 156 "1: \n"
142 "eor.l %[cbit], (%[gpo0]) \n" 157 "move.l %%d1, (%[gpo0]) \n"
143 "eor.l %[cbit], (%[gpo0]) \n" 158 "move.l %%d0, %%d1 \n"
159 "move.l %%d0, (%[gpo0]) \n"
160 "eor.l %[cbit], %%d1 \n"
161 "nop \n"
162
163 "nop \n"
164 "move.l %%d1, (%[gpo0]) \n" /* set CLK = 1 (delayed) */
165
166 "move.w %%d2, %%sr \n" /* Restore interrupt level */
144 : /* outputs */ 167 : /* outputs */
145 [data]"+d"(data) 168 [data]"+d"(data)
146 : /* inputs */ 169 : /* inputs */
@@ -148,7 +171,7 @@ static inline void _write_byte(unsigned data)
148 [cbit]"d"(0x00004000), 171 [cbit]"d"(0x00004000),
149 [dbit]"d"(0x00002000) 172 [dbit]"d"(0x00002000)
150 : /* clobbers */ 173 : /* clobbers */
151 "d0", "d1" 174 "d0", "d1", "d2"
152 ); 175 );
153} 176}
154 177
@@ -157,7 +180,7 @@ static inline void _write_byte(unsigned data)
157static inline void _write_fast(unsigned data) 180static inline void _write_fast(unsigned data)
158{ 181{
159 asm volatile ( 182 asm volatile (
160 "move.w %%sr,%%d3 \n" /* Get current interrupt level */ 183 "move.w %%sr,%%d2 \n" /* Get current interrupt level */
161 "move.w #0x2700,%%sr \n" /* Disable interrupts */ 184 "move.w #0x2700,%%sr \n" /* Disable interrupts */
162 185
163 "move.l (%[gpo0]), %%d0 \n" /* Get current state of data port */ 186 "move.l (%[gpo0]), %%d0 \n" /* Get current state of data port */
@@ -239,7 +262,7 @@ static inline void _write_fast(unsigned data)
239 "move.l %%d1, (%[gpo0]) \n" 262 "move.l %%d1, (%[gpo0]) \n"
240 "move.l %%d0, (%[gpo0]) \n" 263 "move.l %%d0, (%[gpo0]) \n"
241 264
242 "move.w %%d3, %%sr \n" /* Restore interrupt level */ 265 "move.w %%d2, %%sr \n" /* Restore interrupt level */
243 : /* outputs */ 266 : /* outputs */
244 [data]"+d"(data) 267 [data]"+d"(data)
245 : /* inputs */ 268 : /* inputs */
@@ -247,7 +270,7 @@ static inline void _write_fast(unsigned data)
247 [cbit]"d"(0x00004000), 270 [cbit]"d"(0x00004000),
248 [dbit]"d"(0x00002000) 271 [dbit]"d"(0x00002000)
249 : /* clobbers */ 272 : /* clobbers */
250 "d0", "d1", "d2", "d3" 273 "d0", "d1", "d2"
251 ); 274 );
252} 275}
253 276
diff --git a/firmware/target/coldfire/iaudio/m3/button-m3.c b/firmware/target/coldfire/iaudio/m3/button-m3.c
index ecea221a4c..f5d4b59363 100644
--- a/firmware/target/coldfire/iaudio/m3/button-m3.c
+++ b/firmware/target/coldfire/iaudio/m3/button-m3.c
@@ -116,7 +116,7 @@ int button_read_device(void)
116 else 116 else
117 btn |= BUTTON_RC_VOL_DOWN; 117 btn |= BUTTON_RC_VOL_DOWN;
118 } 118 }
119 if ((GPIO_READ & 0x80000000) == 0) 119 if ((GPIO_READ & 0x80000000) == 0)
120 btn |= BUTTON_RC_PLAY; 120 btn |= BUTTON_RC_PLAY;
121 } 121 }
122 122
diff --git a/firmware/target/coldfire/iaudio/m3/lcd-m3.c b/firmware/target/coldfire/iaudio/m3/lcd-m3.c
index ae72832a82..4bc22380f5 100644
--- a/firmware/target/coldfire/iaudio/m3/lcd-m3.c
+++ b/firmware/target/coldfire/iaudio/m3/lcd-m3.c
@@ -61,263 +61,6 @@ static int cached_contrast = DEFAULT_CONTRAST_SETTING;
61bool initialized = false; 61bool initialized = false;
62 62
63 63
64/* Standard low-level byte writer. Requires CLK high on entry */
65static inline void _write_byte(unsigned data)
66{
67 asm volatile (
68 "move.l (%[gpo0]), %%d0 \n" /* Get current state of data line */
69 "and.l %[dbit], %%d0 \n"
70 "beq.s 1f \n" /* and set it as previous-state bit */
71 "bset #8, %[data] \n"
72 "1: \n"
73 "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */
74 "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */
75 "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */
76 "swap %[data] \n" /* Shift data to upper byte */
77 "lsl.l #8, %[data] \n"
78
79 "move.l %[cbit], %%d1 \n" /* Prepare mask for flipping CLK */
80 "or.l %[dbit], %%d1 \n" /* and DATA at once */
81
82 "lsl.l #1,%[data] \n" /* Shift out MSB */
83 "bcc.s 1f \n"
84 "eor.l %%d1, (%[gpo0]) \n" /* 1: Flip both CLK and DATA */
85 ".word 0x51fa \n" /* (trapf.w - shadow next insn) */
86 "1: \n"
87 "eor.l %[cbit], (%[gpo0]) \n" /* else flip CLK only */
88 "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK again */
89
90 "lsl.l #1,%[data] \n" /* ..unrolled.. */
91 "bcc.s 1f \n"
92 "eor.l %%d1, (%[gpo0]) \n"
93 ".word 0x51fa \n"
94 "1: \n"
95 "eor.l %[cbit], (%[gpo0]) \n"
96 "eor.l %[cbit], (%[gpo0]) \n"
97
98 "lsl.l #1,%[data] \n"
99 "bcc.s 1f \n"
100 "eor.l %%d1, (%[gpo0]) \n"
101 ".word 0x51fa \n"
102 "1: \n"
103 "eor.l %[cbit], (%[gpo0]) \n"
104 "eor.l %[cbit], (%[gpo0]) \n"
105
106 "lsl.l #1,%[data] \n"
107 "bcc.s 1f \n"
108 "eor.l %%d1, (%[gpo0]) \n"
109 ".word 0x51fa \n"
110 "1: \n"
111 "eor.l %[cbit], (%[gpo0]) \n"
112 "eor.l %[cbit], (%[gpo0]) \n"
113
114 "lsl.l #1,%[data] \n"
115 "bcc.s 1f \n"
116 "eor.l %%d1, (%[gpo0]) \n"
117 ".word 0x51fa \n"
118 "1: \n"
119 "eor.l %[cbit], (%[gpo0]) \n"
120 "eor.l %[cbit], (%[gpo0]) \n"
121
122 "lsl.l #1,%[data] \n"
123 "bcc.s 1f \n"
124 "eor.l %%d1, (%[gpo0]) \n"
125 ".word 0x51fa \n"
126 "1: \n"
127 "eor.l %[cbit], (%[gpo0]) \n"
128 "eor.l %[cbit], (%[gpo0]) \n"
129
130 "lsl.l #1,%[data] \n"
131 "bcc.s 1f \n"
132 "eor.l %%d1, (%[gpo0]) \n"
133 ".word 0x51fa \n"
134 "1: \n"
135 "eor.l %[cbit], (%[gpo0]) \n"
136 "eor.l %[cbit], (%[gpo0]) \n"
137
138 "lsl.l #1,%[data] \n"
139 "bcc.s 1f \n"
140 "eor.l %%d1, (%[gpo0]) \n"
141 ".word 0x51fa \n"
142 "1: \n"
143 "eor.l %[cbit], (%[gpo0]) \n"
144 "eor.l %[cbit], (%[gpo0]) \n"
145 : /* outputs */
146 [data]"+d"(data)
147 : /* inputs */
148 [gpo0]"a"(&GPIO_OUT),
149 [cbit]"d"(0x20000000),
150 [dbit]"d"(0x04000000)
151 : /* clobbers */
152 "d0", "d1"
153 );
154}
155
156/* Fast low-level byte writer. Don't use with high CPU clock.
157 * Requires CLK high on entry */
158static inline void _write_fast(unsigned data)
159{
160 asm volatile (
161 "move.w %%sr,%%d3 \n" /* Get current interrupt level */
162 "move.w #0x2700,%%sr \n" /* Disable interrupts */
163
164 "move.l (%[gpo0]), %%d0 \n" /* Get current state of data port */
165 "move.l %%d0, %%d1 \n"
166 "and.l %[dbit], %%d1 \n" /* Check current state of data line */
167 "beq.s 1f \n" /* and set it as previous-state bit */
168 "bset #8, %[data] \n"
169 "1: \n"
170 "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */
171 "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */
172 "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */
173 "swap %[data] \n" /* Shift data to upper byte */
174 "lsl.l #8, %[data] \n"
175
176 "move.l %%d0, %%d1 \n" /* precalculate opposite state of clock line */
177 "eor.l %[cbit], %%d1 \n"
178
179 "lsl.l #1,%[data] \n" /* Shift out MSB */
180 "bcc.s 1f \n"
181 "eor.l %[dbit], %%d0 \n" /* 1: Flip data bit */
182 "eor.l %[dbit], %%d1 \n" /* for both clock states */
183 "1: \n"
184 "move.l %%d1, (%[gpo0]) \n" /* Output new state and set CLK */
185 "move.l %%d0, (%[gpo0]) \n" /* reset CLK */
186
187 "lsl.l #1,%[data] \n" /* ..unrolled.. */
188 "bcc.s 1f \n"
189 "eor.l %[dbit], %%d0 \n"
190 "eor.l %[dbit], %%d1 \n"
191 "1: \n"
192 "move.l %%d1, (%[gpo0]) \n"
193 "move.l %%d0, (%[gpo0]) \n"
194
195 "lsl.l #1,%[data] \n"
196 "bcc.s 1f \n"
197 "eor.l %[dbit], %%d0 \n"
198 "eor.l %[dbit], %%d1 \n"
199 "1: \n"
200 "move.l %%d1, (%[gpo0]) \n"
201 "move.l %%d0, (%[gpo0]) \n"
202
203 "lsl.l #1,%[data] \n"
204 "bcc.s 1f \n"
205 "eor.l %[dbit], %%d0 \n"
206 "eor.l %[dbit], %%d1 \n"
207 "1: \n"
208 "move.l %%d1, (%[gpo0]) \n"
209 "move.l %%d0, (%[gpo0]) \n"
210
211 "lsl.l #1,%[data] \n"
212 "bcc.s 1f \n"
213 "eor.l %[dbit], %%d0 \n"
214 "eor.l %[dbit], %%d1 \n"
215 "1: \n"
216 "move.l %%d1, (%[gpo0]) \n"
217 "move.l %%d0, (%[gpo0]) \n"
218
219 "lsl.l #1,%[data] \n"
220 "bcc.s 1f \n"
221 "eor.l %[dbit], %%d0 \n"
222 "eor.l %[dbit], %%d1 \n"
223 "1: \n"
224 "move.l %%d1, (%[gpo0]) \n"
225 "move.l %%d0, (%[gpo0]) \n"
226
227 "lsl.l #1,%[data] \n"
228 "bcc.s 1f \n"
229 "eor.l %[dbit], %%d0 \n"
230 "eor.l %[dbit], %%d1 \n"
231 "1: \n"
232 "move.l %%d1, (%[gpo0]) \n"
233 "move.l %%d0, (%[gpo0]) \n"
234
235 "lsl.l #1,%[data] \n"
236 "bcc.s 1f \n"
237 "eor.l %[dbit], %%d0 \n"
238 "eor.l %[dbit], %%d1 \n"
239 "1: \n"
240 "move.l %%d1, (%[gpo0]) \n"
241 "move.l %%d0, (%[gpo0]) \n"
242
243 "move.w %%d3, %%sr \n" /* Restore interrupt level */
244 : /* outputs */
245 [data]"+d"(data)
246 : /* inputs */
247 [gpo0]"a"(&GPIO_OUT),
248 [cbit]"d"(0x20000000),
249 [dbit]"d"(0x04000000)
250 : /* clobbers */
251 "d0", "d1", "d2", "d3"
252 );
253}
254
255void lcd_write_command(int cmd)
256{
257 RS_LO;
258 CS_LO;
259 _write_byte(cmd);
260 CS_HI;
261}
262
263void lcd_write_command_e(int cmd, int data)
264{
265 RS_LO;
266 CS_LO;
267 _write_byte(cmd);
268 _write_byte(data);
269 CS_HI;
270}
271
272void lcd_write_data(const fb_data *p_words, int count)
273{
274 const unsigned char *p_bytes = (const unsigned char *)p_words;
275 const unsigned char *p_end = (const unsigned char *)(p_words + count);
276
277 RS_HI;
278 CS_LO;
279 if (cpu_frequency < 50000000)
280 {
281 while (p_bytes < p_end)
282 _write_fast(*p_bytes++);
283 }
284 else
285 {
286 while (p_bytes < p_end)
287 _write_byte(*p_bytes++);
288 }
289 CS_HI;
290}
291
292static void lcd_mono_data(const unsigned char *p_words, int count)
293{
294 unsigned data;
295 const unsigned char *p_bytes = p_words;
296 const unsigned char *p_end = p_words + count;
297
298 RS_HI;
299 CS_LO;
300 if (cpu_frequency < 50000000)
301 {
302 while (p_bytes < p_end)
303 {
304 data = *p_bytes++;
305 _write_fast(data);
306 _write_fast(data);
307 }
308 }
309 else
310 {
311 while (p_bytes < p_end)
312 {
313 data = *p_bytes++;
314 _write_byte(data);
315 _write_byte(data);
316 }
317 }
318 CS_HI;
319}
320
321int lcd_default_contrast(void) 64int lcd_default_contrast(void)
322{ 65{
323 return DEFAULT_CONTRAST_SETTING; 66 return DEFAULT_CONTRAST_SETTING;
@@ -457,6 +200,9 @@ void lcd_init_device(void)
457#endif 200#endif
458} 201}
459 202
203/* Helper function. */
204void lcd_mono_data(const unsigned char *data, int count);
205
460/* Performance function that works with an external buffer 206/* Performance function that works with an external buffer
461 note that by and bheight are in 8-pixel units! */ 207 note that by and bheight are in 8-pixel units! */
462void lcd_blit_mono(const unsigned char *data, int x, int by, int width, 208void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
@@ -477,20 +223,28 @@ void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
477 } 223 }
478} 224}
479 225
480/* TODO: implement grey blit function */ 226/* Helper function for lcd_grey_phase_blit(). */
227void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
481 228
482/* Performance function that works with an external buffer 229/* Performance function that works with an external buffer
483 note that by and bheight are in 8-pixel units! */ 230 note that by and bheight are in 8-pixel units! */
484void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, 231void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
485 int x, int by, int width, int bheight, int stride) 232 int x, int by, int width, int bheight, int stride)
486{ 233{
487 (void)values; 234 if (initialized)
488 (void)phases; 235 {
489 (void)x; 236 stride <<= 3; /* 8 pixels per block */
490 (void)by; 237 while (bheight--)
491 (void)width; 238 {
492 (void)bheight; 239 lcd_write_command(LCD_SET_PAGE | ((by > 5 ? by + 2 : by) & 0xf));
493 (void)stride; 240 lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0xf);
241
242 lcd_grey_data(values, phases, width);
243 values += stride;
244 phases += stride;
245 by++;
246 }
247 }
494} 248}
495 249
496/* Update the display. 250/* Update the display.
@@ -501,12 +255,13 @@ void lcd_update(void)
501 int y; 255 int y;
502 if (initialized) 256 if (initialized)
503 { 257 {
504 for(y = 0;y < LCD_FBHEIGHT;y++) { 258 for(y = 0;y < LCD_FBHEIGHT;y++)
259 {
505 /* Copy display bitmap to hardware. 260 /* Copy display bitmap to hardware.
506 The COM48-COM63 lines are not connected so we have to skip 261 The COM48-COM63 lines are not connected so we have to skip
507 them. Further, the column address doesn't wrap, so we 262 them. Further, the column address doesn't wrap, so we
508 have to update one page at a time. */ 263 have to update one page at a time. */
509 lcd_write_command(LCD_SET_PAGE | (y>5?y+2:y)); 264 lcd_write_command(LCD_SET_PAGE | (y > 5 ? y + 2 : y));
510 lcd_write_command_e(LCD_SET_COLUMN | 0, 0); 265 lcd_write_command_e(LCD_SET_COLUMN | 0, 0);
511 lcd_write_data(lcd_framebuffer[y], LCD_WIDTH); 266 lcd_write_data(lcd_framebuffer[y], LCD_WIDTH);
512 } 267 }
@@ -536,7 +291,7 @@ void lcd_update_rect(int x, int y, int width, int height)
536 COM48-COM63 are not connected, so we need to skip those */ 291 COM48-COM63 are not connected, so we need to skip those */
537 for (; y <= ymax; y++) 292 for (; y <= ymax; y++)
538 { 293 {
539 lcd_write_command(LCD_SET_PAGE | ((y > 5?y + 2:y) & 0xf)); 294 lcd_write_command(LCD_SET_PAGE | ((y > 5 ? y + 2 : y) & 0xf));
540 lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0xf); 295 lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0xf);
541 296
542 lcd_write_data(&lcd_framebuffer[y][x], width); 297 lcd_write_data(&lcd_framebuffer[y][x], width);
@@ -547,19 +302,23 @@ void lcd_update_rect(int x, int y, int width, int height)
547void lcd_set_invert_display(bool yesno) 302void lcd_set_invert_display(bool yesno)
548{ 303{
549 cached_invert = yesno; 304 cached_invert = yesno;
550 if(initialized) 305 if (initialized)
551 lcd_write_command(LCD_REVERSE | yesno); 306 lcd_write_command(LCD_REVERSE | yesno);
552} 307}
553 308
554void lcd_set_flip(bool yesno) 309void lcd_set_flip(bool yesno)
555{ 310{
556 cached_flip = yesno; 311 cached_flip = yesno;
557 if(initialized) { 312 if (initialized)
558 if(yesno) { 313 {
314 if(yesno)
315 {
559 lcd_write_command(LCD_SELECT_ADC | 0); 316 lcd_write_command(LCD_SELECT_ADC | 0);
560 lcd_write_command(LCD_SELECT_SHL | 0); 317 lcd_write_command(LCD_SELECT_SHL | 0);
561 lcd_write_command_e(LCD_SET_COM0, 16); 318 lcd_write_command_e(LCD_SET_COM0, 16);
562 } else { 319 }
320 else
321 {
563 lcd_write_command(LCD_SELECT_ADC | 1); 322 lcd_write_command(LCD_SELECT_ADC | 1);
564 lcd_write_command(LCD_SELECT_SHL | 8); 323 lcd_write_command(LCD_SELECT_SHL | 8);
565 lcd_write_command_e(LCD_SET_COM0, 0); 324 lcd_write_command_e(LCD_SET_COM0, 0);