diff options
Diffstat (limited to 'firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c')
-rw-r--r-- | firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c new file mode 100644 index 0000000000..35e6bd31fb --- /dev/null +++ b/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * Creative Zen Vision:M interrupt based PIC driver | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
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 "system.h" | ||
24 | #include "kernel.h" | ||
25 | #include "button-target.h" | ||
26 | #include "i2c-dm320.h" | ||
27 | |||
28 | |||
29 | #include "lcd-target.h" | ||
30 | #include "lcd.h" | ||
31 | #include "sprintf.h" | ||
32 | #include "font.h" | ||
33 | |||
34 | #ifndef ZEN_VISION | ||
35 | /* Creative Zen Vision:M */ | ||
36 | #define BTN_LEFT 0x5F00 | ||
37 | #define BTN_RIGHT 0x4F00 | ||
38 | #define BTN_BACK 0xBF00 | ||
39 | #define BTN_CUSTOM 0x8F00 | ||
40 | #define BTN_PLAY 0x2F00 | ||
41 | #define BTN_POWER 0x0F00 | ||
42 | #define BTN_MENU 0x9F00 | ||
43 | #define BTN_HOLD 0x9F06 | ||
44 | #define BTN_UNHOLD 0xAF06 | ||
45 | |||
46 | #define BTN_REL 1 | ||
47 | |||
48 | #define BTN_TOUCHPAD_PRESS 0x1F00 | ||
49 | #define BTN_TOUCHPAD_CORNER_DOWN 0xAF00 | ||
50 | #define BTN_TOUCHPAD_CORNER_UP 0x3F00 | ||
51 | |||
52 | #define HEADPHONE_PLUGIN_A 0x5707 | ||
53 | #define HEADPHONE_PLUGIN_B 0x5F07 | ||
54 | #define HEADPHONE_UNPLUG_A 0x3707 | ||
55 | #define HEADPHONE_UNPLUG_B 0x3F07 | ||
56 | |||
57 | #define DOCK_INSERT 0x6707 | ||
58 | #define DOCK_UNPLUG 0xDF06 | ||
59 | #define DOCK_USB_INSERT 0x2F06 | ||
60 | #define DOCK_USB_UNPLUG 0x3F06 | ||
61 | #define DOCK_POWER_INSERT 0x2707 | ||
62 | #define DOCK_POWER_UNPLUG 0x2F07 | ||
63 | |||
64 | #else | ||
65 | /* Creative Zen Vision */ | ||
66 | #define BTN_LEFT 0xCF00 | ||
67 | #define BTN_RIGHT 0xEF00 | ||
68 | #define BTN_BACK 0xBF00 | ||
69 | #define BTN_CUSTOM 0x0 | ||
70 | #define BTN_PLAY 0x2F00 | ||
71 | #define BTN_POWER 0x0F00 | ||
72 | #define BTN_MENU 0x9F00 | ||
73 | #define BTN_HOLD 0x9F06 | ||
74 | #define BTN_UNHOLD 0xAF06 | ||
75 | /* TODO: other values | ||
76 | First number is just pressing it, second is when you release it or keep it pressed a bit longer | ||
77 | On/Off = 0F00 && 0F01 | ||
78 | Hold = 9F06 && AF06 | ||
79 | Volume Up = 6F00 && 6F01 | ||
80 | Vol Down = 7F00 && 7F01 | ||
81 | Up = DF00 && DF01 | ||
82 | Right = EF00 && EF01 | ||
83 | Down = FF00 && FF01 | ||
84 | Left = CF00 && CF01 | ||
85 | Back = BF00 && BF01 | ||
86 | Menu = 9F00 && Etcetera | ||
87 | Ok = 1F00 | ||
88 | Play = 2F00 | ||
89 | Next = 4F00 | ||
90 | Prev = 5F00 | ||
91 | |||
92 | USB = 2F06 | ||
93 | USB ouot = 3F06 | ||
94 | Headphones= AF06 | ||
95 | Hdphns out= BF06 | ||
96 | Charger = 4F06 -> 9F05 | ||
97 | Chgrout = 5F06 -> 8F05 | ||
98 | AV in = 8F06 | ||
99 | AV out = 9F06 */ | ||
100 | |||
101 | #define BTN_REL 1 | ||
102 | |||
103 | #define BTN_TOUCHPAD_PRESS 0x8F00 | ||
104 | #define BTN_TOUCHPAD_LONG_PRESS 0x0F00 | ||
105 | #define BTN_TOUCHPAD_CORNER_DOWN 0xD700 | ||
106 | #define BTN_TOUCHPAD_CORNER_LONG_DOWN 0x5700 | ||
107 | #define BTN_TOUCHPAD_CORNER_UP 0x9F00 | ||
108 | #define BTN_TOUCHPAD_CORNER_LONG_UP 0x1F00 | ||
109 | |||
110 | #define HEADPHONE_PLUGIN_A 0xAF06 | ||
111 | #define HEADPHONE_PLUGIN_B 0xAF06 | ||
112 | #define HEADPHONE_UNPLUG_A 0xBF06 | ||
113 | #define HEADPHONE_UNPLUG_B 0xBF06 | ||
114 | |||
115 | #define DOCK_INSERT 0x0 | ||
116 | #define DOCK_UNPLUG 0x0 | ||
117 | #define DOCK_USB_INSERT 0x2F06 | ||
118 | #define DOCK_USB_UNPLUG_A 0x3F06 | ||
119 | #define DOCK_USB_UNPLUG_B 0x3F06 | ||
120 | #define DOCK_POWER_INSERT 0x4F06 | ||
121 | #define DOCK_POWER_UNPLUG 0x5F06 | ||
122 | #define DOCK_AV_INSERT 0x8F06 | ||
123 | #define DOCK_AV_UNPLUG 0x9F06 | ||
124 | #endif | ||
125 | |||
126 | #define PIC_ADR 0x07 | ||
127 | |||
128 | #define MASK_TV_OUT(x) ((x >> 14) & 1) | ||
129 | #define MASK_xx1(x) ((x >> 9) & 3) | ||
130 | #define MASK_xx2(x) ((x >> 4) & 1) | ||
131 | #define MASK_xx3(x) ((x >> 5) & 1) | ||
132 | #define MASK_xx4(x) ((x >> 6) & 1) | ||
133 | #define MASK_xx5(x) ((x >> 13) & 1) | ||
134 | #define MASK_xx6(x) ((x >> 12) & 1) | ||
135 | #define MASK_xx7(x) ((x >> 11) & 1) | ||
136 | |||
137 | #define NONBUTTON_HEADPHONE (1 << 0) | ||
138 | #define NONBUTTON_DOCK (1 << 1) | ||
139 | #define NONBUTTON_USB (1 << 2) | ||
140 | #define NONBUTTON_POWER (1 << 3) | ||
141 | #define NONBUTTON_VIDEOUT (1 << 4) | ||
142 | |||
143 | static unsigned int btn; | ||
144 | static bool hold_switch; | ||
145 | static unsigned char nonbtn; | ||
146 | static unsigned int pic_init_value; | ||
147 | static unsigned int pic_init2_value; | ||
148 | static unsigned int last_btn; | ||
149 | static long last_tick; | ||
150 | static int tick_diff; | ||
151 | |||
152 | #define TICK_MIN 0x33 | ||
153 | #define TICK_MAX 0x34 | ||
154 | |||
155 | /* Taken from scramble.c and modified */ | ||
156 | static inline unsigned short le2short(unsigned char* buf) | ||
157 | { | ||
158 | return (unsigned short)((buf[1] << 8) | buf[0]); | ||
159 | } | ||
160 | |||
161 | #define map_button(BtN,BtN2) case BtN: \ | ||
162 | btn ^= BtN2; \ | ||
163 | btn &= BtN2; \ | ||
164 | break; \ | ||
165 | case BtN ^ BTN_REL: \ | ||
166 | btn ^= BtN2; \ | ||
167 | btn &= BtN2; \ | ||
168 | break; | ||
169 | |||
170 | #ifdef BUTTON_DEBUG | ||
171 | static bool sw = false; | ||
172 | #endif | ||
173 | |||
174 | void GIO0(void) | ||
175 | { | ||
176 | unsigned char msg[4]; | ||
177 | i2c_read(PIC_ADR, msg, sizeof(msg)); | ||
178 | tick_diff = current_tick - last_tick; | ||
179 | last_tick = current_tick; | ||
180 | unsigned short btn_press = le2short(msg); | ||
181 | if(tick_diff >= TICK_MIN && tick_diff <= TICK_MAX) | ||
182 | { | ||
183 | /* Ignore this, as it is a hold event */ | ||
184 | IO_INTC_IRQ1 = INTR_IRQ1_EXT0; | ||
185 | return; | ||
186 | } | ||
187 | last_btn = btn_press; | ||
188 | switch(btn_press) | ||
189 | { | ||
190 | map_button(BTN_LEFT, BUTTON_LEFT); | ||
191 | map_button(BTN_RIGHT, BUTTON_RIGHT); | ||
192 | map_button(BTN_BACK, BUTTON_BACK); | ||
193 | map_button(BTN_CUSTOM, BUTTON_CUSTOM); | ||
194 | map_button(BTN_MENU, BUTTON_MENU); | ||
195 | map_button(BTN_PLAY, BUTTON_PLAY); | ||
196 | map_button(BTN_POWER, BUTTON_POWER); | ||
197 | map_button(BTN_TOUCHPAD_PRESS, BUTTON_SELECT); | ||
198 | map_button(BTN_TOUCHPAD_CORNER_DOWN, BUTTON_DOWN); | ||
199 | map_button(BTN_TOUCHPAD_CORNER_UP, BUTTON_UP); | ||
200 | case BTN_HOLD: | ||
201 | hold_switch = true; | ||
202 | break; | ||
203 | case BTN_UNHOLD: | ||
204 | hold_switch = false; | ||
205 | break; | ||
206 | case HEADPHONE_PLUGIN_A: | ||
207 | case HEADPHONE_PLUGIN_B: | ||
208 | nonbtn |= NONBUTTON_HEADPHONE; | ||
209 | break; | ||
210 | case HEADPHONE_UNPLUG_A: | ||
211 | case HEADPHONE_UNPLUG_B: | ||
212 | nonbtn &= ~NONBUTTON_HEADPHONE; | ||
213 | break; | ||
214 | case DOCK_INSERT: | ||
215 | nonbtn |= NONBUTTON_DOCK; | ||
216 | break; | ||
217 | case DOCK_UNPLUG: | ||
218 | nonbtn &= ~(NONBUTTON_DOCK | NONBUTTON_USB | NONBUTTON_POWER); | ||
219 | break; | ||
220 | case DOCK_USB_INSERT: | ||
221 | nonbtn |= NONBUTTON_USB; | ||
222 | break; | ||
223 | case DOCK_USB_UNPLUG: | ||
224 | nonbtn &= ~NONBUTTON_USB; | ||
225 | break; | ||
226 | case DOCK_POWER_INSERT: | ||
227 | nonbtn |= NONBUTTON_POWER; | ||
228 | break; | ||
229 | case DOCK_POWER_UNPLUG: | ||
230 | nonbtn &= ~NONBUTTON_POWER; | ||
231 | break; | ||
232 | } | ||
233 | #ifdef BUTTON_DEBUG | ||
234 | unsigned char weergvn[10]; | ||
235 | #ifdef BOOTLOADER | ||
236 | lcd_set_foreground((sw ? LCD_RGBPACK(255,0,0) : LCD_RGBPACK(0,255,0) )); | ||
237 | #endif | ||
238 | snprintf(weergvn, sizeof(char)*10, "%x", (unsigned int)((msg[3] << 24) | (msg[2] << 16) | (msg[1] << 8) | msg[0])); | ||
239 | lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*10, weergvn); | ||
240 | snprintf(weergvn, sizeof(char)*10, "%x", btn); | ||
241 | lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*7, weergvn); | ||
242 | #ifdef BOOTLOADER | ||
243 | lcd_set_foreground(LCD_BLACK); | ||
244 | #endif | ||
245 | lcd_update(); | ||
246 | sw = !sw; | ||
247 | #endif | ||
248 | /* Mask GIO0 interrupt */ | ||
249 | IO_INTC_IRQ1 = INTR_IRQ1_EXT0; | ||
250 | } | ||
251 | |||
252 | void send_command_to_pic(unsigned char in, unsigned char* out, unsigned int length) | ||
253 | { | ||
254 | /* Disable GIO0 interrupt */ | ||
255 | IO_INTC_EINT1 &= ~INTR_EINT1_EXT0; | ||
256 | /* Clear EXT0 interrupt */ | ||
257 | IO_INTC_IRQ1 = INTR_IRQ1_EXT0; | ||
258 | /* Write command to I²C */ | ||
259 | restart: | ||
260 | i2c_write(PIC_ADR, &in, 1); | ||
261 | /* Wait for PIC */ | ||
262 | int i = 0; | ||
263 | while(!(IO_INTC_IRQ1 & INTR_IRQ1_EXT0)) | ||
264 | { | ||
265 | sleep(0); | ||
266 | i++; | ||
267 | if(i > 50) | ||
268 | goto restart; | ||
269 | } | ||
270 | /* Read return from I²C */ | ||
271 | i2c_read(PIC_ADR, out, length); | ||
272 | /* Re-enable GIO0 interrupt */ | ||
273 | IO_INTC_EINT1 |= INTR_EINT1_EXT0; | ||
274 | } | ||
275 | |||
276 | bool headphones_inserted(void) | ||
277 | { | ||
278 | return (bool)(nonbtn & NONBUTTON_HEADPHONE); | ||
279 | } | ||
280 | |||
281 | void button_init_device(void) | ||
282 | { | ||
283 | /* TODO: I suppose GIO0 has to be set to input and enable interrupts on it? */ | ||
284 | /* Enable GIO0 interrupt */ | ||
285 | IO_INTC_EINT1 |= INTR_EINT1_EXT0; | ||
286 | btn = nonbtn = pic_init_value = pic_init2_value = last_btn = hold_switch = 0; | ||
287 | /* Initialize PIC */ | ||
288 | send_command_to_pic(1, &pic_init_value, sizeof(pic_init_value)); | ||
289 | send_command_to_pic(2, &pic_init2_value, sizeof(pic_init2_value)); | ||
290 | } | ||
291 | |||
292 | int get_debug_info(int choice) | ||
293 | { | ||
294 | switch(choice) | ||
295 | { | ||
296 | case 1: | ||
297 | return pic_init_value; | ||
298 | case 2: | ||
299 | return pic_init2_value; | ||
300 | case 3: | ||
301 | return last_btn; | ||
302 | case 4: | ||
303 | return nonbtn; | ||
304 | case 5: | ||
305 | return tick_diff; | ||
306 | } | ||
307 | return -1; | ||
308 | } | ||
309 | |||
310 | int button_read_device(void) | ||
311 | { | ||
312 | return btn; | ||
313 | } | ||
314 | |||
315 | bool button_hold(void) | ||
316 | { | ||
317 | return hold_switch; | ||
318 | } | ||
319 | |||
320 | bool button_usb_connected(void) | ||
321 | { | ||
322 | return (bool)(nonbtn & NONBUTTON_USB); | ||
323 | } | ||