@@ -189,7 +189,8 @@ uint32_t analogRead(uint32_t pin)
189189// to digital output.
190190void analogWrite (uint32_t pin , uint32_t value )
191191{
192- uint32_t attr = g_APinDescription [pin ].ulPinAttribute ;
192+ PinDescription pinDesc = g_APinDescription [pin ];
193+ uint32_t attr = pinDesc .ulPinAttribute ;
193194
194195 if ((attr & PIN_ATTR_ANALOG ) == PIN_ATTR_ANALOG )
195196 {
@@ -211,104 +212,92 @@ void analogWrite(uint32_t pin, uint32_t value)
211212
212213 if ((attr & PIN_ATTR_PWM ) == PIN_ATTR_PWM )
213214 {
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...
218236 pinPeripheral (pin , PIO_TIMER_ALT );
219- } else
220- #endif
221- {
222- pinPeripheral (pin , PIO_TIMER );
223237 }
224- } else {
225- // We suppose that attr has PIN_ATTR_TIMER_ALT bit set...
226- pinPeripheral (pin , PIO_TIMER_ALT );
227- }
228238
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+ }
234290 } 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 -> CC [tcChannel ].reg = (uint32_t ) value ;
298+ syncTCC (TCCx );
299+ }
310300 }
311-
312301 return ;
313302 }
314303
0 commit comments