summaryrefslogtreecommitdiff
path: root/firmware/target/sh/archos
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/sh/archos')
-rw-r--r--firmware/target/sh/archos/lcd-archos-bitmap.c19
-rw-r--r--firmware/target/sh/archos/lcd-as-archos-bitmap.S259
2 files changed, 220 insertions, 58 deletions
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