From c6b6bad18fcd68182574086c2eb2a1da30d36d25 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Mon, 17 Mar 2008 00:19:23 +0000 Subject: iAudio M3: ADC driver, making buttons and battery voltage reading work. * Disable the multi-colour LED for now to save power. Proper handling will be added later. * Make reboot on button press work on iAudio X5, M5, M3 in panicf(), and on M3 in UIE(). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16684 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/coldfire/iaudio/m3/adc-m3.c | 91 +++++++++++++++++++++-- firmware/target/coldfire/iaudio/m3/adc-target.h | 29 ++++++++ firmware/target/coldfire/iaudio/m3/button-m3.c | 4 +- firmware/target/coldfire/iaudio/m3/power-m3.c | 4 + firmware/target/coldfire/iaudio/m3/powermgmt-m3.c | 57 ++++++++++++++ 5 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 firmware/target/coldfire/iaudio/m3/adc-target.h create mode 100644 firmware/target/coldfire/iaudio/m3/powermgmt-m3.c (limited to 'firmware/target/coldfire/iaudio/m3') diff --git a/firmware/target/coldfire/iaudio/m3/adc-m3.c b/firmware/target/coldfire/iaudio/m3/adc-m3.c index c4f8d92ae1..b0d7f7430b 100644 --- a/firmware/target/coldfire/iaudio/m3/adc-m3.c +++ b/firmware/target/coldfire/iaudio/m3/adc-m3.c @@ -18,15 +18,90 @@ ****************************************************************************/ #include "config.h" -#include "cpu.h" -#include "system.h" -#include "kernel.h" -#include "thread.h" + #include "adc.h" +#include "i2c-coldfire.h" +#include "system.h" + +#define ADC_I2C_ADDR 0xa0 + +/* The M3 ADC is hooked exclusively to the secondary I²C bus, and requires + * very slow transfers (I²C clock <= 16kHz). So we start one 4-byte read + * transfer each tick, and handle it via an ISR. At 11MHz, one transfer + * takes too long to be started every tick, but it seems we have to live + * with that. */ + +static unsigned char adc_data[NUM_ADC_CHANNELS] IBSS_ATTR; +static volatile bool data_ready = false; + + +static void adc_tick(void) +{ + if ((MBSR2 & IBB) == 0) /* Bus is free */ + { + MBCR2 |= (MSTA|TXAK|MTX); /* Generate START and prepare for write */ + MBDR2 = ADC_I2C_ADDR|1; /* Send address */ + } +} -unsigned short adc_scan(int channel) +void IIC2(void) __attribute__((interrupt_handler)); +void IIC2(void) { - /* TODO */ - (void)channel; - return 0xff; + static int bytenum = 0; + + MBSR2 &= ~IFF; /* Clear interrupt flag */ + + if (MBSR2 & IAL) /* Arbitration lost - shouldn't happen */ + { /* normally, but CPU freq change might induce it */ + MBSR2 &= ~IAL; /* Clear flag */ + MBCR2 &= ~MSTA; /* STOP */ + } + else if (MBCR2 & MTX) /* Address phase */ + { + if (MBSR2 & RXAK) /* No ACK received */ + { + MBCR2 &= ~MSTA; /* STOP */ + return; + } + MBCR2 &= ~(MTX|TXAK); /* Switch to RX mode, enable TX ack generation */ + MBDR2; /* Dummy read */ + bytenum = 0; + } + else + { + switch (bytenum) + { + case 2: + MBCR2 |= TXAK; /* Don't ACK the last byte */ + break; + + case 3: + MBCR2 &= ~MSTA; /* STOP before reading the last value */ + data_ready = true; /* Simplification - the last byte is a dummy. */ + break; + } + adc_data[bytenum++] = MBDR2; + } + +} + +unsigned short adc_read(int channel) +{ + return adc_data[channel]; +} + +void adc_init(void) +{ + MFDR2 = 0x1f; /* I²C clock = SYSCLK / 3840 */ + MBCR2 = IEN; /* Enable interface */ + MBSR2 = 0; /* Clear flags */ + MBCR2 = (IEN|IIEN); /* Enable interrupts */ + + and_l(~0x0f000000, &INTPRI8); + or_l( 0x04000000, &INTPRI8); /* INT62 - Priority 4 */ + + tick_add_task(adc_tick); + + while (!data_ready) + sleep(1); /* Ensure valid readings when adc_init returns */ } diff --git a/firmware/target/coldfire/iaudio/m3/adc-target.h b/firmware/target/coldfire/iaudio/m3/adc-target.h new file mode 100644 index 0000000000..e5ff818647 --- /dev/null +++ b/firmware/target/coldfire/iaudio/m3/adc-target.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Jens Arnold + * + * 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. + * + ****************************************************************************/ + +#ifndef _ADC_TARGET_H_ +#define _ADC_TARGET_H_ + +#define NUM_ADC_CHANNELS 4 + +#define ADC_BUTTONS 0 +#define ADC_BATTERY 1 +#define ADC_REMOTE 2 + +#endif /* _ADC_TARGET_H_ */ diff --git a/firmware/target/coldfire/iaudio/m3/button-m3.c b/firmware/target/coldfire/iaudio/m3/button-m3.c index c7c5b2e90f..ecea221a4c 100644 --- a/firmware/target/coldfire/iaudio/m3/button-m3.c +++ b/firmware/target/coldfire/iaudio/m3/button-m3.c @@ -56,7 +56,7 @@ int button_read_device(void) if (!hold_button) { - data = adc_scan(ADC_BUTTONS); + data = adc_read(ADC_BUTTONS); if (data < 0xc0) { @@ -82,7 +82,7 @@ int button_read_device(void) } /* remote buttons */ - data = remote_detect() ? adc_scan(ADC_REMOTE) : 0xff; + data = remote_detect() ? adc_read(ADC_REMOTE) : 0xff; remote_hold_button_old = remote_hold_button; remote_hold_button = data < 0x14; diff --git a/firmware/target/coldfire/iaudio/m3/power-m3.c b/firmware/target/coldfire/iaudio/m3/power-m3.c index 7b5af43026..52a5de3460 100644 --- a/firmware/target/coldfire/iaudio/m3/power-m3.c +++ b/firmware/target/coldfire/iaudio/m3/power-m3.c @@ -36,6 +36,10 @@ void power_init(void) /* Charger detect */ and_l(~0x00000020, &GPIO1_ENABLE); or_l(0x00000020, &GPIO1_FUNCTION); + + /* FIXME: Just disable the multi-colour LED for now. */ + and_l(~0x00000210, &GPIO1_OUT); + and_l(~0x00008000, &GPIO_OUT); } bool charger_inserted(void) diff --git a/firmware/target/coldfire/iaudio/m3/powermgmt-m3.c b/firmware/target/coldfire/iaudio/m3/powermgmt-m3.c new file mode 100644 index 0000000000..8c94947785 --- /dev/null +++ b/firmware/target/coldfire/iaudio/m3/powermgmt-m3.c @@ -0,0 +1,57 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 Jens Arnold + * + * 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 "adc.h" +#include "powermgmt.h" + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3540 +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3500 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + /* average measured values from X5 and M5L */ + { 3500, 3650, 3720, 3740, 3760, 3790, 3840, 3900, 3950, 4040, 4120 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = +{ + /* TODO: This is identical to the discharge curve. + * Calibrate charging curve using a battery_bench log. */ + 3500, 3650, 3720, 3740, 3760, 3790, 3840, 3900, 3950, 4040, 4120 +}; + +#define BATTERY_SCALE_FACTOR 5720 +/* full-scale ADC readout (2^8) in millivolt */ + +/* Returns battery voltage from ADC [millivolts] */ +unsigned int battery_adc_voltage(void) +{ + return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 8; +} + -- cgit v1.2.3