From 36f8fba2090491913cb9c565bf3770873678eb8a Mon Sep 17 00:00:00 2001 From: Rob Purchase Date: Fri, 4 Apr 2008 23:43:31 +0000 Subject: Tick/IRQ driven ADCs for TCC780x. Solves the weird button behaviour mentioned on the D2 wiki page. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16974 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/tcc780x/adc-tcc780x.c | 75 +++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 23 deletions(-) (limited to 'firmware/target') diff --git a/firmware/target/arm/tcc780x/adc-tcc780x.c b/firmware/target/arm/tcc780x/adc-tcc780x.c index 871db2b61d..62bc53e6c1 100644 --- a/firmware/target/arm/tcc780x/adc-tcc780x.c +++ b/firmware/target/arm/tcc780x/adc-tcc780x.c @@ -24,20 +24,46 @@ #include "string.h" #include "adc.h" -/* - TODO: We probably want to do this on the timer interrupt once we get - interrupts going - see the sh-adc.c implementation for an example which - looks like it should work well with the TCC77x. - - Also, this code is practically identical between 77x & 780x targets. - Should probably find a common location to avoid the duplication. -*/ - static unsigned short adcdata[8]; -static void adc_do_read(void) +#ifndef BOOTLOADER + +/* Tick task */ +static void adc_tick(void) { int i; + + PCLK_ADC |= PCK_EN; /* Enable ADC clock */ + + /* Start converting the first 4 channels */ + for (i = 0; i < 4; i++) + ADCCON = i; + +} + +/* IRQ handler */ +void ADC(void) +{ + int num; + uint32_t adc_status; + + do + { + adc_status = ADCSTATUS; + num = (adc_status>>24) & 7; + if (num) adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; + } while (num); + + PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ +} +#endif /* BOOTLOADER */ + + +unsigned short adc_read(int channel) +{ +#ifdef BOOTLOADER + /* IRQs aren't enabled in the bootloader - just do the read directly */ + int i,num; uint32_t adc_status; PCLK_ADC |= PCK_EN; /* Enable ADC clock */ @@ -49,20 +75,15 @@ static void adc_do_read(void) /* Wait for data to become stable */ while ((ADCDATA & 0x1) == 0); - /* Now read the values back */ - for (i=0;i < 4; i++) { + do + { adc_status = ADCSTATUS; - adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; - } + num = (adc_status>>24) & 7; + if (num) adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; + } while (num); PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ -} - -unsigned short adc_read(int channel) -{ - /* Either move this to an interrupt routine, or only perform the read if - the last call was X length of time ago. */ - adc_do_read(); +#endif return adcdata[channel]; } @@ -71,6 +92,14 @@ void adc_init(void) { /* consider configuring PCK_ADC source here */ - ADCCON = (1<<4); /* Leave standby mode */ - ADCCFG |= 0x00000003; /* Single-mode, auto power-down */ + ADCCON = (1<<4); /* Enter standby mode */ + ADCCFG |= 0x0000000B; /* Single-mode, auto power-down, IRQ enable */ + +#ifndef BOOTLOADER + IEN |= ADC_IRQ_MASK; /* Enable ADC IRQs */ + + tick_add_task(adc_tick); + + sleep(2); /* Ensure valid readings when adc_init returns */ +#endif } -- cgit