summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/lcd.h11
-rw-r--r--firmware/target/arm/ipod/lcd-gray.c117
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-as-m5.S93
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-m5.c15
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-as-h100.S120
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-h100.c15
-rw-r--r--firmware/target/sh/archos/lcd-archos-bitmap.c19
-rw-r--r--firmware/target/sh/archos/lcd-as-archos-bitmap.S259
8 files changed, 545 insertions, 104 deletions
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index de03222441..60d9efaf92 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -95,15 +95,24 @@ extern void lcd_puts_scroll(int x, int y, const unsigned char* string);
95extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, 95extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
96 int style); 96 int style);
97 97
98#ifdef HAVE_LCD_BITMAP
99
98#if defined(HAVE_LCD_COLOR) 100#if defined(HAVE_LCD_COLOR)
99#define LCD_YUV_DITHER 0x1 101#define LCD_YUV_DITHER 0x1
100extern void lcd_yuv_set_options(unsigned options); 102extern void lcd_yuv_set_options(unsigned options);
101extern void lcd_yuv_blit(unsigned char * const src[3], 103extern void lcd_yuv_blit(unsigned char * const src[3],
102 int src_x, int src_y, int stride, 104 int src_x, int src_y, int stride,
103 int x, int y, int width, int height); 105 int x, int y, int width, int height);
106#else
107struct grey_data {
108 unsigned char phase; /* SH1 uses it signed (doesn't matter for high level) */
109 unsigned char value; /* 0..128 are allowed */
110} __attribute__((packed));
111extern void lcd_grey_data(const struct grey_data *data, int count); /* private */
112extern void lcd_grey_phase_blit(const struct grey_data *data, int bx, int by,
113 int bwidth, int bheight, int stride);
104#endif 114#endif
105 115
106#ifdef HAVE_LCD_BITMAP
107/* performance function */ 116/* performance function */
108extern void lcd_blit(const fb_data* data, int x, int by, int width, 117extern void lcd_blit(const fb_data* data, int x, int by, int width,
109 int bheight, int stride); 118 int bheight, int stride);
diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c
index 65fa2a779e..c7f4074c0b 100644
--- a/firmware/target/arm/ipod/lcd-gray.c
+++ b/firmware/target/arm/ipod/lcd-gray.c
@@ -299,6 +299,123 @@ void lcd_blit(const unsigned char* data, int bx, int y, int bwidth,
299 } 299 }
300} 300}
301 301
302/* Performance function that works with an external buffer
303 note that bx and bwidth are in 8-pixel units! */
304void lcd_grey_phase_blit(const struct grey_data *data, int bx, int y,
305 int bwidth, int height, int stride)
306{
307 const struct grey_data *addr;
308 int width;
309
310 while (height--) {
311 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx);
312 lcd_prepare_cmd(R_RAM_DATA);
313
314 addr = data;
315 width = bwidth;
316 asm volatile (
317 "10: \n"
318 "ldmia %[addr]!, {r0-r3} \n" /* r0 = v1p1v0p0 ... */
319#ifdef IPOD_MINI2G
320 "mov r5, #0x7600 \n"
321#else
322 "mov r5, #0 \n"
323#endif
324
325 "and r4, r0, %[mask] \n" /* r4 = --p1--p0 */
326 "and r0, %[mask], r0, lsr #8 \n" /* r0 = --v1--v0 */
327
328 "tst r4, #0x80 \n"
329 "orreq r5, r5, #0xc0 \n"
330 "tst r4, #0x800000 \n"
331 "orreq r5, r5, #0x30 \n"
332 "bic r4, r4, %[clbt] \n"
333
334 "add r4, r0, r4 \n" /* p0 += v0; p1 += v1; */
335 "strb r4, [%[addr], #-16] \n"
336 "mov r4, r4, lsr #16 \n"
337 "strb r4, [%[addr], #-14] \n"
338
339 "and r4, r1, %[mask] \n"
340 "and r1, %[mask], r1, lsr #8 \n"
341
342 "tst r4, #0x80 \n"
343 "orreq r5, r5, #0x0c \n"
344 "tst r4, #0x800000 \n"
345 "orreq r5, r5, #0x03 \n"
346 "bic r4, r4, %[clbt] \n"
347
348 "add r4, r1, r4 \n"
349 "strb r4, [%[addr], #-12] \n"
350 "mov r4, r4, lsr #16 \n"
351 "strb r4, [%[addr], #-10] \n"
352
353#ifdef IPOD_MINI2G
354 "mov r5, r5, lsl #8 \n"
355#else
356 "1: \n"
357 "ldr r4, [%[lcdb]] \n"
358 "tst r4, #0x8000 \n"
359 "bne 1b \n"
360
361 "str r5, [%[lcdb], #0x10] \n"
362 "mov r5, #0 \n"
363#endif
364
365 "and r4, r2, %[mask] \n"
366 "and r2, %[mask], r2, lsr #8 \n"
367
368 "tst r4, #0x80 \n"
369 "orreq r5, r5, #0xc0 \n"
370 "tst r4, #0x800000 \n"
371 "orreq r5, r5, #0x30 \n"
372 "bic r4, r4, %[clbt] \n"
373
374 "add r4, r2, r4 \n"
375 "strb r4, [%[addr], #-8] \n"
376 "mov r4, r4, lsr #16 \n"
377 "strb r4, [%[addr], #-6] \n"
378
379 "and r4, r3, %[mask] \n"
380 "and r3, %[mask], r3, lsr #8 \n"
381
382 "tst r4, #0x80 \n"
383 "orreq r5, r5, #0x0c \n"
384 "tst r4, #0x800000 \n"
385 "orreq r5, r5, #0x03 \n"
386 "bic r4, r4, %[clbt] \n"
387
388 "add r4, r3, r4 \n"
389 "strb r4, [%[addr], #-4] \n"
390 "mov r4, r4, lsr #16 \n"
391 "strb r4, [%[addr], #-2] \n"
392
393 "1: \n"
394 "ldr r4, [%[lcdb]] \n"
395 "tst r4, #0x8000 \n"
396 "bne 1b \n"
397#ifdef IPOD_MINI2G
398 "str r5, [%[lcdb], #0x08] \n"
399#else
400 "str r5, [%[lcdb], #0x10] \n"
401#endif
402
403 "subs %[wdth], %[wdth], #1 \n"
404 "bne 10b \n"
405 : /* outputs */
406 [addr]"+r"(addr),
407 [wdth]"+r"(width)
408 : /* inputs */
409 [mask]"r"(0x00ff00ff),
410 [clbt]"r"(0x00800080),
411 [lcdb]"r"(LCD1_BASE)
412 : /* clobbers */
413 "r0", "r1", "r2", "r3", "r4", "r5"
414 );
415 data += stride;
416 }
417}
418
302void lcd_update_rect(int x, int y, int width, int height) 419void lcd_update_rect(int x, int y, int width, int height)
303{ 420{
304 int xmax, ymax; 421 int xmax, ymax;
diff --git a/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S b/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S
index 4a88dc92b0..7e89815ec8 100644
--- a/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S
+++ b/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S
@@ -41,18 +41,18 @@ lcd_write_command:
41lcd_write_command_ex: 41lcd_write_command_ex:
42 lea.l 0xf0008000, %a0 42 lea.l 0xf0008000, %a0
43 43
44 move.l (4, %sp), %d0 /* Command */ 44 move.l (4, %sp), %d0 /* Command */
45 move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */ 45 move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */
46 46
47 move.l (8, %sp), %d0 /* Data */ 47 move.l (8, %sp), %d0 /* Data */
48 cmp.l #-1, %d0 /* -1? */ 48 cmp.l #-1, %d0 /* -1? */
49 beq.b .last 49 beq.b .last
50 move.w %d0, (%a0) /* Write to LCD */ 50 move.w %d0, (%a0) /* Write to LCD */
51 51
52 move.l (12, %sp), %d0 /* Data */ 52 move.l (12, %sp), %d0 /* Data */
53 cmp.l #-1, %d0 /* -1? */ 53 cmp.l #-1, %d0 /* -1? */
54 beq.b .last 54 beq.b .last
55 move.w %d0, (%a0) /* Write to LCD */ 55 move.w %d0, (%a0) /* Write to LCD */
56 56
57.last: 57.last:
58 rts 58 rts
@@ -65,19 +65,80 @@ lcd_write_command_ex:
65 .type lcd_write_data,@function 65 .type lcd_write_data,@function
66 66
67lcd_write_data: 67lcd_write_data:
68 move.l (4,%sp), %a0 /* Data pointer */ 68 movem.l (4, %sp), %a0-%a1 /* Data pointer */
69 move.l (8,%sp), %d0 /* Length */ 69 move.l %a1, %d0 /* Length */
70
71 lea 0xf0008002, %a1 70 lea 0xf0008002, %a1
71
72.loop: 72.loop:
73 /* When running in IRAM, this loop takes 10 cycles plus the LCD write. 73 /* When running in IRAM, this loop takes 10 cycles plus the LCD write.
74 The 10 cycles are necessary to follow the LCD timing specs 74 The 10 cycles are necessary to follow the LCD timing specs
75 at 140MHz */ 75 at 140MHz */
76 nop /* 3(0/0) */ 76 nop /* 3(0/0) */
77 move.b (%a0)+, %d1 /* 3(1/0) */ 77 move.b (%a0)+, %d1 /* 3(1/0) */
78 move.w %d1, (%a1) /* 1(0/1) */ 78 move.w %d1, (%a1) /* 1(0/1) */
79 subq.l #1, %d0 /* 1(0/0) */ 79 subq.l #1, %d0 /* 1(0/0) */
80 bne .loop /* 2(0/0) */ 80 bne .loop /* 2(0/0) */
81 rts 81 rts
82.wd_end: 82.wd_end:
83 .size lcd_write_data,.wd_end-lcd_write_data 83 .size lcd_write_data,.wd_end-lcd_write_data
84
85
86 .align 2
87 .global lcd_grey_data
88 .type lcd_grey_data,@function
89
90lcd_grey_data:
91 lea.l (-4*4, %sp), %sp
92 movem.l %d2-%d5, (%sp)
93 movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */
94 move.l %a1, %d0 /* Length */
95 lea 0xf0008002, %a1 /* LCD data port */
96 move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */
97
98.greyloop:
99 movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */
100 /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */
101 move.l %d2, %d3 /* copy mask */
102 and.l %d4, %d3 /* %d3 = p0--p1-- */
103 eor.l %d3, %d4 /* %d4 = --v0--v1 */
104 lsr.l #8, %d3 /* %d3 = --p0--p1 */
105
106 bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
107 seq.b %d1 /* %d1 = ........................00000000 */
108 lsl.l #2, %d1 /* %d1 = ......................00000000.. */
109 bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
110 seq.b %d1 /* %d1 = ......................0011111111 */
111 lsl.l #2, %d1 /* %d1 = ....................0011111111.. */
112
113 add.l %d4, %d3 /* p0 += v0; p1 += v1; */
114 move.b %d3, (2, %a0) /* store p1 */
115 swap %d3
116 move.b %d3, (%a0) /* store p0 */
117
118 move.l %d2, %d3 /* copy mask */
119 and.l %d5, %d3 /* %d3 = p2--p3-- */
120 eor.l %d3, %d5 /* %d5 = --v2--v3 */
121 lsr.l #8, %d3 /* %d3 = --p2--p3 */
122
123 bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
124 seq.b %d1 /* %d1 = ....................001122222222 */
125 lsl.l #2, %d1 /* %d1 = ..................001122222222.. */
126 bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
127 seq.b %d1 /* %d1 = ..................00112233333333 */
128 lsr.l #6, %d1 /* %d1 = ........................00112233 */
129
130 add.l %d5, %d3 /* p2 += v2; p3 += v3; */
131 move.b %d3, (6, %a0) /* store p3 */
132 swap %d3
133 move.b %d3, (4, %a0) /* store p2 */
134
135 move.w %d1, (%a1) /* write pixel block */
136 addq.l #8, %a0 /* advance address pointer */
137 subq.l #1, %d0 /* any blocks left? */
138 bne.b .greyloop
139
140 movem.l (%sp), %d2-%d5
141 lea.l (4*4, %sp), %sp
142 rts
143.gd_end:
144 .size lcd_grey_data,.gd_end-lcd_grey_data
diff --git a/firmware/target/coldfire/iaudio/m5/lcd-m5.c b/firmware/target/coldfire/iaudio/m5/lcd-m5.c
index 2af46b3145..4f963795c7 100644
--- a/firmware/target/coldfire/iaudio/m5/lcd-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/lcd-m5.c
@@ -171,6 +171,21 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
171 } 171 }
172} 172}
173 173
174/* Performance function that works with an external buffer
175 note that by and bheight are in 4-pixel units! */
176void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
177 int width, int bheight, int stride)
178{
179 stride <<= 2; /* 4 pixels per block */
180 while (bheight--)
181 {
182 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1);
183 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
184 lcd_write_command(LCD_CNTL_DATA_WRITE);
185 lcd_grey_data(data, width);
186 data += stride;
187 }
188}
174 189
175/* Update the display. 190/* Update the display.
176 This must be called after all other LCD functions that change the display. */ 191 This must be called after all other LCD functions that change the display. */
diff --git a/firmware/target/coldfire/iriver/h100/lcd-as-h100.S b/firmware/target/coldfire/iriver/h100/lcd-as-h100.S
index c7509871fc..df410fa379 100644
--- a/firmware/target/coldfire/iriver/h100/lcd-as-h100.S
+++ b/firmware/target/coldfire/iriver/h100/lcd-as-h100.S
@@ -28,11 +28,10 @@
28 .type lcd_write_command,@function 28 .type lcd_write_command,@function
29 29
30lcd_write_command: 30lcd_write_command:
31 move.l (4,%sp),%d0 31 move.l #~8, %d1
32 lea MBAR2,%a1 32 and.l %d1, (MBAR2+0xb4)
33 move.l #~8,%d1 33 move.l (4, %sp), %d0
34 and.l %d1,(0xb4,%a1) 34 move.w %d0, 0xf0000000
35 move.w %d0,0xf0000000
36 rts 35 rts
37.wc_end: 36.wc_end:
38 .size lcd_write_command,.wc_end-lcd_write_command 37 .size lcd_write_command,.wc_end-lcd_write_command
@@ -43,26 +42,27 @@ lcd_write_command:
43 .type lcd_write_command_ex,@function 42 .type lcd_write_command_ex,@function
44 43
45lcd_write_command_ex: 44lcd_write_command_ex:
46 lea MBAR2,%a1 45 lea.l 0xf0000000, %a0
46 lea.l MBAR2+0xb4, %a1
47 47
48 move.l (4,%sp),%d0 /* Command */ 48 move.l #~8, %d1 /* Set A0 = 0 */
49 and.l %d1, (%a1)
49 50
50 move.l #~8,%d1 /* Set A0 = 0 */ 51 move.l (4, %sp), %d0 /* Command */
51 and.l %d1,(0xb4,%a1) 52 move.w %d0, (%a0) /* Write to LCD */
52 move.w %d0,0xf0000000 /* Write to LCD */
53 53
54 not.l %d1 /* Set A0 = 1 */ 54 not.l %d1 /* Set A0 = 1 */
55 or.l %d1,(0xb4,%a1) 55 or.l %d1, (%a1)
56 56
57 move.l (8,%sp),%d0 /* Data */ 57 move.l (8, %sp), %d0 /* Data */
58 cmp.l #0xffffffff,%d0 /* -1? */ 58 cmp.l #-1, %d0 /* -1? */
59 beq.b .last 59 beq.b .last
60 move.w %d0,0xf0000000 /* Write to LCD */ 60 move.w %d0, (%a0) /* Write to LCD */
61 61
62 move.l (12,%sp),%d0 /* Data */ 62 move.l (12, %sp), %d0 /* Data */
63 cmp.l #0xffffffff,%d0 /* -1? */ 63 cmp.l #-1, %d0 /* -1? */
64 beq.b .last 64 beq.b .last
65 move.w %d0,0xf0000000 /* Write to LCD */ 65 move.w %d0, (%a0) /* Write to LCD */
66 66
67.last: 67.last:
68 rts 68 rts
@@ -75,22 +75,84 @@ lcd_write_command_ex:
75 .type lcd_write_data,@function 75 .type lcd_write_data,@function
76 76
77lcd_write_data: 77lcd_write_data:
78 move.l (4,%sp),%a0 /* Data pointer */ 78 movem.l (4, %sp), %a0-%a1 /* Data pointer */
79 move.l (8,%sp),%d0 /* Length */ 79 move.l %a1, %d0 /* Length */
80 lea MBAR2,%a1 80 moveq #8, %d1
81 moveq #8,%d1 81 or.l %d1, (MBAR2+0xb4)
82 or.l %d1,(0xb4,%a1) 82 lea.l 0xf0000000, %a1
83 83
84 lea 0xf0000000,%a1
85.loop: 84.loop:
86 /* When running in IRAM, this loop takes 10 cycles plus the LCD write. 85 /* When running in IRAM, this loop takes 10 cycles plus the LCD write.
87 The 10 cycles are necessary to follow the LCD timing specs 86 The 10 cycles are necessary to follow the LCD timing specs
88 at 140MHz */ 87 at 140MHz */
89 nop /* 3(0/0) */ 88 nop /* 3(0/0) */
90 move.b (%a0)+,%d1 /* 3(1/0) */ 89 move.b (%a0)+, %d1 /* 3(1/0) */
91 move.w %d1,(%a1) /* 1(0/1) */ 90 move.w %d1, (%a1) /* 1(0/1) */
92 subq.l #1,%d0 /* 1(0/0) */ 91 subq.l #1, %d0 /* 1(0/0) */
93 bne .loop /* 2(0/0) */ 92 bne .loop /* 2(0/0) */
94 rts 93 rts
95.wd_end: 94.wd_end:
96 .size lcd_write_data,.wd_end-lcd_write_data 95 .size lcd_write_data,.wd_end-lcd_write_data
96
97
98 .align 2
99 .global lcd_grey_data
100 .type lcd_grey_data,@function
101
102lcd_grey_data:
103 lea.l (-4*4, %sp), %sp
104 movem.l %d2-%d5, (%sp)
105 movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */
106 move.l %a1, %d0 /* Length */
107 moveq #8, %d1
108 or.l %d1, (MBAR2+0xb4) /* A0 = 1 (data) */
109 lea 0xf0000000, %a1 /* LCD data port */
110 move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */
111
112.greyloop:
113 movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */
114 /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */
115 move.l %d2, %d3 /* copy mask */
116 and.l %d4, %d3 /* %d3 = p0--p1-- */
117 eor.l %d3, %d4 /* %d4 = --v0--v1 */
118 lsr.l #8, %d3 /* %d3 = --p0--p1 */
119
120 bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
121 seq.b %d1 /* %d1 = ........................00000000 */
122 lsl.l #2, %d1 /* %d1 = ......................00000000.. */
123 bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
124 seq.b %d1 /* %d1 = ......................0011111111 */
125 lsl.l #2, %d1 /* %d1 = ....................0011111111.. */
126
127 add.l %d4, %d3 /* p0 += v0; p1 += v1; */
128 move.b %d3, (2, %a0) /* store p1 */
129 swap %d3
130 move.b %d3, (%a0) /* store p0 */
131
132 move.l %d2, %d3 /* copy mask */
133 and.l %d5, %d3 /* %d3 = p2--p3-- */
134 eor.l %d3, %d5 /* %d5 = --v2--v3 */
135 lsr.l #8, %d3 /* %d3 = --p2--p3 */
136
137 bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
138 seq.b %d1 /* %d1 = ....................001122222222 */
139 lsl.l #2, %d1 /* %d1 = ..................001122222222.. */
140 bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
141 seq.b %d1 /* %d1 = ..................00112233333333 */
142 lsr.l #6, %d1 /* %d1 = ........................00112233 */
143
144 add.l %d5, %d3 /* p2 += v2; p3 += v3; */
145 move.b %d3, (6, %a0) /* store p3 */
146 swap %d3
147 move.b %d3, (4, %a0) /* store p2 */
148
149 move.w %d1, (%a1) /* write pixel block */
150 addq.l #8, %a0 /* advance address pointer */
151 subq.l #1, %d0 /* any blocks left? */
152 bne.b .greyloop
153
154 movem.l (%sp), %d2-%d5
155 lea.l (4*4, %sp), %sp
156 rts
157.gd_end:
158 .size lcd_grey_data,.gd_end-lcd_grey_data
diff --git a/firmware/target/coldfire/iriver/h100/lcd-h100.c b/firmware/target/coldfire/iriver/h100/lcd-h100.c
index a721273384..c17de952c3 100644
--- a/firmware/target/coldfire/iriver/h100/lcd-h100.c
+++ b/firmware/target/coldfire/iriver/h100/lcd-h100.c
@@ -180,6 +180,21 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
180 } 180 }
181} 181}
182 182
183/* Performance function that works with an external buffer
184 note that by and bheight are in 4-pixel units! */
185void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
186 int width, int bheight, int stride)
187{
188 stride <<= 2; /* 4 pixels per block */
189 while (bheight--)
190 {
191 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1);
192 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
193 lcd_write_command(LCD_CNTL_DATA_WRITE);
194 lcd_grey_data(data, width);
195 data += stride;
196 }
197}
183 198
184/* Update the display. 199/* Update the display.
185 This must be called after all other LCD functions that change the display. */ 200 This must be called after all other LCD functions that change the display. */
diff --git a/firmware/target/sh/archos/lcd-archos-bitmap.c b/firmware/target/sh/archos/lcd-archos-bitmap.c
index 28600a9769..17c4d76092 100644
--- a/firmware/target/sh/archos/lcd-archos-bitmap.c
+++ b/firmware/target/sh/archos/lcd-archos-bitmap.c
@@ -155,10 +155,26 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
155 } 155 }
156} 156}
157 157
158/* Performance function that works with an external buffer
159 note that by and bheight are in 8-pixel units! */
160void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
161 int width, int bheight, int stride)
162{
163 stride <<= 3; /* 8 pixels per block */
164 while (bheight--)
165 {
166 lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf));
167 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
168 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
169
170 lcd_grey_data(data, width);
171 data += stride;
172 }
173}
174
158 175
159/* Update the display. 176/* Update the display.
160 This must be called after all other LCD functions that change the display. */ 177 This must be called after all other LCD functions that change the display. */
161void lcd_update(void) ICODE_ATTR;
162void lcd_update(void) 178void lcd_update(void)
163{ 179{
164 int y; 180 int y;
@@ -175,7 +191,6 @@ void lcd_update(void)
175} 191}
176 192
177/* Update a fraction of the display. */ 193/* Update a fraction of the display. */
178void lcd_update_rect(int, int, int, int) ICODE_ATTR;
179void lcd_update_rect(int x, int y, int width, int height) 194void lcd_update_rect(int x, int y, int width, int height)
180{ 195{
181 int ymax; 196 int ymax;
diff --git a/firmware/target/sh/archos/lcd-as-archos-bitmap.S b/firmware/target/sh/archos/lcd-as-archos-bitmap.S
index bef231c3c7..a84ce50686 100644
--- a/firmware/target/sh/archos/lcd-as-archos-bitmap.S
+++ b/firmware/target/sh/archos/lcd-as-archos-bitmap.S
@@ -81,26 +81,25 @@
81 */ 81 */
82 82
83_lcd_write_command: 83_lcd_write_command:
84 mov.l .lcdr,r3 /* put lcd data port address in r3 */ 84 mov.l .lcdr, r3 /* put lcd data port address in r3 */
85 mov r4,r1 /* copy data byte to r1 */ 85 mov r4, r1 /* copy data byte to r1 */
86 mov #1,r5 /* set byte count to 1 (!) */
87 86
88 /* This code will fail if an interrupt changes the contents of PBDRL. 87 /* This code will fail if an interrupt changes the contents of PBDRL.
89 * If so, we must disable the interrupt here. */ 88 * If so, we must disable the interrupt here. */
90 89
91 mov.b @r3,r0 /* r0 = PBDRL */ 90 mov.b @r3, r0 /* r0 = PBDRL */
92 or #(LCD_SD),r0 /* r0 |= LCD_SD */ 91 mov r4, r5 /* (fake) end address = current address */
93 and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */ 92 or #(LCD_SD), r0 /* r0 |= LCD_SD */
93 and #(~(LCD_CS|LCD_DS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */
94 94
95 bra .single_transfer /* jump into the transfer loop */ 95 bra .single_transfer /* jump into the transfer loop */
96 neg r0,r2 /* r2 = 0 - r0 */ 96 neg r0, r2 /* r2 = 0 - r0 */
97 97
98 98
99 .align 2 99 .align 2
100 .global _lcd_write_data 100 .global _lcd_write_data
101 .type _lcd_write_data,@function 101 .type _lcd_write_data,@function
102 102
103
104/* A high performance function to write data to the display, 103/* A high performance function to write data to the display,
105 * one or multiple bytes. 104 * one or multiple bytes.
106 * 105 *
@@ -117,8 +116,8 @@ _lcd_write_command:
117 */ 116 */
118 117
119_lcd_write_data: 118_lcd_write_data:
120 mov.l .lcdr,r3 /* put lcd data port address in r3 */ 119 mov.l .lcdr, r3 /* put lcd data port address in r3 */
121 nop /* align here */ 120 add r4, r5 /* end address */
122 121
123 /* This code will fail if an interrupt changes the contents of PBDRL. 122 /* This code will fail if an interrupt changes the contents of PBDRL.
124 * If so, we must disable the interrupt here. If disabling interrupts 123 * If so, we must disable the interrupt here. If disabling interrupts
@@ -127,85 +126,233 @@ _lcd_write_data:
127 * disable/precalculate/transfer/enable for each iteration. However, 126 * disable/precalculate/transfer/enable for each iteration. However,
128 * this would significantly decrease performance. */ 127 * this would significantly decrease performance. */
129 128
130 mov.b @r3,r0 /* r0 = PBDRL */ 129 mov.b @r3, r0 /* r0 = PBDRL */
131 or #(LCD_DS|LCD_SD),r0 /* r0 |= LCD_DS|LCD_SD */ 130 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
132 and #(~(LCD_CS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_SC) */ 131 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
133 neg r0,r2 /* r2 = 0 - r0 */ 132 neg r0, r2 /* r2 = 0 - r0 */
134 133
135 /* loop exploits that SD is on bit 0 for recorders and Ondios */ 134 /* loop exploits that SD is on bit 0 for recorders and Ondios */
136 135
137 .align 2 136 .align 2
138.multi_transfer: 137.multi_transfer:
139 mov.b @r4+,r1 /* load data byte from memory */ 138 mov.b @r4+, r1 /* load data byte from memory */
140 nop 139 nop
141 140
142.single_transfer: 141.single_transfer:
143 shll16 r1 /* shift data to most significant byte */ 142 shll16 r1 /* shift data to most significant byte */
144 shll8 r1 143 shll8 r1
145 not r1,r1 /* and invert for use with negc */ 144 not r1, r1 /* and invert for use with negc */
146 145
147 shll r1 /* shift the MSB into carry */ 146 shll r1 /* shift the MSB into carry */
148 negc r2,r0 /* carry to SD, SC low */ 147 negc r2, r0 /* carry to SD, SC low */
149 shll r1 /* next shift here for alignment */ 148 shll r1 /* next shift here for alignment */
150 mov.b r0,@r3 /* set data to port */ 149 mov.b r0, @r3 /* set data to port */
151 or #(LCD_SC),r0 /* rise SC (independent of SD level) */ 150 or #(LCD_SC), r0 /* rise SC (independent of SD level) */
152 mov.b r0,@r3 /* set to port */ 151 mov.b r0, @r3 /* set to port */
153 152
154 negc r2,r0 153 negc r2, r0
155 mov.b r0,@r3 154 mov.b r0, @r3
156 or #(LCD_SC),r0 155 or #(LCD_SC), r0
157 mov.b r0,@r3 156 mov.b r0, @r3
158 157
159 shll r1 158 shll r1
160 negc r2,r0 159 negc r2, r0
161 shll r1 160 shll r1
162 mov.b r0,@r3 161 mov.b r0, @r3
163 or #(LCD_SC),r0 162 or #(LCD_SC), r0
164 mov.b r0,@r3 163 mov.b r0, @r3
165 164
166 negc r2,r0 165 negc r2, r0
167 mov.b r0,@r3 166 mov.b r0, @r3
168 or #(LCD_SC),r0 167 or #(LCD_SC), r0
169 mov.b r0,@r3 168 mov.b r0, @r3
170 169
171 shll r1 170 shll r1
172 negc r2,r0 171 negc r2, r0
173 shll r1 172 shll r1
174 mov.b r0,@r3 173 mov.b r0, @r3
175 or #(LCD_SC),r0 174 or #(LCD_SC), r0
176 mov.b r0,@r3 175 mov.b r0, @r3
177 176
178 negc r2,r0 177 negc r2, r0
179 mov.b r0,@r3 178 mov.b r0, @r3
180 or #(LCD_SC),r0 179 or #(LCD_SC), r0
181 mov.b r0,@r3 180 mov.b r0, @r3
182 181
183 shll r1 182 shll r1
184 negc r2,r0 183 negc r2, r0
185 shll r1 184 shll r1
186 mov.b r0,@r3 185 mov.b r0, @r3
187 or #(LCD_SC),r0 186 or #(LCD_SC), r0
188 mov.b r0,@r3 187 mov.b r0, @r3
188
189 negc r2, r0
190 mov.b r0, @r3
191 or #(LCD_SC), r0
192 mov.b r0, @r3
193
194 cmp/hi r4, r5 /* some blocks left? */
195 bt .multi_transfer
196
197 or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0 /* restore port */
198 rts
199 mov.b r0, @r3
200
201 /* This is the place to reenable the interrupts, if we have disabled
202 * them. See above. */
203
204
205 .align 2
206 .global _lcd_grey_data
207 .type _lcd_grey_data,@function
208
209/* A high performance function to write grey phase data to the display,
210 * one or multiple pixels.
211 *
212 * Arguments:
213 * r4 - data address, (phase,value)-pairs
214 * r5 - pixel block count
215 *
216 * Register usage:
217 * r0 - current pixel value
218 * r1 - scratch
219 * r2 - precalculated port value (CS and SC low, DS and SD high),
220 * negated (neg)!
221 * r3 - lcd port address
222 * r5 - end address
223 * r6/r7 - current/next pixel phase
224 * r8 - current block address (for writing back phase)
225 * r9 - 0x80 (for phase modification)
226 */
227
228_lcd_grey_data:
229 mov.l r8, @-r15 /* save r8 */
230 shll2 r5 /* v */
231 mov.l r9, @-r15 /* save r9 */
232 shll2 r5 /* r5 *= 16; (8 pixel per block * 2 bytes/pixel) */
233 mov.l .lcdr, r3 /* put lcd data port address in r3 */
234 add r4, r5 /* end address */
189 235
190 negc r2,r0 236 /* This code will fail if an interrupt changes the contents of PBDRL.
191 mov.b r0,@r3 237 * If so, we must disable the interrupt here. If disabling interrupts
192 or #(LCD_SC),r0 238 * for a long time is undesirable, the loop has to be rewritten to
193 mov.b r0,@r3 239 * disable/precalculate/transfer/enable for each iteration. However,
240 * this would significantly decrease performance. */
194 241
195 add #-1,r5 /* decrease byte count */ 242 mov.b @r3, r0 /* r0 = PBDRL */
196 tst r5,r5 /* r5 == 0 ? */ 243 mov r4, r8 /* copy start address */
197 bf .multi_transfer /* no: next iteration */ 244 mov.b @r4+, r6 /* fetch first pixel phase */
245 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
246 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
247 neg r0, r2 /* r2 = 0 - r0 */
248 mov #0x80, r9 /* for phase modification - "or #imm,xx" only allows r0 */
249
250 /* loop exploits that SD is on bit 0 for recorders and Ondios */
198 251
199 or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC),r0 /* restore port */ 252.greyloop:
253 cmp/pz r6 /* phase non-negative? */
254 mov.b @r4+, r0 /* fetch pixel value */
255 negc r2, r1 /* T -> SD, SC low */
256 mov.b r1, @r3 /* set port */
257 or r9, r6 /* r6 -= (r6 >= 0) ? 128 : 0; */
258 mov.b @r4+, r7 /* fetch next pixel phase */
259 add #(LCD_SC), r1 /* rise SC */
260 mov.b r1, @r3 /* set port */
261 add r6, r0 /* calculate new phase */
262 mov.b r0, @r8 /* store phase */
263
264 cmp/pz r7
265 mov.b @r4+, r0
266 negc r2, r1
267 mov.b r1, @r3
268 or r9, r7
269 mov.b @r4+, r6
270 add #(LCD_SC), r1
271 mov.b r1, @r3
272 add r7, r0
273 mov.b r0, @(2,r8)
274
275 cmp/pz r6
276 mov.b @r4+, r0
277 negc r2, r1
278 mov.b r1, @r3
279 or r9, r6
280 mov.b @r4+, r7
281 add #(LCD_SC), r1
282 mov.b r1, @r3
283 add r6, r0
284 mov.b r0, @(4,r8)
285
286 cmp/pz r7
287 mov.b @r4+, r0
288 negc r2, r1
289 mov.b r1, @r3
290 or r9, r7
291 mov.b @r4+, r6
292 add #(LCD_SC), r1
293 mov.b r1, @r3
294 add r7, r0
295 mov.b r0, @(6,r8)
296
297 cmp/pz r6
298 mov.b @r4+, r0
299 negc r2, r1
300 mov.b r1, @r3
301 or r9, r6
302 mov.b @r4+, r7
303 add #(LCD_SC), r1
304 mov.b r1, @r3
305 add r6, r0
306 mov.b r0, @(8,r8)
307
308 cmp/pz r7
309 mov.b @r4+, r0
310 negc r2, r1
311 mov.b r1, @r3
312 or r9, r7
313 mov.b @r4+, r6
314 add #(LCD_SC), r1
315 mov.b r1, @r3
316 add r7, r0
317 mov.b r0, @(10,r8)
318
319 cmp/pz r6
320 mov.b @r4+, r0
321 negc r2, r1
322 mov.b r1, @r3
323 or r9, r6
324 mov.b @r4+, r7
325 add #(LCD_SC), r1
326 mov.b r1, @r3
327 add r6, r0
328 mov.b r0, @(12,r8)
329
330 cmp/pz r7
331 mov.b @r4+, r0
332 negc r2, r1
333 mov.b r1, @r3
334 or r9, r7
335 mov.b @r4+, r6
336 add #(LCD_SC), r1
337 mov.b r1, @r3
338 add r7, r0
339 mov.b r0, @(14,r8)
340
341 add #16, r8 /* advance current block address */
342 cmp/hi r4, r5 /* some blocks left? */
343 bt .greyloop
344
345 mov.l @r15+, r9 /* restore r9 */
346 mov #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0
347 mov.l @r15+, r8 /* restore r8 */
348 or r0, r1 /* restore port */
200 rts 349 rts
201 mov.b r0,@r3 350 mov.b r1, @r3
202 351
203 /* This is the place to reenable the interrupts, if we have disabled 352 /* This is the place to reenable the interrupts, if we have disabled
204 * them. See above. */ 353 * them. See above. */
205 354
355
206 .align 2 356 .align 2
207.lcdr: 357.lcdr:
208 .long LCDR 358 .long LCDR
209
210.end:
211 .size _lcd_write_command,.end-_lcd_write_command