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
This commit is contained in:
Jens Arnold 2008-03-17 00:19:23 +00:00
parent 648104a318
commit c6b6bad18f
10 changed files with 197 additions and 28 deletions

View File

@ -504,9 +504,9 @@ target/coldfire/iaudio/m3/button-m3.c
target/coldfire/iaudio/m3/fmradio_i2c-m3.c
target/coldfire/iaudio/m3/lcd-m3.c
target/coldfire/iaudio/m3/power-m3.c
target/coldfire/iaudio/m3/powermgmt-m3.c
target/coldfire/iaudio/m3/system-m3.c
target/coldfire/iaudio/m3/usb-m3.c
target/coldfire/iaudio/powermgmt-iaudio.c
#ifndef BOOTLOADER
target/coldfire/iaudio/m3/audio-m3.c
#endif

View File

@ -108,10 +108,12 @@ void panicf( const char *fmt, ...)
#define system_reboot() nop
#elif defined (TOSHIBA_GIGABEAT_F)
if ((GPGDAT & (1 << 0)) != 0)
#elif defined (IRIVER_H100_SERIES)
if ((GPIO1_READ & 0x22) == 0) /* check for ON button and !hold */
#elif defined(IRIVER_H300_SERIES)
#elif defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
if ((GPIO1_READ & 0x22) == 0) /* check for ON button and !hold */
#elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
if ((GPIO_READ & 0x0c000000) == 0x08000000) /* check for ON button and !hold */
#elif defined(IAUDIO_M3)
if ((GPIO1_READ & 0x202) == 0x200) /* check for ON button and !hold */
#elif CONFIG_CPU == SH7034
#if CONFIG_KEYPAD == PLAYER_PAD
if (!(PADRL & 0x20))

View File

@ -56,15 +56,16 @@ void i2c_init(void)
/* I2C Clock divisor = 160 => 124.1556 MHz / 2 / 160 = 388.08 kHz */
MFDR = 0x0d;
#if defined(IAUDIO_M3)
MBCR = IEN; /* Enable interface 1 */
/* secondary channel is handled in the interrupt driven ADC driver */
#elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
MBCR = IEN; /* Enable interface 1 */
MFDR2 = 0x0d;
#if defined(IAUDIO_X5) || defined(IAUDIO_M5)
MBCR = IEN; /* Enable interface */
MBCR2 = IEN;
#endif
#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
/* Audio Codec */
MBCR2 = IEN; /* Enable interface 2 */
#elif defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
MBDR = 0; /* iRiver firmware does this */
MBCR = IEN; /* Enable interface */
#endif
@ -156,7 +157,7 @@ int i2c_read(volatile unsigned char *iface, unsigned char addr,
iface[O_MBCR] |= TXAK;
else if (i == 1)
/* Generate STOP before reading last byte received */
i2c_stop(iface);
i2c_stop(iface);
*buf++ = iface[O_MBDR];
}

View File

@ -18,15 +18,90 @@
****************************************************************************/
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "kernel.h"
#include "thread.h"
#include "adc.h"
unsigned short adc_scan(int channel)
#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)
{
/* TODO */
(void)channel;
return 0xff;
if ((MBSR2 & IBB) == 0) /* Bus is free */
{
MBCR2 |= (MSTA|TXAK|MTX); /* Generate START and prepare for write */
MBDR2 = ADC_I2C_ADDR|1; /* Send address */
}
}
void IIC2(void) __attribute__((interrupt_handler));
void IIC2(void)
{
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 */
}

View File

@ -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_ */

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -53,10 +53,6 @@ const unsigned short percent_to_volt_charge[11] =
/* Returns battery voltage from ADC [millivolts] */
unsigned int battery_adc_voltage(void)
{
#ifdef IAUDIO_M3
return 4000; /* FIXME: fake value - no ADC yet */
#else
return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
#endif
}

View File

@ -144,6 +144,11 @@ default_interrupt (ADC); /* A/D converter */
#define EXCP_BUTTON_MASK 0x0c000000
#define EXCP_BUTTON_VALUE 0x08000000 /* On button and !hold */
#define EXCP_PLLCR 0x10400000
#elif defined(IAUDIO_M3)
#define EXCP_BUTTON_GPIO_READ GPIO1_READ
#define EXCP_BUTTON_MASK 0x00000202
#define EXCP_BUTTON_VALUE 0x00000200 /* On button and !hold */
#define EXCP_PLLCR 0x10800000
#else
#define EXCP_BUTTON_GPIO_READ GPIO1_READ
#define EXCP_BUTTON_MASK 0x00000022