summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c')
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c323
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
76First number is just pressing it, second is when you release it or keep it pressed a bit longer
77On/Off = 0F00 && 0F01
78Hold = 9F06 && AF06
79Volume Up = 6F00 && 6F01
80Vol Down = 7F00 && 7F01
81Up = DF00 && DF01
82Right = EF00 && EF01
83Down = FF00 && FF01
84Left = CF00 && CF01
85Back = BF00 && BF01
86Menu = 9F00 && Etcetera
87Ok = 1F00
88Play = 2F00
89Next = 4F00
90Prev = 5F00
91
92USB = 2F06
93USB ouot = 3F06
94Headphones= AF06
95Hdphns out= BF06
96Charger = 4F06 -> 9F05
97Chgrout = 5F06 -> 8F05
98AV in = 8F06
99AV 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
143static unsigned int btn;
144static bool hold_switch;
145static unsigned char nonbtn;
146static unsigned int pic_init_value;
147static unsigned int pic_init2_value;
148static unsigned int last_btn;
149static long last_tick;
150static int tick_diff;
151
152#define TICK_MIN 0x33
153#define TICK_MAX 0x34
154
155/* Taken from scramble.c and modified */
156static 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
171static bool sw = false;
172#endif
173
174void 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
252void 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
276bool headphones_inserted(void)
277{
278 return (bool)(nonbtn & NONBUTTON_HEADPHONE);
279}
280
281void 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
292int 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
310int button_read_device(void)
311{
312 return btn;
313}
314
315bool button_hold(void)
316{
317 return hold_switch;
318}
319
320bool button_usb_connected(void)
321{
322 return (bool)(nonbtn & NONBUTTON_USB);
323}