@@ -189,7 +189,8 @@ uint32_t analogRead(uint32_t pin)
189
189
// to digital output.
190
190
void analogWrite (uint32_t pin , uint32_t value )
191
191
{
192
- uint32_t attr = g_APinDescription [pin ].ulPinAttribute ;
192
+ PinDescription pinDesc = g_APinDescription [pin ];
193
+ uint32_t attr = pinDesc .ulPinAttribute ;
193
194
194
195
if ((attr & PIN_ATTR_ANALOG ) == PIN_ATTR_ANALOG )
195
196
{
@@ -211,104 +212,96 @@ void analogWrite(uint32_t pin, uint32_t value)
211
212
212
213
if ((attr & PIN_ATTR_PWM ) == PIN_ATTR_PWM )
213
214
{
214
- if (attr & PIN_ATTR_TIMER ) {
215
- #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603 )
216
- // Compatibility for cores based on SAMD core <=1.6.2
217
- if (g_APinDescription [pin ].ulPinType == PIO_TIMER_ALT ) {
215
+ value = mapResolution (value , _writeResolution , 8 );
216
+
217
+ uint32_t tcNum = GetTCNumber (pinDesc .ulPWMChannel );
218
+ uint8_t tcChannel = GetTCChannelNumber (pinDesc .ulPWMChannel );
219
+ static bool tcEnabled [TCC_INST_NUM + TC_INST_NUM ];
220
+
221
+ if (!tcEnabled [tcNum ]) {
222
+ tcEnabled [tcNum ] = true;
223
+
224
+ if (attr & PIN_ATTR_TIMER ) {
225
+ #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603 )
226
+ // Compatibility for cores based on SAMD core <=1.6.2
227
+ if (pinDesc .ulPinType == PIO_TIMER_ALT ) {
228
+ pinPeripheral (pin , PIO_TIMER_ALT );
229
+ } else
230
+ #endif
231
+ {
232
+ pinPeripheral (pin , PIO_TIMER );
233
+ }
234
+ } else {
235
+ // We suppose that attr has PIN_ATTR_TIMER_ALT bit set...
218
236
pinPeripheral (pin , PIO_TIMER_ALT );
219
- } else
220
- #endif
221
- {
222
- pinPeripheral (pin , PIO_TIMER );
223
237
}
224
- } else {
225
- // We suppose that attr has PIN_ATTR_TIMER_ALT bit set...
226
- pinPeripheral (pin , PIO_TIMER_ALT );
227
- }
228
238
229
- Tc * TCx = NULL ;
230
- Tcc * TCCx = NULL ;
231
- uint8_t Channelx = GetTCChannelNumber (g_APinDescription [pin ].ulPWMChannel );
232
- if (GetTCNumber (g_APinDescription [pin ].ulPWMChannel ) >= TCC_INST_NUM ) {
233
- TCx = (Tc * ) GetTC (g_APinDescription [pin ].ulPWMChannel );
239
+ uint16_t GCLK_CLKCTRL_IDs [] = {
240
+ GCLK_CLKCTRL_ID (GCM_TCC0_TCC1 ), // TCC0
241
+ GCLK_CLKCTRL_ID (GCM_TCC0_TCC1 ), // TCC1
242
+ GCLK_CLKCTRL_ID (GCM_TCC2_TC3 ), // TCC2
243
+ GCLK_CLKCTRL_ID (GCM_TCC2_TC3 ), // TC3
244
+ GCLK_CLKCTRL_ID (GCM_TC4_TC5 ), // TC4
245
+ GCLK_CLKCTRL_ID (GCM_TC4_TC5 ), // TC5
246
+ GCLK_CLKCTRL_ID (GCM_TC6_TC7 ), // TC6
247
+ GCLK_CLKCTRL_ID (GCM_TC6_TC7 ), // TC7
248
+ };
249
+ GCLK -> CLKCTRL .reg = (uint16_t ) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs [tcNum ]);
250
+ while (GCLK -> STATUS .bit .SYNCBUSY == 1 );
251
+
252
+ // Set PORT
253
+ if (tcNum >= TCC_INST_NUM ) {
254
+ // -- Configure TC
255
+ Tc * TCx = (Tc * ) GetTC (pinDesc .ulPWMChannel );
256
+ // Disable TCx
257
+ TCx -> COUNT8 .CTRLA .bit .ENABLE = 0 ;
258
+ syncTC_8 (TCx );
259
+ // Set Timer counter Mode to 8 bits, normal PWM
260
+ TCx -> COUNT8 .CTRLA .reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_WAVEGEN_NPWM ;
261
+ syncTC_8 (TCx );
262
+ // Set the initial value
263
+ TCx -> COUNT8 .CC [tcChannel ].reg = (uint8_t ) value ;
264
+ syncTC_8 (TCx );
265
+ // Set PER to maximum counter value (resolution : 0xFF)
266
+ TCx -> COUNT8 .PER .reg = 0xFF ;
267
+ syncTC_8 (TCx );
268
+ // Enable TCx
269
+ TCx -> COUNT8 .CTRLA .bit .ENABLE = 1 ;
270
+ syncTC_8 (TCx );
271
+ } else {
272
+ // -- Configure TCC
273
+ Tcc * TCCx = (Tcc * ) GetTC (pinDesc .ulPWMChannel );
274
+ // Disable TCCx
275
+ TCCx -> CTRLA .bit .ENABLE = 0 ;
276
+ syncTCC (TCCx );
277
+ // Set TCx as normal PWM
278
+ TCCx -> WAVE .reg |= TCC_WAVE_WAVEGEN_NPWM ;
279
+ syncTCC (TCCx );
280
+ // Set the initial value
281
+ TCCx -> CC [tcChannel ].reg = (uint32_t ) value ;
282
+ syncTCC (TCCx );
283
+ // Set PER to maximum counter value (resolution : 0xFF)
284
+ TCCx -> PER .reg = 0xFF ;
285
+ syncTCC (TCCx );
286
+ // Enable TCCx
287
+ TCCx -> CTRLA .bit .ENABLE = 1 ;
288
+ syncTCC (TCCx );
289
+ }
234
290
} else {
235
- TCCx = (Tcc * ) GetTC (g_APinDescription [pin ].ulPWMChannel );
236
- }
237
-
238
- // Enable clocks according to TCCx instance to use
239
- switch (GetTCNumber (g_APinDescription [pin ].ulPWMChannel ))
240
- {
241
- case 0 : // TCC0
242
- case 1 : // TCC1
243
- // Enable GCLK for TCC0 and TCC1 (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 2 : // TCC2
248
- case 3 : // TC3
249
- // Enable GCLK for TCC2 and TC3 (timer counter input clock)
250
- GCLK -> CLKCTRL .reg = (uint16_t ) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID (GCM_TCC2_TC3 ));
251
- break ;
252
-
253
- case 4 : // TC4
254
- case 5 : // TC5
255
- // Enable GCLK for TC4 and TC5 (timer counter input clock)
256
- GCLK -> CLKCTRL .reg = (uint16_t ) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID (GCM_TC4_TC5 ));
257
- break ;
258
-
259
- case 6 : // TC6 (not available on Zero)
260
- case 7 : // TC7 (not available on Zero)
261
- // Enable GCLK for TC6 and TC7 (timer counter input clock)
262
- GCLK -> CLKCTRL .reg = (uint16_t ) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID (GCM_TC6_TC7 ));
263
- break ;
264
- }
265
-
266
- while (GCLK -> STATUS .bit .SYNCBUSY == 1 );
267
-
268
- value = mapResolution (value , _writeResolution , 8 );
269
-
270
- // Set PORT
271
- if (TCx )
272
- {
273
- // -- Configure TC
274
-
275
- // Disable TCx
276
- TCx -> COUNT8 .CTRLA .reg &= ~TC_CTRLA_ENABLE ;
277
- syncTC_8 (TCx );
278
- // Set Timer counter Mode to 8 bits
279
- TCx -> COUNT8 .CTRLA .reg |= TC_CTRLA_MODE_COUNT8 ;
280
- // Set TCx as normal PWM
281
- TCx -> COUNT8 .CTRLA .reg |= TC_CTRLA_WAVEGEN_NPWM ;
282
- // Set TCx in waveform mode Normal PWM
283
- TCx -> COUNT8 .CC [Channelx ].reg = (uint8_t ) value ;
284
- syncTC_8 (TCx );
285
- // Set PER to maximum counter value (resolution : 0xFF)
286
- TCx -> COUNT8 .PER .reg = 0xFF ;
287
- syncTC_8 (TCx );
288
- // Enable TCx
289
- TCx -> COUNT8 .CTRLA .reg |= TC_CTRLA_ENABLE ;
290
- syncTC_8 (TCx );
291
- }
292
- else
293
- {
294
- // -- Configure TCC
295
- // Disable TCCx
296
- TCCx -> CTRLA .reg &= ~TCC_CTRLA_ENABLE ;
297
- syncTCC (TCCx );
298
- // Set TCx as normal PWM
299
- TCCx -> WAVE .reg |= TCC_WAVE_WAVEGEN_NPWM ;
300
- syncTCC (TCCx );
301
- // Set TCx in waveform mode Normal PWM
302
- TCCx -> CC [Channelx ].reg = (uint32_t )value ;
303
- syncTCC (TCCx );
304
- // Set PER to maximum counter value (resolution : 0xFF)
305
- TCCx -> PER .reg = 0xFF ;
306
- syncTCC (TCCx );
307
- // Enable TCCx
308
- TCCx -> CTRLA .reg |= TCC_CTRLA_ENABLE ;
309
- syncTCC (TCCx );
291
+ if (tcNum >= TCC_INST_NUM ) {
292
+ Tc * TCx = (Tc * ) GetTC (pinDesc .ulPWMChannel );
293
+ TCx -> COUNT8 .CC [tcChannel ].reg = (uint8_t ) value ;
294
+ syncTC_8 (TCx );
295
+ } else {
296
+ Tcc * TCCx = (Tcc * ) GetTC (pinDesc .ulPWMChannel );
297
+ TCCx -> CTRLBSET .bit .LUPD = 1 ;
298
+ syncTCC (TCCx );
299
+ TCCx -> CCB [tcChannel ].reg = (uint32_t ) value ;
300
+ syncTCC (TCCx );
301
+ TCCx -> CTRLBCLR .bit .LUPD = 1 ;
302
+ syncTCC (TCCx );
303
+ }
310
304
}
311
-
312
305
return ;
313
306
}
314
307
0 commit comments