summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2008-04-04 23:43:31 +0000
committerRob Purchase <shotofadds@rockbox.org>2008-04-04 23:43:31 +0000
commit36f8fba2090491913cb9c565bf3770873678eb8a (patch)
tree1e79d85e105dc86014e1bb6f9065446c23f2ed9c
parent32bd0f8ab1526e32011937a827b6e44476a6743e (diff)
downloadrockbox-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
-rw-r--r--firmware/export/tcc780x.h1
-rw-r--r--firmware/target/arm/tcc780x/adc-tcc780x.c75
2 files changed, 53 insertions, 23 deletions
diff --git a/firmware/export/tcc780x.h b/firmware/export/tcc780x.h
index 89c2fdd9c4..f153d14bfe 100644
--- a/firmware/export/tcc780x.h
+++ b/firmware/export/tcc780x.h
@@ -123,6 +123,7 @@
123#define TIMER0_IRQ_MASK (1<<6) 123#define TIMER0_IRQ_MASK (1<<6)
124#define DAI_RX_IRQ_MASK (1<<14) 124#define DAI_RX_IRQ_MASK (1<<14)
125#define DAI_TX_IRQ_MASK (1<<15) 125#define DAI_TX_IRQ_MASK (1<<15)
126#define ADC_IRQ_MASK (1<<30)
126 127
127/* Timer / Counters */ 128/* Timer / Counters */
128 129
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
36static unsigned short adcdata[8]; 27static unsigned short adcdata[8];
37 28
38static void adc_do_read(void) 29#ifndef BOOTLOADER
30
31/* Tick task */
32static 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 */
45void 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
62unsigned 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
61unsigned 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}