summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
new file mode 100644
index 0000000000..4c448c2e41
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
@@ -0,0 +1,144 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Wade Brown
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "cpu.h"
20#include "adc-target.h"
21#include "kernel.h"
22
23
24
25static unsigned short adc_readings[NUM_ADC_CHANNELS];
26
27/* prototypes */
28static unsigned short __adc_read(int channel);
29static void adc_tick(void);
30
31
32
33void adc_init(void)
34{
35 int i;
36
37 /* Turn on the ADC PCLK */
38 CLKCON |= (1<<15);
39
40 /* Set channel 0, normal mode, disable "start by read" */
41 ADCCON &= ~(0x3F);
42
43 /* No start delay. Use normal conversion mode. */
44 ADCDLY = 0x1;
45
46 /* Set and enable the prescaler */
47 ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
48 ADCCON |= (1<<14);
49
50 /* prefill the adc channels */
51 for (i = 0; i < NUM_ADC_CHANNELS; i++)
52 {
53 adc_readings[i] = __adc_read(i);
54 }
55
56 /* start at zero so when the tick starts it is at zero */
57 adc_readings[0] = __adc_read(0);
58
59 /* attach the adc reading to the tick */
60 tick_add_task(adc_tick);
61
62
63}
64
65
66
67/* Called to get the recent ADC reading */
68inline unsigned short adc_read(int channel)
69{
70 return adc_readings[channel];
71}
72
73
74
75/**
76 * Read the ADC by polling
77 * @param channel The ADC channel to read
78 * @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
79 */
80static unsigned short __adc_read(int channel)
81{
82 int i;
83
84 /* Set the channel */
85 ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3);
86
87 /* Start the conversion process */
88 ADCCON |= 0x1;
89
90 /* Wait for a low Enable_start */
91 for (i = 20000;;) {
92 if(0 == (ADCCON & 0x1)) {
93 break;
94 }
95 else {
96 i--;
97 if (0 == i) {
98 /* Ran out of time */
99 return ADC_READ_ERROR;
100 }
101 }
102 }
103
104 /* Wait for high End_of_Conversion */
105 for(i = 20000;;) {
106 if(ADCCON & (1<<15)) {
107 break;
108 }
109 else {
110 i--;
111 if(0 == i) {
112 /* Ran out of time */
113 return ADC_READ_ERROR;
114 }
115 }
116 }
117
118 return (ADCDAT0 & 0x3ff);
119}
120
121
122
123/* add this to the tick so that the ADC converts are done in the background */
124static void adc_tick(void)
125{
126 static unsigned channel;
127
128 /* Check if the End Of Conversion is set */
129 if (ADCCON & (1<<15))
130 {
131 adc_readings[channel] = (ADCDAT0 & 0x3FF);
132 if (++channel >= NUM_ADC_CHANNELS)
133 {
134 channel = 0;
135 }
136
137 /* setup the next conversion and start it*/
138 ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01;
139 }
140}
141
142
143
144