From 95167e01773dcfe8e5c1b356cfa1ea4b3a55441b Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Thu, 24 Apr 2008 20:08:28 +0000 Subject: Commit whole Creative Zen Vision:M target tree + all related firmware/ changes. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17241 a1c6a512-1295-4272-9138-f99709370657 --- .../arm/tms320dm320/creative-zvm/pic-creativezvm.c | 323 +++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c (limited to 'firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c') 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 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2008 by Maurus Cuelenaere +* +* Creative Zen Vision:M interrupt based PIC driver +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "config.h" +#include "system.h" +#include "kernel.h" +#include "button-target.h" +#include "i2c-dm320.h" + + +#include "lcd-target.h" +#include "lcd.h" +#include "sprintf.h" +#include "font.h" + +#ifndef ZEN_VISION +/* Creative Zen Vision:M */ +#define BTN_LEFT 0x5F00 +#define BTN_RIGHT 0x4F00 +#define BTN_BACK 0xBF00 +#define BTN_CUSTOM 0x8F00 +#define BTN_PLAY 0x2F00 +#define BTN_POWER 0x0F00 +#define BTN_MENU 0x9F00 +#define BTN_HOLD 0x9F06 +#define BTN_UNHOLD 0xAF06 + +#define BTN_REL 1 + +#define BTN_TOUCHPAD_PRESS 0x1F00 +#define BTN_TOUCHPAD_CORNER_DOWN 0xAF00 +#define BTN_TOUCHPAD_CORNER_UP 0x3F00 + +#define HEADPHONE_PLUGIN_A 0x5707 +#define HEADPHONE_PLUGIN_B 0x5F07 +#define HEADPHONE_UNPLUG_A 0x3707 +#define HEADPHONE_UNPLUG_B 0x3F07 + +#define DOCK_INSERT 0x6707 +#define DOCK_UNPLUG 0xDF06 +#define DOCK_USB_INSERT 0x2F06 +#define DOCK_USB_UNPLUG 0x3F06 +#define DOCK_POWER_INSERT 0x2707 +#define DOCK_POWER_UNPLUG 0x2F07 + +#else +/* Creative Zen Vision */ +#define BTN_LEFT 0xCF00 +#define BTN_RIGHT 0xEF00 +#define BTN_BACK 0xBF00 +#define BTN_CUSTOM 0x0 +#define BTN_PLAY 0x2F00 +#define BTN_POWER 0x0F00 +#define BTN_MENU 0x9F00 +#define BTN_HOLD 0x9F06 +#define BTN_UNHOLD 0xAF06 +/* TODO: other values +First number is just pressing it, second is when you release it or keep it pressed a bit longer +On/Off = 0F00 && 0F01 +Hold = 9F06 && AF06 +Volume Up = 6F00 && 6F01 +Vol Down = 7F00 && 7F01 +Up = DF00 && DF01 +Right = EF00 && EF01 +Down = FF00 && FF01 +Left = CF00 && CF01 +Back = BF00 && BF01 +Menu = 9F00 && Etcetera +Ok = 1F00 +Play = 2F00 +Next = 4F00 +Prev = 5F00 + +USB = 2F06 +USB ouot = 3F06 +Headphones= AF06 +Hdphns out= BF06 +Charger = 4F06 -> 9F05 +Chgrout = 5F06 -> 8F05 +AV in = 8F06 +AV out = 9F06 */ + +#define BTN_REL 1 + +#define BTN_TOUCHPAD_PRESS 0x8F00 +#define BTN_TOUCHPAD_LONG_PRESS 0x0F00 +#define BTN_TOUCHPAD_CORNER_DOWN 0xD700 +#define BTN_TOUCHPAD_CORNER_LONG_DOWN 0x5700 +#define BTN_TOUCHPAD_CORNER_UP 0x9F00 +#define BTN_TOUCHPAD_CORNER_LONG_UP 0x1F00 + +#define HEADPHONE_PLUGIN_A 0xAF06 +#define HEADPHONE_PLUGIN_B 0xAF06 +#define HEADPHONE_UNPLUG_A 0xBF06 +#define HEADPHONE_UNPLUG_B 0xBF06 + +#define DOCK_INSERT 0x0 +#define DOCK_UNPLUG 0x0 +#define DOCK_USB_INSERT 0x2F06 +#define DOCK_USB_UNPLUG_A 0x3F06 +#define DOCK_USB_UNPLUG_B 0x3F06 +#define DOCK_POWER_INSERT 0x4F06 +#define DOCK_POWER_UNPLUG 0x5F06 +#define DOCK_AV_INSERT 0x8F06 +#define DOCK_AV_UNPLUG 0x9F06 +#endif + +#define PIC_ADR 0x07 + +#define MASK_TV_OUT(x) ((x >> 14) & 1) +#define MASK_xx1(x) ((x >> 9) & 3) +#define MASK_xx2(x) ((x >> 4) & 1) +#define MASK_xx3(x) ((x >> 5) & 1) +#define MASK_xx4(x) ((x >> 6) & 1) +#define MASK_xx5(x) ((x >> 13) & 1) +#define MASK_xx6(x) ((x >> 12) & 1) +#define MASK_xx7(x) ((x >> 11) & 1) + +#define NONBUTTON_HEADPHONE (1 << 0) +#define NONBUTTON_DOCK (1 << 1) +#define NONBUTTON_USB (1 << 2) +#define NONBUTTON_POWER (1 << 3) +#define NONBUTTON_VIDEOUT (1 << 4) + +static unsigned int btn; +static bool hold_switch; +static unsigned char nonbtn; +static unsigned int pic_init_value; +static unsigned int pic_init2_value; +static unsigned int last_btn; +static long last_tick; +static int tick_diff; + +#define TICK_MIN 0x33 +#define TICK_MAX 0x34 + +/* Taken from scramble.c and modified */ +static inline unsigned short le2short(unsigned char* buf) +{ + return (unsigned short)((buf[1] << 8) | buf[0]); +} + +#define map_button(BtN,BtN2) case BtN: \ + btn ^= BtN2; \ + btn &= BtN2; \ + break; \ + case BtN ^ BTN_REL: \ + btn ^= BtN2; \ + btn &= BtN2; \ + break; + +#ifdef BUTTON_DEBUG +static bool sw = false; +#endif + +void GIO0(void) +{ + unsigned char msg[4]; + i2c_read(PIC_ADR, msg, sizeof(msg)); + tick_diff = current_tick - last_tick; + last_tick = current_tick; + unsigned short btn_press = le2short(msg); + if(tick_diff >= TICK_MIN && tick_diff <= TICK_MAX) + { + /* Ignore this, as it is a hold event */ + IO_INTC_IRQ1 = INTR_IRQ1_EXT0; + return; + } + last_btn = btn_press; + switch(btn_press) + { + map_button(BTN_LEFT, BUTTON_LEFT); + map_button(BTN_RIGHT, BUTTON_RIGHT); + map_button(BTN_BACK, BUTTON_BACK); + map_button(BTN_CUSTOM, BUTTON_CUSTOM); + map_button(BTN_MENU, BUTTON_MENU); + map_button(BTN_PLAY, BUTTON_PLAY); + map_button(BTN_POWER, BUTTON_POWER); + map_button(BTN_TOUCHPAD_PRESS, BUTTON_SELECT); + map_button(BTN_TOUCHPAD_CORNER_DOWN, BUTTON_DOWN); + map_button(BTN_TOUCHPAD_CORNER_UP, BUTTON_UP); + case BTN_HOLD: + hold_switch = true; + break; + case BTN_UNHOLD: + hold_switch = false; + break; + case HEADPHONE_PLUGIN_A: + case HEADPHONE_PLUGIN_B: + nonbtn |= NONBUTTON_HEADPHONE; + break; + case HEADPHONE_UNPLUG_A: + case HEADPHONE_UNPLUG_B: + nonbtn &= ~NONBUTTON_HEADPHONE; + break; + case DOCK_INSERT: + nonbtn |= NONBUTTON_DOCK; + break; + case DOCK_UNPLUG: + nonbtn &= ~(NONBUTTON_DOCK | NONBUTTON_USB | NONBUTTON_POWER); + break; + case DOCK_USB_INSERT: + nonbtn |= NONBUTTON_USB; + break; + case DOCK_USB_UNPLUG: + nonbtn &= ~NONBUTTON_USB; + break; + case DOCK_POWER_INSERT: + nonbtn |= NONBUTTON_POWER; + break; + case DOCK_POWER_UNPLUG: + nonbtn &= ~NONBUTTON_POWER; + break; + } +#ifdef BUTTON_DEBUG + unsigned char weergvn[10]; +#ifdef BOOTLOADER + lcd_set_foreground((sw ? LCD_RGBPACK(255,0,0) : LCD_RGBPACK(0,255,0) )); +#endif + snprintf(weergvn, sizeof(char)*10, "%x", (unsigned int)((msg[3] << 24) | (msg[2] << 16) | (msg[1] << 8) | msg[0])); + lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*10, weergvn); + snprintf(weergvn, sizeof(char)*10, "%x", btn); + lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*7, weergvn); +#ifdef BOOTLOADER + lcd_set_foreground(LCD_BLACK); +#endif + lcd_update(); + sw = !sw; +#endif + /* Mask GIO0 interrupt */ + IO_INTC_IRQ1 = INTR_IRQ1_EXT0; +} + +void send_command_to_pic(unsigned char in, unsigned char* out, unsigned int length) +{ + /* Disable GIO0 interrupt */ + IO_INTC_EINT1 &= ~INTR_EINT1_EXT0; + /* Clear EXT0 interrupt */ + IO_INTC_IRQ1 = INTR_IRQ1_EXT0; + /* Write command to I²C */ + restart: + i2c_write(PIC_ADR, &in, 1); + /* Wait for PIC */ + int i = 0; + while(!(IO_INTC_IRQ1 & INTR_IRQ1_EXT0)) + { + sleep(0); + i++; + if(i > 50) + goto restart; + } + /* Read return from I²C */ + i2c_read(PIC_ADR, out, length); + /* Re-enable GIO0 interrupt */ + IO_INTC_EINT1 |= INTR_EINT1_EXT0; +} + +bool headphones_inserted(void) +{ + return (bool)(nonbtn & NONBUTTON_HEADPHONE); +} + +void button_init_device(void) +{ + /* TODO: I suppose GIO0 has to be set to input and enable interrupts on it? */ + /* Enable GIO0 interrupt */ + IO_INTC_EINT1 |= INTR_EINT1_EXT0; + btn = nonbtn = pic_init_value = pic_init2_value = last_btn = hold_switch = 0; + /* Initialize PIC */ + send_command_to_pic(1, &pic_init_value, sizeof(pic_init_value)); + send_command_to_pic(2, &pic_init2_value, sizeof(pic_init2_value)); +} + +int get_debug_info(int choice) +{ + switch(choice) + { + case 1: + return pic_init_value; + case 2: + return pic_init2_value; + case 3: + return last_btn; + case 4: + return nonbtn; + case 5: + return tick_diff; + } + return -1; +} + +int button_read_device(void) +{ + return btn; +} + +bool button_hold(void) +{ + return hold_switch; +} + +bool button_usb_connected(void) +{ + return (bool)(nonbtn & NONBUTTON_USB); +} -- cgit v1.2.3