From 4e8b171fc4cc3b62a1656ae67e92944ff855dcd3 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Mon, 30 Jul 2007 23:48:03 +0000 Subject: Interrupt driven ADC reading on the 2nd gen. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14086 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c | 55 ++++++++++++++++++--------- firmware/target/arm/system-pp5002.c | 14 ++++++- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c b/firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c index 759b6fb592..8866c3dcde 100644 --- a/firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c +++ b/firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c @@ -24,18 +24,22 @@ static struct mutex adc_mutex NOCACHEBSS_ATTR; +/* used in the 2nd gen ADC interrupt */ +static unsigned int_data; +static int int_status = -1; + unsigned short adc_scan(int channel) { - int i, j; unsigned short data = 0; - unsigned pval; (void)channel; /* there is only one */ spinlock_lock(&adc_mutex); if ((IPOD_HW_REVISION >> 16) == 1) { - pval = GPIOB_OUTPUT_VAL; + int i, j; + unsigned pval = GPIOB_OUTPUT_VAL; + GPIOB_OUTPUT_VAL = pval | 0x04; /* B2 -> high */ for (i = 32; i > 0; --i); @@ -55,26 +59,43 @@ unsigned short adc_scan(int channel) } else if ((IPOD_HW_REVISION >> 16) == 2) { - pval = GPIOB_OUTPUT_VAL; - GPIOB_OUTPUT_VAL = pval | 0x0a; /* B1, B3 -> high */ - while (!(GPIOB_INPUT_VAL & 0x04)); /* wait for B2 == 1 */ + int_status = 0; + GPIOB_INT_LEV |= 0x04; /* high active */ + GPIOB_INT_EN |= 0x04; /* enable interrupt */ + GPIOB_OUTPUT_VAL |= 0x0a; /* B1, B3 -> high: start conversion */ - GPIOB_OUTPUT_VAL = pval; /* B1, B3 -> low */ - while (GPIOB_INPUT_VAL & 0x04); /* wait for B2 == 0 */ + while (int_status >= 0) + yield(); - for (j = 0; j < 8; j++) - { - GPIOB_OUTPUT_VAL = pval | 0x02; /* B1 -> high */ - while (!(GPIOB_INPUT_VAL & 0x04)); /* wait for B2 == 1 */ + data = int_data & 0xff; + } + spinlock_unlock(&adc_mutex); + return data; +} - data = (data << 1) | ((GPIOB_INPUT_VAL & 0x10) >> 4); +/* Used for 2nd gen only. Conversion can take several milliseconds there. */ +void ipod_2g_adc_int(void) +{ + if (GPIOB_INPUT_VAL & 0x04) + { + int_data = (int_data << 1) | ((GPIOB_INPUT_VAL & 0x10) >> 4); - GPIOB_OUTPUT_VAL = pval; /* B1 -> low */ - while (GPIOB_INPUT_VAL & 0x04); /* wait for B2 == 0 */ + GPIOB_OUTPUT_VAL &= ~0x0a; /* B1, B3 -> low */ + /* B3 needs to be set low in the first call only, but then stays low + * anyway so no need for special handling */ + } + else + { + if (++int_status > 8) + { + GPIOB_INT_EN &= ~0x04; + int_status = -1; } + else + GPIOB_OUTPUT_VAL |= 0x02; /* B1 -> high */ } - spinlock_unlock(&adc_mutex); - return data; + GPIOB_INT_LEV ^= 0x04; /* toggle interrupt level */ + GPIOB_INT_CLR = 0x04; /* acknowledge interrupt */ } void adc_init(void) diff --git a/firmware/target/arm/system-pp5002.c b/firmware/target/arm/system-pp5002.c index 6d32d258cc..38dfe5b49c 100644 --- a/firmware/target/arm/system-pp5002.c +++ b/firmware/target/arm/system-pp5002.c @@ -22,6 +22,7 @@ extern void TIMER1(void); extern void TIMER2(void); extern void ipod_3g_button_int(void); +extern void ipod_2g_adc_int(void); void irq(void) { @@ -32,8 +33,17 @@ void irq(void) else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); else if (CPU_INT_STAT & GPIO_MASK) - ipod_3g_button_int(); - } else { + { + if (GPIOA_INT_STAT) + ipod_3g_button_int(); +#ifdef IPOD_1G2G + if (GPIOB_INT_STAT & 0x04) + ipod_2g_adc_int(); +#endif + } + } + else + { if (COP_INT_STAT & TIMER1_MASK) TIMER1(); else if (COP_INT_STAT & TIMER2_MASK) -- cgit v1.2.3