diff options
author | Jens Arnold <amiconn@rockbox.org> | 2007-03-05 00:04:00 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2007-03-05 00:04:00 +0000 |
commit | 8876018d25c6a56cce118482c1372bbff344cb23 (patch) | |
tree | a66dca10bf92674c655b9862fd366ecc77bba76a /firmware/target/coldfire/iaudio/lcd-remote-iaudio.c | |
parent | ee07215d506def8d3483f4adf6e1d4ae51c10c52 (diff) | |
download | rockbox-8876018d25c6a56cce118482c1372bbff344cb23.tar.gz rockbox-8876018d25c6a56cce118482c1372bbff344cb23.zip |
Bring up the M5 port to a working stage: Extended numerous explicit checks for IAUDIO_X5 to also check for IAUDIO_M5, moved code around the target tree, added preliminary background for the sim.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12610 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/coldfire/iaudio/lcd-remote-iaudio.c')
-rw-r--r-- | firmware/target/coldfire/iaudio/lcd-remote-iaudio.c | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c b/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c new file mode 100644 index 0000000000..139ebbc2a3 --- /dev/null +++ b/firmware/target/coldfire/iaudio/lcd-remote-iaudio.c | |||
@@ -0,0 +1,517 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 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 | #include "system.h" | ||
21 | #include "kernel.h" | ||
22 | #include "lcd-remote.h" | ||
23 | |||
24 | /* The LCD in the iAudio M3/M5/X5 remote control is a Tomato LSI 0350 */ | ||
25 | |||
26 | #define LCD_SET_DUTY_RATIO 0x48 | ||
27 | #define LCD_SELECT_ADC 0xa0 | ||
28 | #define LCD_SELECT_SHL 0xc0 | ||
29 | #define LCD_SET_COM0 0x44 | ||
30 | #define LCD_OSC_ON 0xab | ||
31 | #define LCD_SELECT_DCDC 0x64 | ||
32 | #define LCD_SELECT_RES 0x20 | ||
33 | #define LCD_SET_VOLUME 0x81 | ||
34 | #define LCD_SET_BIAS 0x50 | ||
35 | #define LCD_CONTROL_POWER 0x28 | ||
36 | #define LCD_DISPLAY_ON 0xae | ||
37 | #define LCD_SET_INITLINE 0x40 | ||
38 | #define LCD_SET_COLUMN 0x10 | ||
39 | #define LCD_SET_PAGE 0xb0 | ||
40 | #define LCD_SET_GRAY 0x88 | ||
41 | #define LCD_SET_PWM_FRC 0x90 | ||
42 | #define LCD_SET_POWER_SAVE 0xa8 | ||
43 | #define LCD_REVERSE 0xa6 | ||
44 | |||
45 | #define CS_LO and_l(~0x00000020, &GPIO1_OUT) | ||
46 | #define CS_HI or_l(0x00000020, &GPIO1_OUT) | ||
47 | #define CLK_LO and_l(~0x00004000, &GPIO_OUT) | ||
48 | #define CLK_HI or_l(0x00004000, &GPIO_OUT) | ||
49 | #define DATA_LO and_l(~0x00002000, &GPIO_OUT) | ||
50 | #define DATA_HI or_l(0x00002000, &GPIO_OUT) | ||
51 | #define RS_LO and_l(~0x00008000, &GPIO_OUT) | ||
52 | #define RS_HI or_l(0x00008000, &GPIO_OUT) | ||
53 | |||
54 | /* cached settings values */ | ||
55 | static bool cached_invert = false; | ||
56 | static bool cached_flip = false; | ||
57 | static int cached_contrast = DEFAULT_REMOTE_CONTRAST_SETTING; | ||
58 | |||
59 | bool remote_initialized = false; | ||
60 | |||
61 | static void remote_tick(void); | ||
62 | |||
63 | /* Standard low-level byte writer. Requires CLK high on entry */ | ||
64 | static inline void _write_byte(unsigned data) | ||
65 | { | ||
66 | asm volatile ( | ||
67 | "move.l (%[gpo0]), %%d0 \n" /* Get current state of data line */ | ||
68 | "and.l %[dbit], %%d0 \n" | ||
69 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
70 | "bset #8, %[data] \n" | ||
71 | "1: \n" | ||
72 | "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
73 | "lsr.l #1, %%d0 \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 */ | ||
75 | "swap %[data] \n" /* Shift data to upper byte */ | ||
76 | "lsl.l #8, %[data] \n" | ||
77 | |||
78 | "move.l %[cbit], %%d1 \n" /* Prepare mask for flipping CLK */ | ||
79 | "or.l %[dbit], %%d1 \n" /* and DATA at once */ | ||
80 | |||
81 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
82 | "bcc.s 1f \n" | ||
83 | "eor.l %%d1, (%[gpo0]) \n" /* 1: Flip both CLK and DATA */ | ||
84 | ".word 0x51fa \n" /* (trapf.w - shadow next insn) */ | ||
85 | "1: \n" | ||
86 | "eor.l %[cbit], (%[gpo0]) \n" /* else flip CLK only */ | ||
87 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK again */ | ||
88 | |||
89 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
90 | "bcc.s 1f \n" | ||
91 | "eor.l %%d1, (%[gpo0]) \n" | ||
92 | ".word 0x51fa \n" | ||
93 | "1: \n" | ||
94 | "eor.l %[cbit], (%[gpo0]) \n" | ||
95 | "eor.l %[cbit], (%[gpo0]) \n" | ||
96 | |||
97 | "lsl.l #1,%[data] \n" | ||
98 | "bcc.s 1f \n" | ||
99 | "eor.l %%d1, (%[gpo0]) \n" | ||
100 | ".word 0x51fa \n" | ||
101 | "1: \n" | ||
102 | "eor.l %[cbit], (%[gpo0]) \n" | ||
103 | "eor.l %[cbit], (%[gpo0]) \n" | ||
104 | |||
105 | "lsl.l #1,%[data] \n" | ||
106 | "bcc.s 1f \n" | ||
107 | "eor.l %%d1, (%[gpo0]) \n" | ||
108 | ".word 0x51fa \n" | ||
109 | "1: \n" | ||
110 | "eor.l %[cbit], (%[gpo0]) \n" | ||
111 | "eor.l %[cbit], (%[gpo0]) \n" | ||
112 | |||
113 | "lsl.l #1,%[data] \n" | ||
114 | "bcc.s 1f \n" | ||
115 | "eor.l %%d1, (%[gpo0]) \n" | ||
116 | ".word 0x51fa \n" | ||
117 | "1: \n" | ||
118 | "eor.l %[cbit], (%[gpo0]) \n" | ||
119 | "eor.l %[cbit], (%[gpo0]) \n" | ||
120 | |||
121 | "lsl.l #1,%[data] \n" | ||
122 | "bcc.s 1f \n" | ||
123 | "eor.l %%d1, (%[gpo0]) \n" | ||
124 | ".word 0x51fa \n" | ||
125 | "1: \n" | ||
126 | "eor.l %[cbit], (%[gpo0]) \n" | ||
127 | "eor.l %[cbit], (%[gpo0]) \n" | ||
128 | |||
129 | "lsl.l #1,%[data] \n" | ||
130 | "bcc.s 1f \n" | ||
131 | "eor.l %%d1, (%[gpo0]) \n" | ||
132 | ".word 0x51fa \n" | ||
133 | "1: \n" | ||
134 | "eor.l %[cbit], (%[gpo0]) \n" | ||
135 | "eor.l %[cbit], (%[gpo0]) \n" | ||
136 | |||
137 | "lsl.l #1,%[data] \n" | ||
138 | "bcc.s 1f \n" | ||
139 | "eor.l %%d1, (%[gpo0]) \n" | ||
140 | ".word 0x51fa \n" | ||
141 | "1: \n" | ||
142 | "eor.l %[cbit], (%[gpo0]) \n" | ||
143 | "eor.l %[cbit], (%[gpo0]) \n" | ||
144 | : /* outputs */ | ||
145 | [data]"+d"(data) | ||
146 | : /* inputs */ | ||
147 | [gpo0]"a"(&GPIO_OUT), | ||
148 | [cbit]"d"(0x00004000), | ||
149 | [dbit]"d"(0x00002000) | ||
150 | : /* clobbers */ | ||
151 | "d0", "d1" | ||
152 | ); | ||
153 | } | ||
154 | |||
155 | /* Fast low-level byte writer. Don't use with high CPU clock. | ||
156 | * Requires CLK high on entry */ | ||
157 | static inline void _write_fast(unsigned data) | ||
158 | { | ||
159 | asm volatile ( | ||
160 | "move.w %%sr,%%d3 \n" /* Get current interrupt level */ | ||
161 | "move.w #0x2700,%%sr \n" /* Disable interrupts */ | ||
162 | |||
163 | "move.l (%[gpo0]), %%d0 \n" /* Get current state of data port */ | ||
164 | "move.l %%d0, %%d1 \n" | ||
165 | "and.l %[dbit], %%d1 \n" /* Check current state of data line */ | ||
166 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
167 | "bset #8, %[data] \n" | ||
168 | "1: \n" | ||
169 | "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
170 | "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */ | ||
171 | "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */ | ||
172 | "swap %[data] \n" /* Shift data to upper byte */ | ||
173 | "lsl.l #8, %[data] \n" | ||
174 | |||
175 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
176 | "bcc.s 1f \n" | ||
177 | "eor.l %[dbit], %%d0 \n" /* 1: Flip data bit */ | ||
178 | "1: \n" | ||
179 | "eor.l %[cbit], %%d0 \n" /* Flip clock bit */ | ||
180 | "move.l %%d0, (%[gpo0]) \n" /* Output new state */ | ||
181 | "eor.l %[cbit], %%d0 \n" /* Flip clock bit */ | ||
182 | "move.l %%d0, (%[gpo0]) \n" /* Output new state */ | ||
183 | |||
184 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
185 | "bcc.s 1f \n" | ||
186 | "eor.l %[dbit], %%d0 \n" | ||
187 | "1: \n" | ||
188 | "eor.l %[cbit], %%d0 \n" | ||
189 | "move.l %%d0, (%[gpo0]) \n" | ||
190 | "eor.l %[cbit], %%d0 \n" | ||
191 | "move.l %%d0, (%[gpo0]) \n" | ||
192 | |||
193 | "lsl.l #1,%[data] \n" | ||
194 | "bcc.s 1f \n" | ||
195 | "eor.l %[dbit], %%d0 \n" | ||
196 | "1: \n" | ||
197 | "eor.l %[cbit], %%d0 \n" | ||
198 | "move.l %%d0, (%[gpo0]) \n" | ||
199 | "eor.l %[cbit], %%d0 \n" | ||
200 | "move.l %%d0, (%[gpo0]) \n" | ||
201 | |||
202 | "lsl.l #1,%[data] \n" | ||
203 | "bcc.s 1f \n" | ||
204 | "eor.l %[dbit], %%d0 \n" | ||
205 | "1: \n" | ||
206 | "eor.l %[cbit], %%d0 \n" | ||
207 | "move.l %%d0, (%[gpo0]) \n" | ||
208 | "eor.l %[cbit], %%d0 \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 | "1: \n" | ||
215 | "eor.l %[cbit], %%d0 \n" | ||
216 | "move.l %%d0, (%[gpo0]) \n" | ||
217 | "eor.l %[cbit], %%d0 \n" | ||
218 | "move.l %%d0, (%[gpo0]) \n" | ||
219 | |||
220 | "lsl.l #1,%[data] \n" | ||
221 | "bcc.s 1f \n" | ||
222 | "eor.l %[dbit], %%d0 \n" | ||
223 | "1: \n" | ||
224 | "eor.l %[cbit], %%d0 \n" | ||
225 | "move.l %%d0, (%[gpo0]) \n" | ||
226 | "eor.l %[cbit], %%d0 \n" | ||
227 | "move.l %%d0, (%[gpo0]) \n" | ||
228 | |||
229 | "lsl.l #1,%[data] \n" | ||
230 | "bcc.s 1f \n" | ||
231 | "eor.l %[dbit], %%d0 \n" | ||
232 | "1: \n" | ||
233 | "eor.l %[cbit], %%d0 \n" | ||
234 | "move.l %%d0, (%[gpo0]) \n" | ||
235 | "eor.l %[cbit], %%d0 \n" | ||
236 | "move.l %%d0, (%[gpo0]) \n" | ||
237 | |||
238 | "lsl.l #1,%[data] \n" | ||
239 | "bcc.s 1f \n" | ||
240 | "eor.l %[dbit], %%d0 \n" | ||
241 | "1: \n" | ||
242 | "eor.l %[cbit], %%d0 \n" | ||
243 | "move.l %%d0, (%[gpo0]) \n" | ||
244 | "eor.l %[cbit], %%d0 \n" | ||
245 | "move.l %%d0, (%[gpo0]) \n" | ||
246 | |||
247 | "move.w %%d3, %%sr \n" /* Restore interrupt level */ | ||
248 | : /* outputs */ | ||
249 | [data]"+d"(data) | ||
250 | : /* inputs */ | ||
251 | [gpo0]"a"(&GPIO_OUT), | ||
252 | [cbit]"d"(0x00004000), | ||
253 | [dbit]"d"(0x00002000) | ||
254 | : /* clobbers */ | ||
255 | "d0", "d1", "d2", "d3" | ||
256 | ); | ||
257 | } | ||
258 | |||
259 | void lcd_remote_write_command(int cmd) | ||
260 | { | ||
261 | RS_LO; | ||
262 | CS_LO; | ||
263 | _write_byte(cmd); | ||
264 | CS_HI; | ||
265 | } | ||
266 | |||
267 | void lcd_remote_write_command_ex(int cmd, int data) | ||
268 | { | ||
269 | RS_LO; | ||
270 | CS_LO; | ||
271 | _write_byte(cmd); | ||
272 | _write_byte(data); | ||
273 | CS_HI; | ||
274 | } | ||
275 | |||
276 | void lcd_remote_write_data(const unsigned char* p_bytes, int count) | ||
277 | { | ||
278 | const unsigned char *p_end = p_bytes + count; | ||
279 | |||
280 | RS_HI; | ||
281 | CS_LO; | ||
282 | if (cpu_frequency < 50000000) | ||
283 | { | ||
284 | while (p_bytes < p_end) | ||
285 | _write_fast(*p_bytes++); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | while (p_bytes < p_end) | ||
290 | _write_byte(*p_bytes++); | ||
291 | } | ||
292 | CS_HI; | ||
293 | } | ||
294 | |||
295 | int lcd_remote_default_contrast(void) | ||
296 | { | ||
297 | return DEFAULT_REMOTE_CONTRAST_SETTING; | ||
298 | } | ||
299 | |||
300 | void lcd_remote_powersave(bool on) | ||
301 | { | ||
302 | if(remote_initialized) { | ||
303 | if (on) | ||
304 | lcd_remote_write_command(LCD_SET_POWER_SAVE | 1); | ||
305 | else | ||
306 | lcd_remote_write_command(LCD_SET_POWER_SAVE | 1); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void lcd_remote_set_contrast(int val) | ||
311 | { | ||
312 | if (val < 0) | ||
313 | val = 0; | ||
314 | else if (val > 63) | ||
315 | val = 63; | ||
316 | |||
317 | cached_contrast = val; | ||
318 | if(remote_initialized) | ||
319 | lcd_remote_write_command_ex(LCD_SET_VOLUME, val); | ||
320 | } | ||
321 | |||
322 | bool remote_detect(void) | ||
323 | { | ||
324 | return (GPIO_READ & 0x01000000)?false:true; | ||
325 | } | ||
326 | |||
327 | void lcd_remote_init_device(void) | ||
328 | { | ||
329 | or_l(0x0000e000, &GPIO_OUT); | ||
330 | or_l(0x0000e000, &GPIO_ENABLE); | ||
331 | or_l(0x0000e000, &GPIO_FUNCTION); | ||
332 | |||
333 | or_l(0x00000020, &GPIO1_OUT); | ||
334 | or_l(0x00000020, &GPIO1_ENABLE); | ||
335 | or_l(0x00000020, &GPIO1_FUNCTION); | ||
336 | |||
337 | and_l(~0x01000000, &GPIO_OUT); | ||
338 | and_l(~0x01000000, &GPIO_ENABLE); | ||
339 | or_l(0x01000000, &GPIO_FUNCTION); | ||
340 | |||
341 | lcd_remote_clear_display(); | ||
342 | tick_add_task(remote_tick); | ||
343 | } | ||
344 | |||
345 | void lcd_remote_on(void) | ||
346 | { | ||
347 | CS_HI; | ||
348 | CLK_HI; | ||
349 | sleep(10); | ||
350 | |||
351 | lcd_remote_write_command(LCD_SET_DUTY_RATIO); | ||
352 | lcd_remote_write_command(0x70); /* 1/128 */ | ||
353 | |||
354 | lcd_remote_write_command(LCD_OSC_ON); | ||
355 | |||
356 | lcd_remote_write_command(LCD_SELECT_DCDC | 2); /* DC/DC 5xboost */ | ||
357 | |||
358 | lcd_remote_write_command(LCD_SELECT_RES | 7); /* Regulator resistor: 7.2 */ | ||
359 | |||
360 | lcd_remote_write_command(LCD_SET_BIAS | 6); /* 1/11 */ | ||
361 | |||
362 | lcd_remote_write_command(LCD_CONTROL_POWER | 7); /* All circuits ON */ | ||
363 | |||
364 | sleep(30); | ||
365 | |||
366 | lcd_remote_write_command_ex(LCD_SET_GRAY | 0, 0x00); | ||
367 | lcd_remote_write_command_ex(LCD_SET_GRAY | 1, 0x00); | ||
368 | lcd_remote_write_command_ex(LCD_SET_GRAY | 2, 0x0c); | ||
369 | lcd_remote_write_command_ex(LCD_SET_GRAY | 3, 0x00); | ||
370 | lcd_remote_write_command_ex(LCD_SET_GRAY | 4, 0xcc); | ||
371 | lcd_remote_write_command_ex(LCD_SET_GRAY | 5, 0x00); | ||
372 | lcd_remote_write_command_ex(LCD_SET_GRAY | 6, 0xcc); | ||
373 | lcd_remote_write_command_ex(LCD_SET_GRAY | 7, 0x0c); | ||
374 | |||
375 | lcd_remote_write_command(LCD_SET_PWM_FRC | 6); /* 4FRC + 12PWM */ | ||
376 | |||
377 | lcd_remote_write_command(LCD_DISPLAY_ON | 1); /* display on */ | ||
378 | |||
379 | remote_initialized = true; | ||
380 | |||
381 | lcd_remote_set_flip(cached_flip); | ||
382 | lcd_remote_set_contrast(cached_contrast); | ||
383 | lcd_remote_set_invert_display(cached_invert); | ||
384 | } | ||
385 | |||
386 | void lcd_remote_off(void) | ||
387 | { | ||
388 | remote_initialized = false; | ||
389 | CS_HI; | ||
390 | RS_HI; | ||
391 | } | ||
392 | |||
393 | void lcd_remote_poweroff(void) | ||
394 | { | ||
395 | /* Set power save -> Power OFF (VDD - VSS) .. that's it */ | ||
396 | if (remote_initialized && remote_detect()) | ||
397 | lcd_remote_write_command(LCD_SET_POWER_SAVE | 1); | ||
398 | } | ||
399 | |||
400 | /* Monitor remote hotswap */ | ||
401 | static void remote_tick(void) | ||
402 | { | ||
403 | static bool last_status = false; | ||
404 | static int countdown = 0; | ||
405 | static int init_delay = 0; | ||
406 | bool current_status; | ||
407 | |||
408 | current_status = remote_detect(); | ||
409 | |||
410 | /* Only report when the status has changed */ | ||
411 | if (current_status != last_status) | ||
412 | { | ||
413 | last_status = current_status; | ||
414 | countdown = current_status ? 20*HZ : 1; | ||
415 | } | ||
416 | else | ||
417 | { | ||
418 | /* Count down until it gets negative */ | ||
419 | if (countdown >= 0) | ||
420 | countdown--; | ||
421 | |||
422 | if (current_status) | ||
423 | { | ||
424 | if (!(countdown % 8)) | ||
425 | { | ||
426 | if (--init_delay <= 0) | ||
427 | { | ||
428 | queue_post(&remote_scroll_queue, REMOTE_INIT_LCD, 0); | ||
429 | init_delay = 6; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | if (countdown == 0) | ||
436 | { | ||
437 | queue_post(&remote_scroll_queue, REMOTE_DEINIT_LCD, 0); | ||
438 | } | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /* Update the display. | ||
444 | This must be called after all other LCD functions that change the display. */ | ||
445 | void lcd_remote_update(void) ICODE_ATTR; | ||
446 | void lcd_remote_update(void) | ||
447 | { | ||
448 | int y; | ||
449 | if(remote_initialized) { | ||
450 | for(y = 0;y < LCD_REMOTE_FBHEIGHT;y++) { | ||
451 | /* Copy display bitmap to hardware. | ||
452 | The COM48-COM63 lines are not connected so we have to skip | ||
453 | them. Further, the column address doesn't wrap, so we | ||
454 | have to update one page at a time. */ | ||
455 | lcd_remote_write_command(LCD_SET_PAGE | (y>5?y+2:y)); | ||
456 | lcd_remote_write_command_ex(LCD_SET_COLUMN | 0, 0); | ||
457 | lcd_remote_write_data((unsigned char *)lcd_remote_framebuffer[y], | ||
458 | LCD_REMOTE_WIDTH*2); | ||
459 | } | ||
460 | } | ||
461 | } | ||
462 | |||
463 | /* Update a fraction of the display. */ | ||
464 | void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR; | ||
465 | void lcd_remote_update_rect(int x, int y, int width, int height) | ||
466 | { | ||
467 | if(remote_initialized) { | ||
468 | int ymax; | ||
469 | |||
470 | /* The Y coordinates have to work on even 8 pixel rows */ | ||
471 | ymax = (y + height-1) >> 3; | ||
472 | y >>= 3; | ||
473 | |||
474 | if(x + width > LCD_REMOTE_WIDTH) | ||
475 | width = LCD_REMOTE_WIDTH - x; | ||
476 | if (width <= 0) | ||
477 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | ||
478 | if(ymax >= LCD_REMOTE_FBHEIGHT) | ||
479 | ymax = LCD_REMOTE_FBHEIGHT-1; | ||
480 | |||
481 | /* Copy specified rectangle bitmap to hardware | ||
482 | COM48-COM63 are not connected, so we need to skip those */ | ||
483 | for (; y <= ymax; y++) | ||
484 | { | ||
485 | lcd_remote_write_command(LCD_SET_PAGE | | ||
486 | ((y > 5?y + 2:y) & 0xf)); | ||
487 | lcd_remote_write_command_ex(LCD_SET_COLUMN | ((x >> 4) & 0xf), | ||
488 | x & 0xf); | ||
489 | |||
490 | lcd_remote_write_data ( | ||
491 | (unsigned char *)&lcd_remote_framebuffer[y][x], width*2); | ||
492 | } | ||
493 | } | ||
494 | } | ||
495 | |||
496 | void lcd_remote_set_invert_display(bool yesno) | ||
497 | { | ||
498 | cached_invert = yesno; | ||
499 | if(remote_initialized) | ||
500 | lcd_remote_write_command(LCD_REVERSE | yesno); | ||
501 | } | ||
502 | |||
503 | void lcd_remote_set_flip(bool yesno) | ||
504 | { | ||
505 | cached_flip = yesno; | ||
506 | if(remote_initialized) { | ||
507 | if(yesno) { | ||
508 | lcd_remote_write_command(LCD_SELECT_ADC | 0); | ||
509 | lcd_remote_write_command(LCD_SELECT_SHL | 0); | ||
510 | lcd_remote_write_command_ex(LCD_SET_COM0, 16); | ||
511 | } else { | ||
512 | lcd_remote_write_command(LCD_SELECT_ADC | 1); | ||
513 | lcd_remote_write_command(LCD_SELECT_SHL | 8); | ||
514 | lcd_remote_write_command_ex(LCD_SET_COM0, 0); | ||
515 | } | ||
516 | } | ||
517 | } | ||