diff options
author | Rob Purchase <shotofadds@rockbox.org> | 2008-04-04 23:43:31 +0000 |
---|---|---|
committer | Rob Purchase <shotofadds@rockbox.org> | 2008-04-04 23:43:31 +0000 |
commit | 36f8fba2090491913cb9c565bf3770873678eb8a (patch) | |
tree | 1e79d85e105dc86014e1bb6f9065446c23f2ed9c /firmware/target/arm/tcc780x/adc-tcc780x.c | |
parent | 32bd0f8ab1526e32011937a827b6e44476a6743e (diff) | |
download | rockbox-36f8fba2090491913cb9c565bf3770873678eb8a.tar.gz rockbox-36f8fba2090491913cb9c565bf3770873678eb8a.zip |
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
Diffstat (limited to 'firmware/target/arm/tcc780x/adc-tcc780x.c')
-rw-r--r-- | firmware/target/arm/tcc780x/adc-tcc780x.c | 75 |
1 files changed, 52 insertions, 23 deletions
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 @@ | |||
24 | #include "string.h" | 24 | #include "string.h" |
25 | #include "adc.h" | 25 | #include "adc.h" |
26 | 26 | ||
27 | /* | ||
28 | TODO: We probably want to do this on the timer interrupt once we get | ||
29 | interrupts going - see the sh-adc.c implementation for an example which | ||
30 | looks like it should work well with the TCC77x. | ||
31 | |||
32 | Also, this code is practically identical between 77x & 780x targets. | ||
33 | Should probably find a common location to avoid the duplication. | ||
34 | */ | ||
35 | |||
36 | static unsigned short adcdata[8]; | 27 | static unsigned short adcdata[8]; |
37 | 28 | ||
38 | static void adc_do_read(void) | 29 | #ifndef BOOTLOADER |
30 | |||
31 | /* Tick task */ | ||
32 | static void adc_tick(void) | ||
39 | { | 33 | { |
40 | int i; | 34 | int i; |
35 | |||
36 | PCLK_ADC |= PCK_EN; /* Enable ADC clock */ | ||
37 | |||
38 | /* Start converting the first 4 channels */ | ||
39 | for (i = 0; i < 4; i++) | ||
40 | ADCCON = i; | ||
41 | |||
42 | } | ||
43 | |||
44 | /* IRQ handler */ | ||
45 | void ADC(void) | ||
46 | { | ||
47 | int num; | ||
48 | uint32_t adc_status; | ||
49 | |||
50 | do | ||
51 | { | ||
52 | adc_status = ADCSTATUS; | ||
53 | num = (adc_status>>24) & 7; | ||
54 | if (num) adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; | ||
55 | } while (num); | ||
56 | |||
57 | PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ | ||
58 | } | ||
59 | #endif /* BOOTLOADER */ | ||
60 | |||
61 | |||
62 | unsigned short adc_read(int channel) | ||
63 | { | ||
64 | #ifdef BOOTLOADER | ||
65 | /* IRQs aren't enabled in the bootloader - just do the read directly */ | ||
66 | int i,num; | ||
41 | uint32_t adc_status; | 67 | uint32_t adc_status; |
42 | 68 | ||
43 | PCLK_ADC |= PCK_EN; /* Enable ADC clock */ | 69 | PCLK_ADC |= PCK_EN; /* Enable ADC clock */ |
@@ -49,20 +75,15 @@ static void adc_do_read(void) | |||
49 | /* Wait for data to become stable */ | 75 | /* Wait for data to become stable */ |
50 | while ((ADCDATA & 0x1) == 0); | 76 | while ((ADCDATA & 0x1) == 0); |
51 | 77 | ||
52 | /* Now read the values back */ | 78 | do |
53 | for (i=0;i < 4; i++) { | 79 | { |
54 | adc_status = ADCSTATUS; | 80 | adc_status = ADCSTATUS; |
55 | adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; | 81 | num = (adc_status>>24) & 7; |
56 | } | 82 | if (num) adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; |
83 | } while (num); | ||
57 | 84 | ||
58 | PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ | 85 | PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ |
59 | } | 86 | #endif |
60 | |||
61 | unsigned short adc_read(int channel) | ||
62 | { | ||
63 | /* Either move this to an interrupt routine, or only perform the read if | ||
64 | the last call was X length of time ago. */ | ||
65 | adc_do_read(); | ||
66 | 87 | ||
67 | return adcdata[channel]; | 88 | return adcdata[channel]; |
68 | } | 89 | } |
@@ -71,6 +92,14 @@ void adc_init(void) | |||
71 | { | 92 | { |
72 | /* consider configuring PCK_ADC source here */ | 93 | /* consider configuring PCK_ADC source here */ |
73 | 94 | ||
74 | ADCCON = (1<<4); /* Leave standby mode */ | 95 | ADCCON = (1<<4); /* Enter standby mode */ |
75 | ADCCFG |= 0x00000003; /* Single-mode, auto power-down */ | 96 | ADCCFG |= 0x0000000B; /* Single-mode, auto power-down, IRQ enable */ |
97 | |||
98 | #ifndef BOOTLOADER | ||
99 | IEN |= ADC_IRQ_MASK; /* Enable ADC IRQs */ | ||
100 | |||
101 | tick_add_task(adc_tick); | ||
102 | |||
103 | sleep(2); /* Ensure valid readings when adc_init returns */ | ||
104 | #endif | ||
76 | } | 105 | } |