1
0
Fork 0
forked from len0rd/rockbox

Interrupt driven ADC reading on the 2nd gen.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14086 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jens Arnold 2007-07-30 23:48:03 +00:00
parent 35274ce119
commit 4e8b171fc4
2 changed files with 51 additions and 20 deletions

View file

@ -24,18 +24,22 @@
static struct mutex adc_mutex NOCACHEBSS_ATTR; 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) unsigned short adc_scan(int channel)
{ {
int i, j;
unsigned short data = 0; unsigned short data = 0;
unsigned pval;
(void)channel; /* there is only one */ (void)channel; /* there is only one */
spinlock_lock(&adc_mutex); spinlock_lock(&adc_mutex);
if ((IPOD_HW_REVISION >> 16) == 1) 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 */ GPIOB_OUTPUT_VAL = pval | 0x04; /* B2 -> high */
for (i = 32; i > 0; --i); for (i = 32; i > 0; --i);
@ -55,28 +59,45 @@ unsigned short adc_scan(int channel)
} }
else if ((IPOD_HW_REVISION >> 16) == 2) else if ((IPOD_HW_REVISION >> 16) == 2)
{ {
pval = GPIOB_OUTPUT_VAL; int_status = 0;
GPIOB_OUTPUT_VAL = pval | 0x0a; /* B1, B3 -> high */ GPIOB_INT_LEV |= 0x04; /* high active */
while (!(GPIOB_INPUT_VAL & 0x04)); /* wait for B2 == 1 */ GPIOB_INT_EN |= 0x04; /* enable interrupt */
GPIOB_OUTPUT_VAL |= 0x0a; /* B1, B3 -> high: start conversion */
GPIOB_OUTPUT_VAL = pval; /* B1, B3 -> low */ while (int_status >= 0)
while (GPIOB_INPUT_VAL & 0x04); /* wait for B2 == 0 */ yield();
for (j = 0; j < 8; j++) data = int_data & 0xff;
{
GPIOB_OUTPUT_VAL = pval | 0x02; /* B1 -> high */
while (!(GPIOB_INPUT_VAL & 0x04)); /* wait for B2 == 1 */
data = (data << 1) | ((GPIOB_INPUT_VAL & 0x10) >> 4);
GPIOB_OUTPUT_VAL = pval; /* B1 -> low */
while (GPIOB_INPUT_VAL & 0x04); /* wait for B2 == 0 */
}
} }
spinlock_unlock(&adc_mutex); spinlock_unlock(&adc_mutex);
return data; return data;
} }
/* 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 &= ~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 */
}
GPIOB_INT_LEV ^= 0x04; /* toggle interrupt level */
GPIOB_INT_CLR = 0x04; /* acknowledge interrupt */
}
void adc_init(void) void adc_init(void)
{ {
spinlock_init(&adc_mutex); spinlock_init(&adc_mutex);

View file

@ -22,6 +22,7 @@
extern void TIMER1(void); extern void TIMER1(void);
extern void TIMER2(void); extern void TIMER2(void);
extern void ipod_3g_button_int(void); extern void ipod_3g_button_int(void);
extern void ipod_2g_adc_int(void);
void irq(void) void irq(void)
{ {
@ -32,8 +33,17 @@ void irq(void)
else if (CPU_INT_STAT & TIMER2_MASK) else if (CPU_INT_STAT & TIMER2_MASK)
TIMER2(); TIMER2();
else if (CPU_INT_STAT & GPIO_MASK) 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) if (COP_INT_STAT & TIMER1_MASK)
TIMER1(); TIMER1();
else if (COP_INT_STAT & TIMER2_MASK) else if (COP_INT_STAT & TIMER2_MASK)