1
1
2
- #include " ../hardware_api .h"
2
+ #include " samd21_mcu .h"
3
3
4
- // this code was pulled from Paul Gould's git https://github.com/gouldpa/FOC-Arduino-Brushless
5
- static uint32_t ADC_OneBeforeFirstPin; // hack to discard first noisy readout
6
- static uint32_t ADC_FirstPin; // PA04
7
- static uint32_t ADC_LastPin; // PA06
8
- static uint32_t BufferSize = 0 ;
9
4
10
- uint16_t adcBuffer[20 ];
5
+ void adc_stop_with_DMA (void );
6
+ void adc_start_with_DMA (void );
11
7
8
+ /* *
9
+ * @brief ADC sync wait
10
+ * @retval void
11
+ */
12
+ static __inline__ void ADCsync () __attribute__((always_inline, unused));
13
+ static void ADCsync () {
14
+ while (ADC->STATUS .bit .SYNCBUSY == 1 ); // Just wait till the ADC is free
15
+ }
16
+
17
+ // ADC DMA sequential free running (6) with Interrupts /////////////////
18
+
19
+ typedef struct {
20
+ uint16_t btctrl;
21
+ uint16_t btcnt;
22
+ uint32_t srcaddr;
23
+ uint32_t dstaddr;
24
+ uint32_t descaddr;
25
+ } dmacdescriptor ;
26
+ volatile dmacdescriptor wrb[12 ] __attribute__ ((aligned (16 )));
27
+ dmacdescriptor descriptor_section[12 ] __attribute__ ((aligned (16 )));
28
+ dmacdescriptor descriptor __attribute__ ((aligned (16 )));
29
+ DmacDescriptor *desc; // DMA descriptor address (so we can change contents)
12
30
13
- static uint32_t ADC_pinA = A4;
14
- static uint32_t ADC_pinB = A5;
15
- static uint32_t ADC_pinC = 8 ;
16
31
17
32
18
- #define _ADC_VOLTAGE 3.3 // we use ADC_REFCTRL_REFSEL_INTVCC1_Val
19
- #define _ADC_RESOLUTION (1 << 12 )
20
- #define ADC_CONV_ ( _ADC_VOLTAGE / _ADC_RESOLUTION )
33
+ SAMDCurrentSensceADC::SAMDCurrentSensceADC (int pinA, int pinB, int pinC, float arefaVoltage, uint32_t adcBits)
34
+ : _ADC_VOLTAGE(arefaVoltage), _ADC_RESOLUTION(1 << adcBits)
35
+ {
36
+ ADC_CONV_ = ( _ADC_VOLTAGE / _ADC_RESOLUTION );
37
+ this ->pinA = pinA;
38
+ this ->pinB = pinB;
39
+ this ->pinC = pinC;
40
+ }
41
+
42
+ void SAMDCurrentSensceADC::init ()
43
+ {
44
+ _configure3PinsDMA ();
45
+ _start3PinsDMA (); // s
46
+ }
21
47
22
- void adc_dma (void *rxdata, size_t hwords);
23
- void adc_init ();
24
- void adc_start_with_DMA ();
25
- void dma_init ();
26
48
27
- void _start3PinsDMA ()
49
+ void SAMDCurrentSensceADC:: _start3PinsDMA ()
28
50
{
29
51
adc_dma (adcBuffer + ADC_OneBeforeFirstPin, BufferSize);
30
52
adc_start_with_DMA ();
31
53
}
32
- void _read3PinsDMA (const int pinA,const int pinB,const int pinC, float & a, float & b, float & c)
54
+ void SAMDCurrentSensceADC:: _read3PinsDMA (const int pinA,const int pinB,const int pinC, float & a, float & b, float & c)
33
55
{
34
56
while (ADC->CTRLA .bit .ENABLE ) ;
35
57
uint32_t adcA = g_APinDescription[pinA].ulADCChannelNumber ;
@@ -44,7 +66,7 @@ void _read3PinsDMA(const int pinA,const int pinB,const int pinC, float & a, floa
44
66
}
45
67
46
68
// function reading an ADC value and returning the read voltage
47
- void _configure3PinsDMA (const int pinA, const int pinB, const int pinC ){
69
+ void SAMDCurrentSensceADC:: _configure3PinsDMA (){
48
70
49
71
uint32_t adcA = g_APinDescription[pinA].ulADCChannelNumber ;
50
72
uint32_t adcB = g_APinDescription[pinB].ulADCChannelNumber ;
@@ -65,52 +87,24 @@ void _configure3PinsDMA(const int pinA,const int pinB,const int pinC){
65
87
ADC_OneBeforeFirstPin = ADC_FirstPin - 1 ; // hack to discard noisy first readout
66
88
BufferSize = ADC_LastPin - ADC_OneBeforeFirstPin + 1 ;
67
89
68
- ADC_pinA = pinA;
69
- ADC_pinB = pinB;
70
- ADC_pinC = pinC;
71
-
72
90
// ADC and DMA
73
91
adc_init ();
74
92
dma_init ();
75
93
}
76
94
77
95
78
96
79
- // ADC DMA sequential free running (6) with Interrupts /////////////////
80
-
81
- typedef struct {
82
- uint16_t btctrl;
83
- uint16_t btcnt;
84
- uint32_t srcaddr;
85
- uint32_t dstaddr;
86
- uint32_t descaddr;
87
- } dmacdescriptor ;
88
- volatile dmacdescriptor wrb[12 ] __attribute__ ((aligned (16 )));
89
- dmacdescriptor descriptor_section[12 ] __attribute__ ((aligned (16 )));
90
- dmacdescriptor descriptor __attribute__ ((aligned (16 )));
91
- DmacDescriptor *desc; // DMA descriptor address (so we can change contents)
92
-
93
- static uint32_t ADC_DMA_chnl = 3 ; // DMA channel
94
97
95
98
96
- /* *
97
- * @brief ADC sync wait
98
- * @retval void
99
- */
100
- static __inline__ void ADCsync () __attribute__((always_inline, unused));
101
- static void ADCsync () {
102
- while (ADC->STATUS .bit .SYNCBUSY == 1 ); // Just wait till the ADC is free
103
- }
104
-
105
99
/* *
106
100
* @brief Initialize ADC
107
101
* @retval void
108
102
*/
109
- void adc_init (){
103
+ void SAMDCurrentSensceADC:: adc_init (){
110
104
111
- auto a = analogRead (ADC_pinA ); // do some pin init pinPeripheral()
112
- auto b = analogRead (ADC_pinB ); // do some pin init pinPeripheral()
113
- auto c = analogRead (ADC_pinC ); // do some pin init pinPeripheral()
105
+ analogRead (pinA ); // do some pin init pinPeripheral()
106
+ analogRead (pinB ); // do some pin init pinPeripheral()
107
+ analogRead (pinC ); // do some pin init pinPeripheral()
114
108
115
109
ADC->CTRLA .bit .ENABLE = 0x00 ; // Disable ADC
116
110
ADCsync ();
@@ -121,62 +115,55 @@ void adc_init(){
121
115
// ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0;
122
116
ADCsync (); // ref 31.6.16
123
117
124
- a = analogRead (ADC_pinA); // do some pin init pinPeripheral()
125
- b = analogRead (ADC_pinB); // do some pin init pinPeripheral()
126
- c = analogRead (ADC_pinC); // do some pin init pinPeripheral()
127
- SerialUSB.println (" --------------" );
128
- SerialUSB.println (a);
129
- SerialUSB.println (b);
130
- SerialUSB.println (c);
131
- SerialUSB.println (" --------------" );
132
- /*
133
- Bits 19:16 – INPUTSCAN[3:0]: Number of Input Channels Included in Scan
134
- This register gives the number of input sources included in the pin scan. The number of input sources included is
135
- INPUTSCAN + 1. The input channels included are in the range from MUXPOS + INPUTOFFSET to MUXPOS +
136
- INPUTOFFSET + INPUTSCAN.
137
- The range of the scan mode must not exceed the number of input channels available on the device.
138
- Bits 4:0 – MUXPOS[4:0]: Positive Mux Input Selection
139
- These bits define the Mux selection for the positive ADC input. Table 32-14 shows the possible input selections. If
140
- the internal bandgap voltage or temperature sensor input channel is selected, then the Sampling Time Length bit
141
- group in the SamplingControl register must be written.
142
- Table 32-14. Positive Mux Input Selection
143
- MUXPOS[4:0] Group configuration Description
144
- 0x00 PIN0 ADC AIN0 pin
145
- 0x01 PIN1 ADC AIN1 pin
146
- 0x02 PIN2 ADC AIN2 pin
147
- 0x03 PIN3 ADC AIN3 pin
148
- 0x04 PIN4 ADC AIN4 pin
149
- 0x05 PIN5 ADC AIN5 pin
150
- 0x06 PIN6 ADC AIN6 pin
151
- 0x07 PIN7 ADC AIN7 pin
152
- 0x08 PIN8 ADC AIN8 pin
153
- 0x09 PIN9 ADC AIN9 pin
154
- 0x0A PIN10 ADC AIN10 pin
155
- 0x0B PIN11 ADC AIN11 pin
156
- 0x0C PIN12 ADC AIN12 pin
157
- 0x0D PIN13 ADC AIN13 pin
158
- 0x0E PIN14 ADC AIN14 pin
159
- 0x0F PIN15 ADC AIN15 pin
160
- 0x10 PIN16 ADC AIN16 pin
161
- 0x11 PIN17 ADC AIN17 pin
162
- 0x12 PIN18 ADC AIN18 pin
163
- 0x13 PIN19 ADC AIN19 pin
164
- 0x14-0x17 Reserved
165
- 0x18 TEMP Temperature reference
166
- 0x19 BANDGAP Bandgap voltage
167
- 0x1A SCALEDCOREVCC 1/4 scaled core supply
168
- 0x1B SCALEDIOVCC 1/4 scaled I/O supply
169
- 0x1C DAC DAC output
170
- 0x1D-0x1F Reserved
171
- */
118
+ /*
119
+ Bits 19:16 – INPUTSCAN[3:0]: Number of Input Channels Included in Scan
120
+ This register gives the number of input sources included in the pin scan. The number of input sources included is
121
+ INPUTSCAN + 1. The input channels included are in the range from MUXPOS + INPUTOFFSET to MUXPOS +
122
+ INPUTOFFSET + INPUTSCAN.
123
+ The range of the scan mode must not exceed the number of input channels available on the device.
124
+ Bits 4:0 – MUXPOS[4:0]: Positive Mux Input Selection
125
+ These bits define the Mux selection for the positive ADC input. Table 32-14 shows the possible input selections. If
126
+ the internal bandgap voltage or temperature sensor input channel is selected, then the Sampling Time Length bit
127
+ group in the SamplingControl register must be written.
128
+ Table 32-14. Positive Mux Input Selection
129
+ MUXPOS[4:0] Group configuration Description
130
+ 0x00 PIN0 ADC AIN0 pin
131
+ 0x01 PIN1 ADC AIN1 pin
132
+ 0x02 PIN2 ADC AIN2 pin
133
+ 0x03 PIN3 ADC AIN3 pin
134
+ 0x04 PIN4 ADC AIN4 pin
135
+ 0x05 PIN5 ADC AIN5 pin
136
+ 0x06 PIN6 ADC AIN6 pin
137
+ 0x07 PIN7 ADC AIN7 pin
138
+ 0x08 PIN8 ADC AIN8 pin
139
+ 0x09 PIN9 ADC AIN9 pin
140
+ 0x0A PIN10 ADC AIN10 pin
141
+ 0x0B PIN11 ADC AIN11 pin
142
+ 0x0C PIN12 ADC AIN12 pin
143
+ 0x0D PIN13 ADC AIN13 pin
144
+ 0x0E PIN14 ADC AIN14 pin
145
+ 0x0F PIN15 ADC AIN15 pin
146
+ 0x10 PIN16 ADC AIN16 pin
147
+ 0x11 PIN17 ADC AIN17 pin
148
+ 0x12 PIN18 ADC AIN18 pin
149
+ 0x13 PIN19 ADC AIN19 pin
150
+ 0x14-0x17 Reserved
151
+ 0x18 TEMP Temperature reference
152
+ 0x19 BANDGAP Bandgap voltage
153
+ 0x1A SCALEDCOREVCC 1/4 scaled core supply
154
+ 0x1B SCALEDIOVCC 1/4 scaled I/O supply
155
+ 0x1C DAC DAC output
156
+ 0x1D-0x1F Reserved
157
+ */
172
158
ADC->INPUTCTRL .bit .MUXPOS = ADC_OneBeforeFirstPin;
173
159
ADCsync ();
174
160
ADC->INPUTCTRL .bit .INPUTSCAN = ADC_LastPin; // so the adc will scan from AIN[1] to AIN[ADC_Number+1]
175
161
ADCsync ();
176
162
ADC->INPUTCTRL .bit .INPUTOFFSET = 0 ; // input scan cursor
177
163
ADCsync ();
178
164
ADC->AVGCTRL .reg = 0x00 ; // no averaging
179
- ADC->SAMPCTRL .reg = 0x05 ; ; // sample length in 1/2 CLK_ADC cycles
165
+ ADC->SAMPCTRL .reg = 0x05 ; ; // sample length in 1/2 CLK_ADC cycles, see GCLK_ADC and ADC_CTRLB_PRESCALER_DIV16
166
+ // according to the specsheet: f_GCLK_ADC ADC input clock frequency 48 MHz, so same as fCPU
180
167
ADCsync ();
181
168
ADC->CTRLB .reg = ADC_CTRLB_PRESCALER_DIV16 | ADC_CTRLB_FREERUN | ADC_CTRLB_RESSEL_12BIT;
182
169
ADCsync ();
@@ -187,7 +174,7 @@ MUXPOS[4:0] Group configuration Description
187
174
* @brief dma_init
188
175
* @retval void
189
176
*/
190
- void dma_init () {
177
+ void SAMDCurrentSensceADC:: dma_init () {
191
178
// probably on by default
192
179
PM->AHBMASK .reg |= PM_AHBMASK_DMAC ;
193
180
PM->APBBMASK .reg |= PM_APBBMASK_DMAC ;
@@ -201,15 +188,15 @@ void dma_init() {
201
188
* @brief adc_dma
202
189
* @retval void
203
190
*/
204
- void adc_dma (void *rxdata, size_t hwords) {
191
+ void SAMDCurrentSensceADC:: adc_dma (void *rxdata, size_t hwords) {
205
192
uint32_t temp_CHCTRLB_reg;
206
193
207
194
DMAC->CHID .reg = DMAC_CHID_ID (ADC_DMA_chnl);
208
195
DMAC->CHCTRLA .reg &= ~DMAC_CHCTRLA_ENABLE;
209
196
DMAC->CHCTRLA .reg = DMAC_CHCTRLA_SWRST;
210
197
DMAC->SWTRIGCTRL .reg &= (uint32_t )(~(1 << ADC_DMA_chnl));
211
198
temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL (0 ) |
212
- DMAC_CHCTRLB_TRIGSRC (ADC_DMAC_ID_RESRDY) | DMAC_CHCTRLB_TRIGACT_BEAT;
199
+ DMAC_CHCTRLB_TRIGSRC (ADC_DMAC_ID_RESRDY) | DMAC_CHCTRLB_TRIGACT_BEAT;
213
200
DMAC->CHCTRLB .reg = temp_CHCTRLB_reg;
214
201
DMAC->CHINTENSET .reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts
215
202
descriptor.descaddr = 0 ;
@@ -224,6 +211,9 @@ DMAC_CHCTRLB_TRIGSRC(ADC_DMAC_ID_RESRDY) | DMAC_CHCTRLB_TRIGACT_BEAT;
224
211
DMAC->CHCTRLA .reg |= DMAC_CHCTRLA_ENABLE;
225
212
}
226
213
214
+
215
+
216
+
227
217
/* *
228
218
* @brief adc_stop_with_DMA
229
219
* @retval void
@@ -241,16 +231,12 @@ void adc_stop_with_DMA(void)
241
231
void adc_start_with_DMA (void )
242
232
{
243
233
// SerialUSB.println("strating DMA...");
244
-
245
-
246
- ADC->INPUTCTRL .bit .MUXPOS = ADC_OneBeforeFirstPin;
247
- ADC->INPUTCTRL .bit .INPUTSCAN = ADC_LastPin;
234
+ // ADC->INPUTCTRL.bit.MUXPOS = ADC_OneBeforeFirstPin;
235
+ // ADC->INPUTCTRL.bit.INPUTSCAN = ADC_LastPin;
248
236
ADC->INPUTCTRL .bit .INPUTOFFSET = 0 ;
249
237
ADC->SWTRIG .bit .FLUSH = 1 ;
250
238
ADC->CTRLA .bit .ENABLE = 0x01 ;
251
239
}
252
-
253
-
254
240
/* *
255
241
* @brief DMAC_Handler
256
242
* @retval void
@@ -263,4 +249,4 @@ void DMAC_Handler() {
263
249
DMAC->CHINTFLAG .reg = DMAC_CHINTENCLR_TCMPL; // clear
264
250
DMAC->CHINTFLAG .reg = DMAC_CHINTENCLR_TERR;
265
251
DMAC->CHINTFLAG .reg = DMAC_CHINTENCLR_SUSP;
266
- }
252
+ }
0 commit comments