1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
28 #include "button-target.h"
29 #include "i2c-dm320.h"
33 #include "lcd-target.h"
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
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
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
85 First number is just pressing it, second is when you release it or keep it
90 Volume Up = 6F00 && 6F01
91 Vol Down = 7F00 && 7F01
97 Menu = 9F00 && Etcetera
107 Charger = 4F06 -> 9F05
108 Chgrout = 5F06 -> 8F05
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
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: \
175 case BtN ^ BTN_REL: \
181 static bool sw
= false;
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 */
199 last_btn
= 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
);
213 /* These don't seem to work for some reason on the Zen Vision.. */
214 case BTN_TOUCHPAD_SCROLL_DOWN
:
217 case BTN_TOUCHPAD_SCROLL_UP
:
228 /* These don't seem to work for some reason.. */
229 case HEADPHONE_PLUGIN_A
:
230 case HEADPHONE_PLUGIN_B
:
231 nonbtn
|= NONBUTTON_HEADPHONE
;
233 case HEADPHONE_UNPLUG_A
:
234 case HEADPHONE_UNPLUG_B
:
235 nonbtn
&= ~NONBUTTON_HEADPHONE
;
239 nonbtn
|= NONBUTTON_DOCK
;
242 nonbtn
&= ~(NONBUTTON_DOCK
| NONBUTTON_USB
| NONBUTTON_POWER
);
244 case DOCK_USB_INSERT
:
245 nonbtn
|= NONBUTTON_USB
;
247 case DOCK_USB_UNPLUG
:
248 nonbtn
&= ~NONBUTTON_USB
;
250 case DOCK_POWER_INSERT
:
251 nonbtn
|= NONBUTTON_POWER
;
253 case DOCK_POWER_UNPLUG
:
254 nonbtn
&= ~NONBUTTON_POWER
;
258 unsigned char weergvn
[10];
260 lcd_set_foreground((sw
? LCD_RGBPACK(255,0,0) : LCD_RGBPACK(0,255,0) ));
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,
267 snprintf(weergvn
, sizeof(char)*10, "%x", btn
);
268 lcd_putsxy(LCD_WIDTH
-SYSFONT_WIDTH
*10, LCD_HEIGHT
-SYSFONT_HEIGHT
*7,
271 lcd_set_foreground(LCD_BLACK
);
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 */
289 i2c_write(PIC_ADR
, &in
, 1);
292 while(!(IO_INTC_IRQ1
& INTR_IRQ1_EXT0
))
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
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;
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)
332 bool button_hold(void)
337 bool button_usb_connected(void)
339 return (bool)(nonbtn
& NONBUTTON_USB
);
343 int pic_dbg_num_items(void)
348 const char* pic_dbg_item(int selected_item
, void *data
,
349 char *buffer
, size_t buffer_len
)
352 switch(selected_item
)
355 snprintf(buffer
, buffer_len
, "Init value 1: 0x%04x", pic_init_value
);
358 snprintf(buffer
, buffer_len
, "Init value 2: 0x%04x", pic_init2_value
);
361 snprintf(buffer
, buffer_len
, "Last button value: 0x%04x Raw value: 0x%04x", last_btn
, btn
);
364 snprintf(buffer
, buffer_len
, "Last button differs in ticks: 0x%04x", tick_diff
);
367 snprintf(buffer
, buffer_len
, "Dock values: 0x%04x", nonbtn
);
369 #define B(n,w,b) case n: \
370 snprintf(buffer, buffer_len, "%s: 0x%04x", w, b); \
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
));