summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2007-07-30 23:48:03 +0000
committerJens Arnold <amiconn@rockbox.org>2007-07-30 23:48:03 +0000
commit4e8b171fc4cc3b62a1656ae67e92944ff855dcd3 (patch)
tree61ea62ef4b5b483cd86c778028d2b1979547178d /firmware
parent35274ce1196b8055e189d18d8295edf2e5b0b65c (diff)
downloadrockbox-4e8b171fc4cc3b62a1656ae67e92944ff855dcd3.tar.gz
rockbox-4e8b171fc4cc3b62a1656ae67e92944ff855dcd3.zip
Interrupt driven ADC reading on the 2nd gen.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14086 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c55
-rw-r--r--firmware/target/arm/system-pp5002.c14
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)