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

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

ライブラリを Arduino IDE 1.7.9 にupdate

File size: 8.5 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
68 ADC->CTRLA.bit.ENABLE = 0; // Enable ADC
69 while( ADC->STATUS.bit.SYNCBUSY == 1 )
70 {
71 // Waiting for synchroinization
72 }
73 switch(ulMode)
74 {
75 case AR_DEFAULT:
76 //default:
77
78 ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
79 ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;
80 break;
81 case AR_INTERNAL:
82 ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;
83 ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val;
84 break;
85
86 case AR_EXTERNAL:
87 ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;
88 ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;
89 break;
90 }ADC->CTRLA.bit.ENABLE = 1; // Enable ADC
91 while( ADC->STATUS.bit.SYNCBUSY == 1 )
92 {
93 // Waiting for synchroinization
94 }
95}
96
97uint32_t analogRead( uint32_t ulPin )
98{
99 uint32_t valueRead = 0;
100 pinPeripheral(ulPin, g_APinDescription[ulPin].ulPinType);
101 if ( ulPin == 24 ) // Only 1 DAC on A0 (PA02)
102 {
103 DAC->CTRLA.bit.ENABLE = 0; //disable DAC on A0
104 }
105
106 ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber;
107
108 // Start conversion
109 ADC->SWTRIG.bit.START = 1;
110
111 while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 )
112 {
113 // Waiting for a complete conversion and complete synchronization
114 }
115
116 // Store the value
117 valueRead = ADC->RESULT.reg;
118
119 // Clear the Data Ready flag
120 ADC->INTFLAG.bit.RESRDY = 1;
121
122 // Flush the ADC for further conversions
123 // ADC->SWTRIG.bit.FLUSH = 1;
124
125 while( ADC->STATUS.bit.SYNCBUSY == 1 || ADC->SWTRIG.bit.FLUSH == 1 )
126 {
127 // Waiting for synchronization
128 }
129
130 //valueRead = mapResolution(valueRead, ADC_RESOLUTION, _readResolution);
131 return valueRead;
132
133}
134
135
136// Right now, PWM output only works on the pins with
137// hardware support. These are defined in the appropriate
138// pins_*.c file. For the rest of the pins, we default
139// to digital output.
140void analogWrite( uint32_t ulPin, uint32_t ulValue )
141{
142 uint32_t attr = g_APinDescription[ulPin].ulPinAttribute ;
143// uint32_t pwm_name = g_APinDescription[ulPin].ulTCChannel ;
144 uint8_t isTC = 0 ;
145 uint8_t Channelx ;
146 Tc* TCx ;
147 Tcc* TCCx ;
148
149 if ( (attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG )
150 {
151 if ( ulPin == 24 ) // Only 1 DAC on A0 (PA02)
152 {
153 ulValue = mapResolution(ulValue, _writeResolution, DAC_RESOLUTION);
154 DAC->DATA.reg = ulValue & 0x3FF; // Dac on 10 bits.
155 DAC->CTRLA.bit.ENABLE = 1; // DAC Enabled
156 syncDAC();
157 return;
158 }
159
160
161 }
162
163 if ( (attr & PIN_ATTR_PWM) == PIN_ATTR_PWM )
164 {
165 if ( (g_APinDescription[ulPin].ulPinType == PIO_TIMER) || g_APinDescription[ulPin].ulPinType == PIO_TIMER_ALT )
166 {
167 pinPeripheral( ulPin, g_APinDescription[ulPin].ulPinType ) ;
168 }
169
170 switch ( g_APinDescription[ulPin].ulPWMChannel )
171 {
172 case PWM3_CH0 :
173 TCx = TC3 ;
174 Channelx = 0 ;
175 isTC = 1 ;
176 break;
177
178 case PWM3_CH1:
179 TCx = TC3 ;
180 Channelx = 1;
181 isTC = 1;
182 break;
183
184 case PWM0_CH0 :
185 TCCx = TCC0;
186 Channelx = 0;
187 break;
188
189 case PWM0_CH1 :
190 TCCx = TCC0;
191 Channelx = 1;
192 break;
193
194 case PWM0_CH4 :
195 TCCx = TCC0;
196 Channelx = 0;
197 break;
198
199 case PWM0_CH5 :
200 TCCx = TCC0;
201 Channelx = 1;
202 break;
203
204 case PWM0_CH6 :
205 TCCx = TCC0;
206 Channelx = 2;
207 break;
208
209 case PWM0_CH7 :
210 TCCx = TCC0;
211 Channelx = 3;
212 break;
213
214 case PWM1_CH0 :
215 TCCx = TCC1;
216 Channelx = 0;
217 break;
218
219 case PWM1_CH1 :
220 TCCx = TCC1;
221 Channelx = 1;
222 break;
223
224 case PWM2_CH0 :
225 TCCx = TCC2;
226 Channelx = 0;
227 break;
228
229 case PWM2_CH1 :
230 TCCx = TCC2;
231 Channelx = 1;
232 break;
233 }
234
235
236 // Enable clocks according to TCCx instance to use
237 switch ( GetTCNumber( g_APinDescription[ulPin].ulPWMChannel ) )
238 {
239 case 0: // TCC0
240 //Enable GCLK for TCC0 (timer counter input clock)
241 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
242 break;
243
244 case 1: // TCC1
245 //Enable GCLK for TCC1 (timer counter input clock)
246 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
247 break;
248
249 case 2: // TCC2
250 //Enable GCLK for TCC2 (timer counter input clock)
251 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ;
252 break;
253
254 case 3: // TC3
255 //Enable GCLK for TC3 (timer counter input clock)
256 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
257 break;
258
259 case 4: // TC4
260 //Enable GCLK for TC4 (timer counter input clock)
261 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
262 break;
263
264 case 5: // TC5
265 //Enable GCLK for TC5 (timer counter input clock)
266 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 )) ;
267 break;
268 }
269
270 // Set PORT
271 if ( isTC )
272 {
273 // -- Configure TC
274 //DISABLE TCx
275 TCx->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
276 //Set Timer counter Mode to 8 bits
277 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8;
278 //Set TCx as normal PWM
279 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
280 //Set TCx in waveform mode Normal PWM
281 TCx->COUNT8.CC[Channelx].reg = (uint8_t) ulValue;
282 //Set PER to maximum counter value (resolution : 0xFF)
283 TCx->COUNT8.PER.reg = 0xFF;
284 // Enable TCx
285 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
286 }
287 else
288 {
289 // -- Configure TCC
290
291 //DISABLE TCCx
292 TCCx->CTRLA.reg &=~(TCC_CTRLA_ENABLE);
293 //Set TCx as normal PWM
294 TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
295 //Set TCx in waveform mode Normal PWM
296 TCCx->CC[Channelx].reg = (uint32_t)ulValue;
297 //Set PER to maximum counter value (resolution : 0xFF)
298 TCCx->PER.reg = 0xFF;
299 //ENABLE TCCx
300 TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
301 }
302
303 return ;
304 }
305
306 // -- Defaults to digital write
307 pinMode( ulPin, OUTPUT ) ;
308
309 if ( ulValue < 128 )
310 {
311 digitalWrite( ulPin, LOW ) ;
312 }
313 else
314 {
315 digitalWrite( ulPin, HIGH ) ;
316 }
317}
318
319#ifdef __cplusplus
320}
321#endif
Note: See TracBrowser for help on using the repository browser.