source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/wiring_analog.c@ 137

Last change on this file since 137 was 137, checked in by ertl-honda, 8 years ago

サンプルの追加.

File size: 8.6 KB
Line 
1/*
2 Copyright (c) 2014 Arduino. All right reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 See the GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 //
20
21#include "wiring_analog.h"
22#include "wiring_digital.h"
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28static int _readResolution = 10;
29static int _writeResolution = 10;
30static int ADC_RESOLUTION = 12;
31static int DAC_RESOLUTION = 10;
32
33// Wait for synchronization of registers between the clock domains
34static __inline__ void syncDAC() __attribute__((always_inline, unused));
35static void syncDAC() {
36 while (DAC->STATUS.bit.SYNCBUSY == 1)
37 ;
38}
39
40void analogReadResolution(int res) {
41 _readResolution = res;
42 while( ADC->STATUS.bit.SYNCBUSY == 1 )
43 {
44 // Waiting for synchroinization
45 }
46 if(res == 8) ADC->CTRLB.bit.RESSEL= ADC_CTRLB_RESSEL_8BIT_Val;
47 else if(res == 10) ADC->CTRLB.bit.RESSEL= ADC_CTRLB_RESSEL_10BIT_Val;
48 else ADC->CTRLB.bit.RESSEL= ADC_CTRLB_RESSEL_12BIT_Val;
49}
50
51void analogWriteResolution(int res) {
52 _writeResolution = res;
53}
54
55static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to) {
56 if (from == to)
57 return value;
58 if (from > to)
59 return value >> (from-to);
60 else
61 return value << (to-from);
62}
63
64void analogReference( eAnalogReference ulMode )
65{
66
67 // ATTENTION : On this board the default is not 5volts or 3.3volts BUT 1.65 volt
68
69
70
71 ADC->CTRLA.bit.ENABLE = 0; // Enable ADC
72 while( ADC->STATUS.bit.SYNCBUSY == 1 )
73 {
74 // Waiting for synchroinization
75 }
76 switch(ulMode)
77 {
78 case AR_DEFAULT:
79 //default:
80
81 ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
82 ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;
83 break;
84 case AR_INTERNAL:
85 ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;
86 ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val;
87 break;
88
89 case AR_EXTERNAL:
90 ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;
91 ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;
92 break;
93 }ADC->CTRLA.bit.ENABLE = 1; // Enable ADC
94 while( ADC->STATUS.bit.SYNCBUSY == 1 )
95 {
96 // Waiting for synchroinization
97 }
98}
99
100uint32_t analogRead( uint32_t ulPin )
101{
102 uint32_t valueRead = 0;
103 pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType);
104 if ( ulPin == 24 ) // Only 1 DAC on A0 (PA02)
105 {
106 DAC->CTRLA.bit.ENABLE = 0; //disable DAC on A0
107 }
108
109 ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber;
110
111 // Start conversion
112 ADC->SWTRIG.bit.START = 1;
113
114 while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 )
115 {
116 // Waiting for a complete conversion and complete synchronization
117 }
118
119 // Store the value
120 valueRead = ADC->RESULT.reg;
121
122 // Clear the Data Ready flag
123 ADC->INTFLAG.bit.RESRDY = 1;
124
125 // Flush the ADC for further conversions
126 // ADC->SWTRIG.bit.FLUSH = 1;
127
128 while( ADC->STATUS.bit.SYNCBUSY == 1 || ADC->SWTRIG.bit.FLUSH == 1 )
129 {
130 // Waiting for synchronization
131 }
132
133 //valueRead = mapResolution(valueRead, ADC_RESOLUTION, _readResolution);
134 return valueRead;
135
136}
137
138
139// Right now, PWM output only works on the pins with
140// hardware support. These are defined in the appropriate
141// pins_*.c file. For the rest of the pins, we default
142// to digital output.
143void analogWrite( uint32_t ulPin, uint32_t ulValue )
144{
145 uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
146// uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
147 uint8_t isTC = 0 ;
148 uint8_t Channelx ;
149 Tc* TCx ;
150 Tcc* TCCx ;
151
152 if ( (attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG )
153 {
154 if ( ulPin == 24 ) // Only 1 DAC on A0 (PA02)
155 {
156 ulValue = mapResolution(ulValue, _writeResolution, DAC_RESOLUTION);
157 DAC->DATA.reg = ulValue & 0x3FF; // Dac on 10 bits.
158 DAC->CTRLA.bit.ENABLE = 1; // DAC Enabled
159 syncDAC();
160 return;
161 }
162
163
164 }
165
166 if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM )
167 {
168 if ( (g_APinDescription[ulPin].ulPinType == PIO_TIMER) || g_APinDescription[ulPin].ulPinType == PIO_TIMER_ALT )
169 {
170 pinPeripheral( ulPin, g_APinDescription[ulPin].ulPinType ) ;
171 }
172
173 switch ( g_APinDescription[ulPin].ulPWMChannel )
174 {
175 case PWM3_CH0 :
176 TCx = TC3 ;
177 Channelx = 0 ;
178 isTC = 1 ;
179 break;
180
181 case PWM3_CH1:
182 TCx = TC3 ;
183 Channelx = 1;
184 isTC = 1;
185 break;
186
187 case PWM0_CH0 :
188 TCCx = TCC0;
189 Channelx = 0;
190 break;
191
192 case PWM0_CH1 :
193 TCCx = TCC0;
194 Channelx = 1;
195 break;
196
197 case PWM0_CH4 :
198 TCCx = TCC0;
199 Channelx = 0;
200 break;
201
202 case PWM0_CH5 :
203 TCCx = TCC0;
204 Channelx = 1;
205 break;
206
207 case PWM0_CH6 :
208 TCCx = TCC0;
209 Channelx = 2;
210 break;
211
212 case PWM0_CH7 :
213 TCCx = TCC0;
214 Channelx = 3;
215 break;
216
217 case PWM1_CH0 :
218 TCCx = TCC1;
219 Channelx = 0;
220 break;
221
222 case PWM1_CH1 :
223 TCCx = TCC1;
224 Channelx = 1;
225 break;
226
227 case PWM2_CH0 :
228 TCCx = TCC2;
229 Channelx = 0;
230 break;
231
232 case PWM2_CH1 :
233 TCCx = TCC2;
234 Channelx = 1;
235 break;
236 }
237
238
239 // Enable clocks according to TCCx instance to use
240 switch ( GetTCNumber( g_APinDescription[ulPin].ulPWMChannel ) )
241 {
242 case 0: // TCC0
243 //Enable GCLK for TCC0 (timer counter input clock)
244 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
245 break;
246
247 case 1: // TCC1
248 //Enable GCLK for TCC1 (timer counter input clock)
249 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
250 break;
251
252 case 2: // TCC2
253 //Enable GCLK for TCC2 (timer counter input clock)
254 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ;
255 break;
256
257 case 3: // TC3
258 //Enable GCLK for TC3 (timer counter input clock)
259 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
260 break;
261
262 case 4: // TC4
263 //Enable GCLK for TC4 (timer counter input clock)
264 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
265 break;
266
267 case 5: // TC5
268 //Enable GCLK for TC5 (timer counter input clock)
269 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 )) ;
270 break;
271 }
272
273 // Set PORT
274 if ( isTC )
275 {
276 // -- Configure TC
277 //DISABLE TCx
278 TCx->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
279 //Set Timer counter Mode to 8 bits
280 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8;
281 //Set TCx as normal PWM
282 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
283 //Set TCx in waveform mode Normal PWM
284 TCx->COUNT8.CC[Channelx].reg = (uint8_t) ulValue;
285 //Set PER to maximum counter value (resolution : 0xFF)
286 TCx->COUNT8.PER.reg = 0xFF;
287 // Enable TCx
288 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
289 }
290 else
291 {
292 // -- Configure TCC
293
294 //DISABLE TCCx
295 TCCx->CTRLA.reg &=~(TCC_CTRLA_ENABLE);
296 //Set TCx as normal PWM
297 TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
298 //Set TCx in waveform mode Normal PWM
299 TCCx->CC[Channelx].reg = (uint32_t)ulValue;
300 //Set PER to maximum counter value (resolution : 0xFF)
301 TCCx->PER.reg = 0xFF;
302 //ENABLE TCCx
303 TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
304 }
305
306 return ;
307 }
308
309 // -- Defaults to digital write
310 pinMode( ulPin, OUTPUT ) ;
311
312 if ( ulValue < 128 )
313 {
314 digitalWrite( ulPin, LOW ) ;
315 }
316 else
317 {
318 digitalWrite( ulPin, HIGH ) ;
319 }
320}
321
322#ifdef __cplusplus
323}
324#endif
Note: See TracBrowser for help on using the repository browser.