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:
parent
648104a318
commit
c6b6bad18f
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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_ */
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue