diff options
Diffstat (limited to 'firmware/target/coldfire/mpio/hd300')
-rw-r--r-- | firmware/target/coldfire/mpio/hd300/button-hd300.c | 234 | ||||
-rw-r--r-- | firmware/target/coldfire/mpio/hd300/button-target.h | 55 | ||||
-rw-r--r-- | firmware/target/coldfire/mpio/hd300/lcd-as-hd300.S | 227 | ||||
-rw-r--r-- | firmware/target/coldfire/mpio/hd300/lcd-hd300.c | 244 | ||||
-rw-r--r-- | firmware/target/coldfire/mpio/hd300/powermgmt-hd300.c | 58 |
5 files changed, 818 insertions, 0 deletions
diff --git a/firmware/target/coldfire/mpio/hd300/button-hd300.c b/firmware/target/coldfire/mpio/hd300/button-hd300.c new file mode 100644 index 0000000000..19c93abfca --- /dev/null +++ b/firmware/target/coldfire/mpio/hd300/button-hd300.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Marcin Bukat | ||
11 | * scrollstrip logic inspired by button-mini1g.c | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #include "config.h" | ||
24 | #include "cpu.h" | ||
25 | #include "system.h" | ||
26 | #include "button.h" | ||
27 | #include "backlight.h" | ||
28 | #include "adc.h" | ||
29 | #include "powermgmt.h" | ||
30 | |||
31 | #define SLIDER_BASE_SENSITIVITY 6 | ||
32 | |||
33 | /* GPI7 H-L, GPI6 H-L, GPI7 L-H, GPI6 L-H */ | ||
34 | #define SLIDER_GPIO_MASK ((1<<15)|(1<<14)|(1<<7)|(1<<6)) | ||
35 | |||
36 | static inline void disable_scrollstrip_interrupts(void) | ||
37 | { | ||
38 | and_l(~SLIDER_GPIO_MASK,&GPIO_INT_EN); | ||
39 | } | ||
40 | |||
41 | static inline void enable_scrollstrip_interrupts(void) | ||
42 | { | ||
43 | |||
44 | or_l(SLIDER_GPIO_MASK,&GPIO_INT_EN); | ||
45 | } | ||
46 | |||
47 | static inline void ack_scrollstrip_interrupt(void) | ||
48 | { | ||
49 | or_l(SLIDER_GPIO_MASK,&GPIO_INT_CLEAR); | ||
50 | } | ||
51 | |||
52 | void scrollstrip_isr(void) __attribute__ ((interrupt_handler,section(".icode"))); | ||
53 | void scrollstrip_isr(void) | ||
54 | { | ||
55 | /* reading line 6 and 7 forms four possible states: | ||
56 | * 0, 1 , 2, 3 | ||
57 | * tracking the order of line changes we can judge | ||
58 | * if the slide is up or down in the following way: | ||
59 | * sliding up order: 0 2 3 1 0 2 3 1 | ||
60 | * sliding down order: 0 1 3 2 0 1 3 2 | ||
61 | */ | ||
62 | static const signed char scroll_state[4][4] ICONST_ATTR = { | ||
63 | { BUTTON_NONE, BUTTON_DOWN, BUTTON_UP, BUTTON_NONE}, | ||
64 | { BUTTON_UP, BUTTON_NONE, BUTTON_NONE, BUTTON_DOWN}, | ||
65 | { BUTTON_DOWN, BUTTON_NONE, BUTTON_NONE, BUTTON_UP}, | ||
66 | { BUTTON_NONE, BUTTON_UP, BUTTON_DOWN, BUTTON_NONE} | ||
67 | }; | ||
68 | |||
69 | static signed char prev_scroll_lines = -1; | ||
70 | static signed char direction = 0; | ||
71 | static unsigned char count = 0; | ||
72 | static long next_backlight_on = 0; | ||
73 | |||
74 | signed int new_scroll_lines; | ||
75 | signed int scroll_dir; | ||
76 | |||
77 | disable_scrollstrip_interrupts(); | ||
78 | |||
79 | /* read GPIO6 and GPIO7 state*/ | ||
80 | new_scroll_lines = (GPIO_READ >> 6) & 0x03; | ||
81 | |||
82 | if ( prev_scroll_lines == -1 ) | ||
83 | { | ||
84 | prev_scroll_lines = new_scroll_lines; | ||
85 | ack_scrollstrip_interrupt(); | ||
86 | enable_scrollstrip_interrupts(); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | scroll_dir = scroll_state[prev_scroll_lines][new_scroll_lines]; | ||
91 | prev_scroll_lines = new_scroll_lines; | ||
92 | |||
93 | if (direction != scroll_dir) | ||
94 | { | ||
95 | /* direction reversal */ | ||
96 | direction = scroll_dir; | ||
97 | count = 0; | ||
98 | ack_scrollstrip_interrupt(); | ||
99 | enable_scrollstrip_interrupts(); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | /* poke backlight */ | ||
104 | if (TIME_AFTER(current_tick, next_backlight_on)) | ||
105 | { | ||
106 | backlight_on(); | ||
107 | reset_poweroff_timer(); | ||
108 | next_backlight_on = current_tick + HZ/4; | ||
109 | } | ||
110 | |||
111 | if (++count < SLIDER_BASE_SENSITIVITY) | ||
112 | { | ||
113 | ack_scrollstrip_interrupt(); | ||
114 | enable_scrollstrip_interrupts(); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | count = 0; | ||
119 | |||
120 | /* post scrollstrip event to the button queue */ | ||
121 | if (queue_empty(&button_queue)) | ||
122 | queue_post(&button_queue, scroll_dir, 0); | ||
123 | |||
124 | ack_scrollstrip_interrupt(); | ||
125 | enable_scrollstrip_interrupts(); | ||
126 | } | ||
127 | |||
128 | /* register interrupt service routine for scrollstrip lines */ | ||
129 | void GPI6(void) __attribute__ ((alias("scrollstrip_isr"))); | ||
130 | void GPI7(void) __attribute__ ((alias("scrollstrip_isr"))); | ||
131 | |||
132 | void button_init_device(void) | ||
133 | { | ||
134 | /* GPIO56 (PLAY) general input | ||
135 | * GPIO45 (ENTER) general input | ||
136 | * GPIO41 (MENU) dual function pin shared with audio serial data | ||
137 | * | ||
138 | * GPIO6, GPIO7 scrollstrip lines | ||
139 | * GPIO31 scrollstrip enable | ||
140 | */ | ||
141 | |||
142 | or_l((1<<24)|(1<<13),&GPIO1_FUNCTION); | ||
143 | and_l(~((1<<24)|(1<<13)),&GPIO1_ENABLE); | ||
144 | |||
145 | or_l((1<<31)|(1<<7)|(1<<6),&GPIO_FUNCTION); | ||
146 | and_l(~((1<<7)|(1<<6)),&GPIO_ENABLE); | ||
147 | |||
148 | /* scrollstrip enable active low */ | ||
149 | and_l(~(1<<31),&GPIO_OUT); | ||
150 | or_l((1<<31),&GPIO_ENABLE); | ||
151 | |||
152 | /* GPI6, GPI7 interrupt level 4.0 */ | ||
153 | or_l((4<<28)|(4<<24), &INTPRI5); | ||
154 | |||
155 | enable_scrollstrip_interrupts(); | ||
156 | } | ||
157 | |||
158 | bool button_hold(void) | ||
159 | { | ||
160 | /* GPIO51 active low */ | ||
161 | return (GPIO1_READ & (1<<19))?false:true; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Get button pressed from hardware | ||
166 | */ | ||
167 | int button_read_device(void) | ||
168 | { | ||
169 | int btn = BUTTON_NONE; | ||
170 | int data = 0; | ||
171 | static bool hold_button = false; | ||
172 | |||
173 | bool hold_button_old; | ||
174 | |||
175 | |||
176 | /* read hold buttons status */ | ||
177 | hold_button_old = hold_button; | ||
178 | hold_button = button_hold(); | ||
179 | |||
180 | #ifndef BOOTLOADER | ||
181 | /* Only main hold affects backlight */ | ||
182 | if (hold_button != hold_button_old) | ||
183 | backlight_hold_changed(hold_button); | ||
184 | #endif | ||
185 | |||
186 | /* Skip if main hold is active */ | ||
187 | if (!hold_button) | ||
188 | { | ||
189 | data = adc_scan(ADC_BUTTONS); | ||
190 | |||
191 | if (data < 800) /* middle */ | ||
192 | { | ||
193 | if (data < 450) | ||
194 | { | ||
195 | if (data > 250) | ||
196 | btn |= BUTTON_FF; | ||
197 | } | ||
198 | else /* 800 - 450 */ | ||
199 | { | ||
200 | if (data > 600) | ||
201 | btn |= BUTTON_REW; | ||
202 | } | ||
203 | } | ||
204 | else /* data > 800 */ | ||
205 | { | ||
206 | if (data < 1150) | ||
207 | if (data > 950) | ||
208 | btn |= BUTTON_REC; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* Handle GPIOs buttons | ||
213 | * | ||
214 | * GPIO56 active high PLAY/PAUSE/ON | ||
215 | * GPIO45 active low ENTER | ||
216 | * GPIO41 active low MENU | ||
217 | */ | ||
218 | |||
219 | data = GPIO1_READ; | ||
220 | |||
221 | if (!hold_button) | ||
222 | { | ||
223 | if (data & (1<<24)) | ||
224 | btn |= BUTTON_PLAY; | ||
225 | |||
226 | if (!(data & (1<<13))) | ||
227 | btn |= BUTTON_ENTER; | ||
228 | |||
229 | if (!(data & (1<<9))) | ||
230 | btn |= BUTTON_MENU; | ||
231 | } | ||
232 | |||
233 | return btn; | ||
234 | } | ||
diff --git a/firmware/target/coldfire/mpio/hd300/button-target.h b/firmware/target/coldfire/mpio/hd300/button-target.h new file mode 100644 index 0000000000..5cb2ae8bf2 --- /dev/null +++ b/firmware/target/coldfire/mpio/hd300/button-target.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Marcin Bukat | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef _BUTTON_TARGET_H_ | ||
22 | #define _BUTTON_TARGET_H_ | ||
23 | |||
24 | #include <stdbool.h> | ||
25 | #include "config.h" | ||
26 | |||
27 | #define HAS_BUTTON_HOLD | ||
28 | #define BUTTON_REMOTE 0 | ||
29 | |||
30 | bool button_hold(void); | ||
31 | void button_init_device(void); | ||
32 | int button_read_device(void); | ||
33 | |||
34 | /* HD300 specific button codes */ | ||
35 | #define BUTTON_PLAY 0x00000001 | ||
36 | #define BUTTON_REW 0x00000004 | ||
37 | #define BUTTON_FF 0x00000002 | ||
38 | #define BUTTON_UP 0x00000008 | ||
39 | #define BUTTON_DOWN 0x00000010 | ||
40 | #define BUTTON_REC 0x00000020 | ||
41 | #define BUTTON_MENU 0x00000040 | ||
42 | #define BUTTON_ENTER 0x00000080 | ||
43 | |||
44 | #define BUTTON_LEFT BUTTON_REW | ||
45 | #define BUTTON_RIGHT BUTTON_FF | ||
46 | #define BUTTON_ON BUTTON_PLAY | ||
47 | |||
48 | #define BUTTON_MAIN (BUTTON_PLAY|BUTTON_REW|BUTTON_FF|\ | ||
49 | BUTTON_UP|BUTTON_DOWN|BUTTON_REC|BUTTON_MENU|\ | ||
50 | BUTTON_ENTER) | ||
51 | |||
52 | #define POWEROFF_BUTTON BUTTON_PLAY | ||
53 | #define POWEROFF_COUNT 30 | ||
54 | |||
55 | #endif /* _BUTTON_TARGET_H_ */ | ||
diff --git a/firmware/target/coldfire/mpio/hd300/lcd-as-hd300.S b/firmware/target/coldfire/mpio/hd300/lcd-as-hd300.S new file mode 100644 index 0000000000..e5b04001dc --- /dev/null +++ b/firmware/target/coldfire/mpio/hd300/lcd-as-hd300.S | |||
@@ -0,0 +1,227 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Adopted for MPIO HD300 by Marcin Bukat | ||
11 | * Copyright (C) 2007 by Jens Arnold | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #include "config.h" | ||
24 | #include "cpu.h" | ||
25 | |||
26 | .section .icode,"ax",@progbits | ||
27 | |||
28 | .align 2 | ||
29 | .global lcd_write_command | ||
30 | .type lcd_write_command,@function | ||
31 | |||
32 | lcd_write_command: | ||
33 | move.l (4, %sp), %d0 | ||
34 | move.w %d0, 0xf0000000 | ||
35 | rts | ||
36 | .wc_end: | ||
37 | .size lcd_write_command,.wc_end-lcd_write_command | ||
38 | |||
39 | |||
40 | .align 2 | ||
41 | .global lcd_write_command_ex | ||
42 | .type lcd_write_command_ex,@function | ||
43 | |||
44 | lcd_write_command_ex: | ||
45 | lea.l 0xf0000000, %a0 | ||
46 | |||
47 | move.l (4, %sp), %d0 /* Command */ | ||
48 | move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */ | ||
49 | |||
50 | move.l (8, %sp), %d0 /* Data */ | ||
51 | cmp.l #-1, %d0 /* -1? */ | ||
52 | beq.b .last | ||
53 | move.w %d0, (%a0) /* Write to LCD */ | ||
54 | |||
55 | move.l (12, %sp), %d0 /* Data */ | ||
56 | cmp.l #-1, %d0 /* -1? */ | ||
57 | beq.b .last | ||
58 | move.w %d0, (%a0) /* Write to LCD */ | ||
59 | |||
60 | .last: | ||
61 | rts | ||
62 | .wcex_end: | ||
63 | .size lcd_write_command_ex,.wcex_end-lcd_write_command_ex | ||
64 | |||
65 | |||
66 | .align 2 | ||
67 | .global lcd_write_data | ||
68 | .type lcd_write_data,@function | ||
69 | |||
70 | lcd_write_data: | ||
71 | movem.l (4, %sp), %a0-%a1 /* Data pointer */ | ||
72 | move.l %a1, %d0 /* Length */ | ||
73 | lea 0xf0000002, %a1 | ||
74 | |||
75 | .loop: | ||
76 | /* When running in IRAM, this loop takes 10 cycles plus the LCD write. | ||
77 | The 10 cycles are necessary to follow the LCD timing specs | ||
78 | at 140MHz */ | ||
79 | nop /* 3(0/0) */ | ||
80 | move.b (%a0)+, %d1 /* 3(1/0) */ | ||
81 | move.w %d1, (%a1) /* 1(0/1) */ | ||
82 | subq.l #1, %d0 /* 1(0/0) */ | ||
83 | bne .loop /* 2(0/0) */ | ||
84 | rts | ||
85 | .wd_end: | ||
86 | .size lcd_write_data,.wd_end-lcd_write_data | ||
87 | |||
88 | |||
89 | .align 2 | ||
90 | .global lcd_grey_data | ||
91 | .type lcd_grey_data,@function | ||
92 | |||
93 | /* The main loop assumes the buffers are in SDRAM. Otherwise the LCD | ||
94 | * controller timing won't be met at 124 MHz and graphical glitches | ||
95 | * will occur. */ | ||
96 | |||
97 | lcd_grey_data: | ||
98 | lea.l (-11*4, %sp), %sp | ||
99 | movem.l %d2-%d7/%a2-%a6, (%sp) /* free some registers */ | ||
100 | movem.l (11*4+4, %sp), %a0-%a2 /* values, phases, length */ | ||
101 | lea.l (%a1, %a2.l*4), %a2 /* end address */ | ||
102 | lea 0xf0000002, %a3 /* LCD data port */ | ||
103 | moveq.l #24, %d6 /* shift count */ | ||
104 | move.l #0xc30c3, %d7 /* bit shuffle factor */ | ||
105 | |||
106 | moveq.l #12, %d2 | ||
107 | add.l %a1, %d2 | ||
108 | and.l #0xfffffff0, %d2 /* first line bound */ | ||
109 | cmp.l %d2, %a2 /* end address lower than first line bound? */ | ||
110 | bhs.s 1f | ||
111 | move.l %a2, %d2 /* -> adjust end address of head loop */ | ||
112 | 1: | ||
113 | cmp.l %a1, %d2 | ||
114 | bls.s .g_hend | ||
115 | |||
116 | .g_hloop: | ||
117 | move.l (%a1), %d0 /* fetch 4 pixel phases */ | ||
118 | |||
119 | move.l %d0, %d1 | ||
120 | and.l #0x80808080, %d1 /* separate MSBs of the 4 phases */ | ||
121 | eor.l %d1, %d0 /* clear them in %d0 */ | ||
122 | add.l (%a0)+, %d0 /* add 4 pixel values to the phases */ | ||
123 | move.l %d0, (%a1)+ /* store new phases, advance pointer */ | ||
124 | |||
125 | lsr.l #1, %d1 /* %d1 = .0.......1.......2.......3...... */ | ||
126 | mulu.l %d7, %d1 /* %d1 = 00112233112233..2233....33...... */ | ||
127 | not.l %d1 /* negate bits */ | ||
128 | lsr.l %d6, %d1 /* %d1 = ........................00112233 */ | ||
129 | move.w %d1, (%a3) /* write pixel block */ | ||
130 | |||
131 | cmp.l %a1, %d2 /* go up to first line bound */ | ||
132 | bhi.s .g_hloop | ||
133 | |||
134 | .g_hend: | ||
135 | cmp.l %a1, %a2 | ||
136 | bls.w .g_tend | ||
137 | lea.l (-12, %a2), %a2 | ||
138 | cmp.l %a1, %a2 | ||
139 | bls.s .g_lend | ||
140 | |||
141 | .g_lloop: | ||
142 | movem.l (%a1), %d0-%d3 /* fetch 4 blocks of 4 pixel phases each */ | ||
143 | |||
144 | move.l %d0, %d4 /* calculate first pixel block */ | ||
145 | and.l #0x80808080, %d4 | ||
146 | eor.l %d4, %d0 | ||
147 | lsr.l #1, %d4 | ||
148 | mulu.l %d7, %d4 | ||
149 | not.l %d4 | ||
150 | lsr.l %d6, %d4 | ||
151 | |||
152 | move.w %d4, (%a3) /* write first pixel block to LCD */ | ||
153 | |||
154 | move.l %d1, %d5 /* calculate second pixel block */ | ||
155 | and.l #0x80808080, %d5 | ||
156 | eor.l %d5, %d1 | ||
157 | lsr.l #1, %d5 | ||
158 | mulu.l %d7, %d5 | ||
159 | not.l %d5 | ||
160 | lsr.l %d6, %d5 | ||
161 | |||
162 | move.l %d2, %d4 /* calculate third pixel block */ | ||
163 | and.l #0x80808080, %d4 | ||
164 | eor.l %d4, %d2 | ||
165 | lsr.l #1, %d4 | ||
166 | mulu.l %d7, %d4 | ||
167 | not.l %d4 | ||
168 | lsr.l %d6, %d4 | ||
169 | |||
170 | move.w %d5, (%a3) /* write second pixel block to LCD */ | ||
171 | |||
172 | movem.l (%a0), %d5/%a4-%a6 /* fetch 4 blocks of 4 pixel values each */ | ||
173 | lea.l (16, %a0), %a0 | ||
174 | |||
175 | move.w %d4, (%a3) /* write third pixel block to LCD */ | ||
176 | |||
177 | move.l %d3, %d4 /* calculate fourth pixel block */ | ||
178 | and.l #0x80808080, %d4 | ||
179 | eor.l %d4, %d3 | ||
180 | lsr.l #1, %d4 | ||
181 | mulu.l %d7, %d4 | ||
182 | not.l %d4 | ||
183 | lsr.l %d6, %d4 | ||
184 | |||
185 | add.l %d5, %d0 /* calculate 4*4 new pixel phases */ | ||
186 | add.l %a4, %d1 /* (packed addition) */ | ||
187 | add.l %a5, %d2 | ||
188 | add.l %a6, %d3 | ||
189 | |||
190 | movem.l %d0-%d3, (%a1) /* store 4*4 new pixel phases */ | ||
191 | lea.l (16, %a1), %a1 | ||
192 | |||
193 | move.w %d4, (%a3) /* write fourth pixel block to LCD */ | ||
194 | |||
195 | cmp.l %a1, %a2 /* go up to last line bound */ | ||
196 | bhi.s .g_lloop | ||
197 | |||
198 | .g_lend: | ||
199 | lea.l (12, %a2), %a2 | ||
200 | cmp.l %a1, %a2 | ||
201 | bls.s .g_tend | ||
202 | |||
203 | .g_tloop: | ||
204 | move.l (%a1), %d0 /* fetch 4 pixel phases */ | ||
205 | |||
206 | move.l %d0, %d1 | ||
207 | and.l #0x80808080, %d1 | ||
208 | eor.l %d1, %d0 | ||
209 | add.l (%a0)+, %d0 /* add 4 pixel values to the phases */ | ||
210 | move.l %d0, (%a1)+ /* store new phases, advance pointer */ | ||
211 | |||
212 | lsr.l #1, %d1 | ||
213 | mulu.l %d7, %d1 | ||
214 | not.l %d1 | ||
215 | lsr.l %d6, %d1 | ||
216 | move.w %d1, (%a3) /* write pixel block */ | ||
217 | |||
218 | cmp.l %a1, %a2 /* go up to end address */ | ||
219 | bhi.s .g_tloop | ||
220 | |||
221 | .g_tend: | ||
222 | movem.l (%sp), %d2-%d7/%a2-%a6 /* restore registers */ | ||
223 | lea.l (11*4, %sp), %sp | ||
224 | rts | ||
225 | |||
226 | .gd_end: | ||
227 | .size lcd_grey_data,.gd_end-lcd_grey_data | ||
diff --git a/firmware/target/coldfire/mpio/hd300/lcd-hd300.c b/firmware/target/coldfire/mpio/hd300/lcd-hd300.c new file mode 100644 index 0000000000..10ee59571e --- /dev/null +++ b/firmware/target/coldfire/mpio/hd300/lcd-hd300.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Adopted for MPIO HD300 by Marcin Bukat | ||
11 | * Copyright (C) 2007 by Jens Arnold | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | #include "config.h" | ||
23 | |||
24 | #include "system.h" | ||
25 | #include "kernel.h" | ||
26 | #include "lcd.h" | ||
27 | |||
28 | /*** definitions ***/ | ||
29 | |||
30 | /* LCD command codes */ | ||
31 | #define LCD_CNTL_POWER_CONTROL 0x25 | ||
32 | #define LCD_CNTL_VOLTAGE_SELECT 0x2b | ||
33 | #define LCD_CNTL_LINE_INVERT_DRIVE 0x36 | ||
34 | #define LCD_CNTL_GRAY_SCALE_PATTERN 0x39 | ||
35 | #define LCD_CNTL_TEMP_GRADIENT_SELECT 0x4e | ||
36 | #define LCD_CNTL_OSC_FREQUENCY 0x5f | ||
37 | #define LCD_CNTL_ON_OFF 0xae | ||
38 | #define LCD_CNTL_OSC_ON_OFF 0xaa | ||
39 | #define LCD_CNTL_OFF_MODE 0xbe | ||
40 | #define LCD_CNTL_POWER_SAVE 0xa8 | ||
41 | #define LCD_CNTL_REVERSE 0xa6 | ||
42 | #define LCD_CNTL_ALL_LIGHTING 0xa4 | ||
43 | #define LCD_CNTL_COMMON_OUTPUT_STATUS 0xc4 | ||
44 | #define LCD_CNTL_COLUMN_ADDRESS_DIR 0xa0 | ||
45 | #define LCD_CNTL_NLINE_ON_OFF 0xe4 | ||
46 | #define LCD_CNTL_DISPLAY_MODE 0x66 | ||
47 | #define LCD_CNTL_DUTY_SET 0x6d | ||
48 | #define LCD_CNTL_ELECTRONIC_VOLUME 0x81 | ||
49 | #define LCD_CNTL_DATA_INPUT_DIR 0x84 | ||
50 | #define LCD_CNTL_DISPLAY_START_LINE 0x8a | ||
51 | #define LCD_CNTL_AREA_SCROLL 0x10 | ||
52 | |||
53 | #define LCD_CNTL_PAGE 0xb1 | ||
54 | #define LCD_CNTL_COLUMN 0x13 | ||
55 | #define LCD_CNTL_DATA_WRITE 0x1d | ||
56 | |||
57 | /*** shared semi-private declarations ***/ | ||
58 | extern const unsigned char lcd_dibits[16] ICONST_ATTR; | ||
59 | |||
60 | /*** hardware configuration ***/ | ||
61 | int lcd_default_contrast(void) | ||
62 | { | ||
63 | return DEFAULT_CONTRAST_SETTING; | ||
64 | } | ||
65 | |||
66 | void lcd_set_contrast(int val) | ||
67 | { | ||
68 | /* Keep val in acceptable hw range */ | ||
69 | if (val < 0) | ||
70 | val = 0; | ||
71 | else if (val > 127) | ||
72 | val = 127; | ||
73 | |||
74 | lcd_write_command_ex(LCD_CNTL_ELECTRONIC_VOLUME, val, -1); | ||
75 | } | ||
76 | |||
77 | void lcd_set_invert_display(bool yesno) | ||
78 | { | ||
79 | lcd_write_command(LCD_CNTL_REVERSE | (yesno?1:0)); | ||
80 | } | ||
81 | |||
82 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
83 | void lcd_set_flip(bool yesno) | ||
84 | { | ||
85 | if (yesno) | ||
86 | { | ||
87 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 1); | ||
88 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 0); | ||
89 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 0); | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); | ||
94 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); | ||
95 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | void lcd_init_device(void) | ||
100 | { | ||
101 | and_l(~0x00000800, &GPIO_FUNCTION); /* CS3 line */ | ||
102 | |||
103 | /* LCD Reset GPO34 */ | ||
104 | or_l(0x00000004, &GPIO1_ENABLE); /* set as output */ | ||
105 | or_l(0x00000004, &GPIO1_FUNCTION); /* switch to secondary function - GPIO */ | ||
106 | |||
107 | and_l(~0x00000004, &GPIO1_OUT); /* RESET low */ | ||
108 | sleep(1); /* delay at least 1000 ns */ | ||
109 | or_l(0x00000004, &GPIO1_OUT); /* RESET high */ | ||
110 | sleep(1); | ||
111 | |||
112 | lcd_write_command(LCD_CNTL_ON_OFF | 1); /* LCD ON */ | ||
113 | lcd_write_command(LCD_CNTL_OFF_MODE | 1); /* OFF -> VCC on drivers */ | ||
114 | lcd_write_command(LCD_CNTL_REVERSE | 0); /* Reverse OFF */ | ||
115 | lcd_write_command(LCD_CNTL_ALL_LIGHTING | 0); /* Normal */ | ||
116 | lcd_write_command(LCD_CNTL_COMMON_OUTPUT_STATUS | 1); /* Reverse dir */ | ||
117 | lcd_write_command_ex(LCD_CNTL_DISPLAY_START_LINE, 0, -1); | ||
118 | lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); /* Normal */ | ||
119 | lcd_write_command_ex(LCD_CNTL_DISPLAY_MODE, 0, -1); /* Greyscale mode */ | ||
120 | lcd_write_command_ex(LCD_CNTL_GRAY_SCALE_PATTERN, 0x53, -1); | ||
121 | lcd_write_command_ex(LCD_CNTL_DUTY_SET, 0x20, 1); | ||
122 | lcd_write_command_ex(LCD_CNTL_ELECTRONIC_VOLUME, 24, -1); /* 0x18 */ | ||
123 | |||
124 | lcd_write_command(LCD_CNTL_OSC_ON_OFF | 1); /* Oscillator ON */ | ||
125 | lcd_write_command(LCD_CNTL_POWER_SAVE | 0); | ||
126 | lcd_write_command_ex(LCD_CNTL_VOLTAGE_SELECT, 3, -1); | ||
127 | lcd_write_command_ex(LCD_CNTL_POWER_CONTROL, 0x17, -1); | ||
128 | lcd_write_command_ex(LCD_CNTL_OSC_FREQUENCY, 3, -1); | ||
129 | lcd_write_command(LCD_CNTL_NLINE_ON_OFF | 1); /* N-line ON */ | ||
130 | lcd_write_command_ex(LCD_CNTL_LINE_INVERT_DRIVE, 0x10, -1); | ||
131 | lcd_write_command_ex(LCD_CNTL_TEMP_GRADIENT_SELECT, 0, -1); | ||
132 | |||
133 | lcd_update(); | ||
134 | } | ||
135 | |||
136 | /*** update functions ***/ | ||
137 | |||
138 | /* Performance function that works with an external buffer | ||
139 | note that by and bheight are in 8-pixel units! */ | ||
140 | void lcd_blit_mono(const unsigned char *data, int x, int by, int width, | ||
141 | int bheight, int stride) | ||
142 | { | ||
143 | const unsigned char *src, *src_end; | ||
144 | unsigned char *dst_u, *dst_l; | ||
145 | static unsigned char upper[LCD_WIDTH] IBSS_ATTR; | ||
146 | static unsigned char lower[LCD_WIDTH] IBSS_ATTR; | ||
147 | unsigned int byte; | ||
148 | |||
149 | by *= 2; | ||
150 | |||
151 | while (bheight--) | ||
152 | { | ||
153 | src = data; | ||
154 | src_end = data + width; | ||
155 | dst_u = upper; | ||
156 | dst_l = lower; | ||
157 | do | ||
158 | { | ||
159 | byte = *src++; | ||
160 | *dst_u++ = lcd_dibits[byte & 0x0F]; | ||
161 | byte >>= 4; | ||
162 | *dst_l++ = lcd_dibits[byte & 0x0F]; | ||
163 | } | ||
164 | while (src < src_end); | ||
165 | |||
166 | lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); | ||
167 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); | ||
168 | lcd_write_command(LCD_CNTL_DATA_WRITE); | ||
169 | lcd_write_data(upper, width); | ||
170 | |||
171 | lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); | ||
172 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); | ||
173 | lcd_write_command(LCD_CNTL_DATA_WRITE); | ||
174 | lcd_write_data(lower, width); | ||
175 | |||
176 | data += stride; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* Helper function for lcd_grey_phase_blit(). */ | ||
181 | void lcd_grey_data(unsigned char *values, unsigned char *phases, int count); | ||
182 | |||
183 | /* Performance function that works with an external buffer | ||
184 | note that by and bheight are in 4-pixel units! */ | ||
185 | void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, | ||
186 | int x, int by, 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(values, phases, width); | ||
195 | values += stride; | ||
196 | phases += stride; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /* Update the display. | ||
201 | This must be called after all other LCD functions that change the display. */ | ||
202 | void lcd_update(void) ICODE_ATTR; | ||
203 | void lcd_update(void) | ||
204 | { | ||
205 | int y; | ||
206 | |||
207 | /* Copy display bitmap to hardware */ | ||
208 | for (y = 0; y < LCD_FBHEIGHT; y++) | ||
209 | { | ||
210 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); | ||
211 | lcd_write_command_ex(LCD_CNTL_COLUMN, 0, -1); | ||
212 | |||
213 | lcd_write_command(LCD_CNTL_DATA_WRITE); | ||
214 | lcd_write_data (lcd_framebuffer[y], LCD_WIDTH); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | /* Update a fraction of the display. */ | ||
219 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | ||
220 | void lcd_update_rect(int x, int y, int width, int height) | ||
221 | { | ||
222 | int ymax; | ||
223 | |||
224 | /* The Y coordinates have to work on even 8 pixel rows */ | ||
225 | ymax = (y + height-1) >> 2; | ||
226 | y >>= 2; | ||
227 | |||
228 | if(x + width > LCD_WIDTH) | ||
229 | width = LCD_WIDTH - x; | ||
230 | if (width <= 0) | ||
231 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | ||
232 | if(ymax >= LCD_FBHEIGHT) | ||
233 | ymax = LCD_FBHEIGHT-1; | ||
234 | |||
235 | /* Copy specified rectange bitmap to hardware */ | ||
236 | for (; y <= ymax; y++) | ||
237 | { | ||
238 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); | ||
239 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); | ||
240 | |||
241 | lcd_write_command(LCD_CNTL_DATA_WRITE); | ||
242 | lcd_write_data (&lcd_framebuffer[y][x], width); | ||
243 | } | ||
244 | } | ||
diff --git a/firmware/target/coldfire/mpio/hd300/powermgmt-hd300.c b/firmware/target/coldfire/mpio/hd300/powermgmt-hd300.c new file mode 100644 index 0000000000..9d95938ff9 --- /dev/null +++ b/firmware/target/coldfire/mpio/hd300/powermgmt-hd300.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Marcin Bukat | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "adc.h" | ||
24 | #include "powermgmt.h" | ||
25 | |||
26 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = | ||
27 | { | ||
28 | 3600 | ||
29 | }; | ||
30 | |||
31 | const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = | ||
32 | { | ||
33 | 3500 | ||
34 | }; | ||
35 | |||
36 | /* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ | ||
37 | const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = | ||
38 | { | ||
39 | { 3500, 3566, 3597, 3619, 3644, 3676, 3732, 3806, 3868, 3937, 4004 } | ||
40 | }; | ||
41 | |||
42 | /* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ | ||
43 | const unsigned short percent_to_volt_charge[11] = | ||
44 | { | ||
45 | /* values measured over one full charging cycle */ | ||
46 | 3386, 3872, 3904, 3942, 3996, 4029, 4033, 4036, 4038, 4039, 4041 | ||
47 | }; | ||
48 | |||
49 | /* 3.33V as reference */ | ||
50 | #define BATTERY_SCALE_FACTOR 3330 | ||
51 | |||
52 | |||
53 | /* Returns battery voltage from ADC [millivolts] */ | ||
54 | unsigned int battery_adc_voltage(void) | ||
55 | { | ||
56 | return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 11; | ||
57 | } | ||
58 | |||