Fix last sprintf warning.
[kugel-rb.git] / firmware / target / arm / tms320dm320 / creative-zvm / pic-creativezvm.c
blobd910eeb3b6d61fd13e005ce439800ac26b2fe226
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * Creative Zen Vision:M interrupt based PIC driver
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #include <stdio.h>
25 #include "config.h"
26 #include "system.h"
27 #include "kernel.h"
28 #include "button-target.h"
29 #include "i2c-dm320.h"
30 #include "logf.h"
32 #ifdef BUTTON_DEBUG
33 #include "lcd-target.h"
34 #include "lcd.h"
35 #include "font.h"
36 #endif
38 #ifndef ZEN_VISION
39 /* Creative Zen Vision:M */
40 #define BTN_LEFT 0xAF00
41 #define BTN_RIGHT 0xA700
42 #define BTN_BACK 0xDF00
43 #define BTN_CUSTOM 0xC700
44 #define BTN_PLAY 0x9700
45 #define BTN_POWER 0x8700
46 #define BTN_MENU 0xCF00
47 #define BTN_HOLD 0xCF07
48 #define BTN_UNHOLD 0xD707
50 #define BTN_REL 1
52 #define BTN_TOUCHPAD_PRESS 0x8F00
53 #define BTN_TOUCHPAD_SCROLL_DOWN 0x0F03
54 #define BTN_TOUCHPAD_CORNER_DOWN 0xD700
55 #define BTN_TOUCHPAD_CORNER_UP 0x9F00
56 #define BTN_TOUCHPAD_SCROLL_UP 0x0F04
58 #define HEADPHONE_PLUGIN_A 0x5707
59 #define HEADPHONE_PLUGIN_B 0x5F07
60 #define HEADPHONE_UNPLUG_A 0x3707
61 #define HEADPHONE_UNPLUG_B 0x3F07
63 #define DOCK_INSERT 0x6707
64 #define DOCK_UNPLUG 0xDF06
65 #define DOCK_USB_INSERT 0x2F06
66 #define DOCK_USB_UNPLUG 0x3F06
67 #define DOCK_POWER_INSERT 0x1707
68 #define DOCK_POWER_UNPLUG 0x1F07
70 #else
71 /* Creative Zen Vision */
72 #define BTN_LEFT 0xCF00
73 #define BTN_RIGHT 0xEF00
74 #define BTN_BACK 0xBF00
75 #define BTN_CUSTOM 0x0
76 #define BTN_PLAY 0x2F00
77 #define BTN_POWER 0x0F00
78 #define BTN_MENU 0x9F00
79 #define BTN_HOLD 0x9F06
80 #define BTN_UNHOLD 0xAF06
83 /* TODO: other values
85 First number is just pressing it, second is when you release it or keep it
86 pressed a bit longer
88 On/Off = 0F00 && 0F01
89 Hold = 9F06 && AF06
90 Volume Up = 6F00 && 6F01
91 Vol Down = 7F00 && 7F01
92 Up = DF00 && DF01
93 Right = EF00 && EF01
94 Down = FF00 && FF01
95 Left = CF00 && CF01
96 Back = BF00 && BF01
97 Menu = 9F00 && Etcetera
98 Ok = 1F00
99 Play = 2F00
100 Next = 4F00
101 Prev = 5F00
103 USB = 2F06
104 USB ouot = 3F06
105 Headphones= AF06
106 Hdphns out= BF06
107 Charger = 4F06 -> 9F05
108 Chgrout = 5F06 -> 8F05
109 AV in = 8F06
110 AV out = 9F06 */
112 #define BTN_REL 1
114 #define BTN_TOUCHPAD_PRESS 0x1F00
115 #define BTN_TOUCHPAD_LONG_PRESS 0x1F01
116 #define BTN_TOUCHPAD_CORNER_DOWN 0xFF00
117 #define BTN_TOUCHPAD_SCROLL_DOWN 0xFF01
118 #define BTN_TOUCHPAD_CORNER_UP 0xDF00
119 #define BTN_TOUCHPAD_SCROLL_UP 0xDF01
121 #define HEADPHONE_PLUGIN_A 0xAF06
122 #define HEADPHONE_PLUGIN_B 0x00AF06 //Dummy Value
123 #define HEADPHONE_UNPLUG_A 0x00BF06 //Dummy Value
124 #define HEADPHONE_UNPLUG_B 0x00BF061 //Dummy Value
126 #define DOCK_INSERT 0x00003 //Dummy Value
127 #define DOCK_UNPLUG 0x00002 //Dummy Value
128 #define DOCK_USB_INSERT 0x2F06
129 #define DOCK_USB_UNPLUG 0x3F06
130 #define DOCK_POWER_INSERT 0x4F06
131 #define DOCK_POWER_UNPLUG 0x5F06
132 #define DOCK_AV_INSERT 0x8F06
133 #define DOCK_AV_UNPLUG 0x9F06
134 #endif
136 #define PIC_ADR 0x07
138 #define MASK_TV_OUT(x) ((x >> 14) & 1)
139 #define MASK_xx1(x) ((x >> 9) & 3)
140 #define MASK_xx2(x) ((x >> 4) & 1)
141 #define MASK_xx3(x) ((x >> 5) & 1)
142 #define MASK_xx4(x) ((x >> 6) & 1)
143 #define MASK_xx5(x) ((x >> 13) & 1)
144 #define MASK_xx6(x) ((x >> 12) & 1)
145 #define MASK_xx7(x) ((x >> 11) & 1)
147 #define NONBUTTON_HEADPHONE (1 << 0)
148 #define NONBUTTON_DOCK (1 << 1)
149 #define NONBUTTON_USB (1 << 2)
150 #define NONBUTTON_POWER (1 << 3)
151 #define NONBUTTON_VIDEOUT (1 << 4)
153 static unsigned int btn;
154 static bool hold_switch;
155 static unsigned char nonbtn;
156 static unsigned int pic_init_value;
157 static unsigned int pic_init2_value;
158 static unsigned int last_btn;
159 static long last_tick;
160 static int tick_diff;
162 #define TICK_MIN 0x33
163 #define TICK_MAX 0x34
165 /* Taken from scramble.c and modified */
166 static inline unsigned short le2short(unsigned char* buf)
168 return (unsigned short)((buf[1] << 8) | buf[0]);
171 #define map_button(BtN,BtN2) case BtN: \
172 btn ^= BtN2; \
173 btn &= BtN2; \
174 break; \
175 case BtN ^ BTN_REL: \
176 btn ^= BtN2; \
177 btn &= BtN2; \
178 break;
180 #ifdef BUTTON_DEBUG
181 static bool sw = false;
182 #endif
184 void GIO0(void)
186 /* Mask GIO0 interrupt */
187 IO_INTC_IRQ1 = INTR_IRQ1_EXT0;
189 unsigned char msg[4];
190 i2c_read(PIC_ADR, msg, sizeof(msg));
191 tick_diff = current_tick - last_tick;
192 last_tick = current_tick;
193 unsigned short btn_press = le2short(msg);
194 if(tick_diff >= TICK_MIN && tick_diff <= TICK_MAX)
196 /* Ignore this, as it is a hold event */
197 return;
199 last_btn = btn_press;
200 switch(btn_press)
202 map_button(BTN_LEFT, BUTTON_LEFT);
203 map_button(BTN_RIGHT, BUTTON_RIGHT);
204 map_button(BTN_BACK, BUTTON_BACK);
205 map_button(BTN_CUSTOM, BUTTON_CUSTOM);
206 map_button(BTN_MENU, BUTTON_MENU);
207 map_button(BTN_PLAY, BUTTON_PLAY);
208 map_button(BTN_POWER, BUTTON_POWER);
209 map_button(BTN_TOUCHPAD_PRESS, BUTTON_SELECT);
210 map_button(BTN_TOUCHPAD_CORNER_DOWN, BUTTON_DOWN);
211 map_button(BTN_TOUCHPAD_CORNER_UP, BUTTON_UP);
212 #ifndef ZEN_VISION
213 /* These don't seem to work for some reason on the Zen Vision.. */
214 case BTN_TOUCHPAD_SCROLL_DOWN:
215 btn = BUTTON_DOWN;
216 break;
217 case BTN_TOUCHPAD_SCROLL_UP:
218 btn = BUTTON_UP;
219 break;
220 #endif
221 case BTN_HOLD:
222 hold_switch = true;
223 break;
224 case BTN_UNHOLD:
225 hold_switch = false;
226 break;
227 #ifndef ZEN_VISION
228 /* These don't seem to work for some reason.. */
229 case HEADPHONE_PLUGIN_A:
230 case HEADPHONE_PLUGIN_B:
231 nonbtn |= NONBUTTON_HEADPHONE;
232 break;
233 case HEADPHONE_UNPLUG_A:
234 case HEADPHONE_UNPLUG_B:
235 nonbtn &= ~NONBUTTON_HEADPHONE;
236 break;
237 #endif
238 case DOCK_INSERT:
239 nonbtn |= NONBUTTON_DOCK;
240 break;
241 case DOCK_UNPLUG:
242 nonbtn &= ~(NONBUTTON_DOCK | NONBUTTON_USB | NONBUTTON_POWER);
243 break;
244 case DOCK_USB_INSERT:
245 nonbtn |= NONBUTTON_USB;
246 break;
247 case DOCK_USB_UNPLUG:
248 nonbtn &= ~NONBUTTON_USB;
249 break;
250 case DOCK_POWER_INSERT:
251 nonbtn |= NONBUTTON_POWER;
252 break;
253 case DOCK_POWER_UNPLUG:
254 nonbtn &= ~NONBUTTON_POWER;
255 break;
257 #ifdef BUTTON_DEBUG
258 unsigned char weergvn[10];
259 #ifdef BOOTLOADER
260 lcd_set_foreground((sw ? LCD_RGBPACK(255,0,0) : LCD_RGBPACK(0,255,0) ));
261 #endif
262 snprintf(weergvn, sizeof(char)*10, "%x",
263 (unsigned int)((msg[3] << 24) |
264 (msg[2] << 16) | (msg[1] << 8) | msg[0]));
265 lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*10,
266 weergvn);
267 snprintf(weergvn, sizeof(char)*10, "%x", btn);
268 lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*7,
269 weergvn);
270 #ifdef BOOTLOADER
271 lcd_set_foreground(LCD_BLACK);
272 #endif
273 lcd_update();
274 sw = !sw;
275 #endif
276 logf("PIC: 0x%x", (unsigned int)((msg[3] << 24) |
277 (msg[2] << 16) | (msg[1] << 8) | msg[0]));
280 static void send_command_to_pic(const unsigned char in, unsigned char* out,
281 const unsigned int length)
283 /* Disable GIO0 interrupt */
284 IO_INTC_EINT1 &= ~INTR_EINT1_EXT0;
285 /* Clear EXT0 interrupt */
286 IO_INTC_IRQ1 = INTR_IRQ1_EXT0;
287 /* Write command to I²C */
288 restart:
289 i2c_write(PIC_ADR, &in, 1);
290 /* Wait for PIC */
291 int i = 0;
292 while(!(IO_INTC_IRQ1 & INTR_IRQ1_EXT0))
294 sleep(0);
295 i++;
296 if(i > 50)
297 goto restart;
299 /* Read return from I²C */
300 i2c_read(PIC_ADR, out, length);
301 /* Re-enable GIO0 interrupt */
302 IO_INTC_EINT1 |= INTR_EINT1_EXT0;
305 bool headphones_inserted(void)
307 return (bool)(nonbtn & NONBUTTON_HEADPHONE);
310 void button_init_device(void)
312 /* TODO: I suppose GIO0 has to be set to input and enable interrupts on
313 it? */
314 /* Enable GIO0 interrupt */
315 IO_INTC_EINT1 |= INTR_EINT1_EXT0;
316 btn=nonbtn=pic_init_value=pic_init2_value=last_btn=hold_switch=0;
317 /* Initialize PIC */
318 send_command_to_pic(1, (unsigned char *)&pic_init_value,
319 sizeof(pic_init_value));
320 send_command_to_pic(2, (unsigned char *)&pic_init2_value,
321 sizeof(pic_init2_value));
324 int button_read_device(void)
326 if(hold_switch)
327 return 0;
328 else
329 return btn;
332 bool button_hold(void)
334 return hold_switch;
337 bool button_usb_connected(void)
339 return (bool)(nonbtn & NONBUTTON_USB);
342 #ifndef BOOTLOADER
343 int pic_dbg_num_items(void)
345 return 13;
348 const char* pic_dbg_item(int selected_item, void *data,
349 char *buffer, size_t buffer_len)
351 (void)data;
352 switch(selected_item)
354 case 0:
355 snprintf(buffer, buffer_len, "Init value 1: 0x%04x", pic_init_value);
356 return buffer;
357 case 1:
358 snprintf(buffer, buffer_len, "Init value 2: 0x%04x", pic_init2_value);
359 return buffer;
360 case 2:
361 snprintf(buffer, buffer_len, "Last button value: 0x%04x Raw value: 0x%04x", last_btn, btn);
362 return buffer;
363 case 3:
364 snprintf(buffer, buffer_len, "Last button differs in ticks: 0x%04x", tick_diff);
365 return buffer;
366 case 4:
367 snprintf(buffer, buffer_len, "Dock values: 0x%04x", nonbtn);
368 return buffer;
369 #define B(n,w,b) case n: \
370 snprintf(buffer, buffer_len, "%s: 0x%04x", w, b); \
371 return buffer;
372 B(5, "MASK_TV_OUT", MASK_TV_OUT(pic_init_value));
373 B(6, "MASK_xx1", MASK_xx1(pic_init_value));
374 B(7, "MASK_xx2", MASK_xx2(pic_init_value));
375 B(8, "MASK_xx3", MASK_xx3(pic_init_value));
376 B(9, "MASK_xx4", MASK_xx4(pic_init_value));
377 B(10, "MASK_xx5", MASK_xx5(pic_init_value));
378 B(11, "MASK_xx6", MASK_xx6(pic_init_value));
379 B(12, "MASK_xx7", MASK_xx7(pic_init_value));
380 #undef B
382 return NULL;
384 #endif