11#include " Arduino.h"
22
33XMC_PWM4_t *pwm4;
4+ static volatile bool timer_interrupt_ccu4 = false ;
5+ static volatile bool timer_interrupt_ccu8 = false ;
6+
7+ #ifdef __cplusplus
8+ extern " C" {
9+ #endif
10+ void CCU43_0_IRQHandler (void ) {
11+
12+ XMC_CCU4_SLICE_StopTimer (CCU43_CC40);
13+ XMC_CCU4_SLICE_ClearEvent (CCU43_CC40, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
14+ timer_interrupt_ccu4 = true ;
15+
16+ }
17+
18+ void CCU81_0_IRQHandler (void ) {
19+ XMC_CCU8_SLICE_StopTimer (CCU81_CC80);
20+ XMC_CCU8_SLICE_ClearEvent (CCU81_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
21+ timer_interrupt_ccu8 = true ;
22+ }
23+ #ifdef __cplusplus
24+ }
25+ #endif
426
527class Tone {
628public:
@@ -18,12 +40,14 @@ class Tone {
1840 XMC_GPIO_SetMode (pwm4->port_pin .port , pwm4->port_pin .pin ,
1941 (XMC_GPIO_MODE_t)(XMC_GPIO_MODE_OUTPUT_PUSH_PULL | pwm4->port_mode ));
2042 XMC_CCU4_SLICE_StartTimer (pwm4->slice );
21- if (duration >0 ) {
22- unsigned long start_time = millis ();
23- while (millis () - start_time < duration) {
24- delay (1 );
43+ if (duration >0 ) {
44+ configureTimerInterrupt (duration);
45+ if (timer_interrupt_ccu4 == true )
46+ {
47+ XMC_CCU4_SLICE_StopTimer (pwm4->slice );
48+ timer_interrupt_ccu4 = false ;
49+
2550 }
26- XMC_CCU4_SLICE_StopTimer (pwm4->slice );
2751 }
2852 }
2953#if defined(CCU8V2) || defined(CCU8V1)
@@ -34,15 +58,18 @@ class Tone {
3458 (XMC_GPIO_MODE_t)(XMC_GPIO_MODE_OUTPUT_PUSH_PULL | pwm8->port_mode ));
3559 XMC_CCU8_SLICE_StartTimer (pwm8->slice );
3660 // calculate pulses
37- if (duration >0 ) {
38- unsigned long start_time = millis ();
39- while (millis () - start_time < duration) {
40- delay (1 );
61+ if (duration >0 ) {
62+ configureTimerInterrupt (duration);
63+ if (timer_interrupt_ccu8 == true )
64+ {
65+ XMC_CCU8_SLICE_StopTimer (pwm8->slice );
66+ timer_interrupt_ccu8 = false ;
67+
4168 }
42- XMC_CCU8_SLICE_StopTimer (pwm8->slice );
4369 }
4470 }
4571#endif
72+
4673 }
4774
4875 void stop (pin_size_t pin) {
@@ -65,6 +92,8 @@ class Tone {
6592private:
6693 void configureTone (pin_size_t pin, unsigned int frequency) {
6794 int pin_index;
95+ timer_interrupt_ccu4 = false ;
96+
6897 if ((pin_index = scanMapTable (mapping_pin_PWM4, pin)) >= 0 ) {
6998 XMC_PWM4_t *pwm4 = &mapping_pwm4[pin_index];
7099 XMC_CCU4_SLICE_COMPARE_CONFIG_t compare_config;
@@ -86,7 +115,6 @@ class Tone {
86115 }
87116#if defined(CCU8V2) || defined(CCU8V1)
88117 else if ((pin_index = scanMapTable (mapping_pin_PWM8, pin)) >= 0 ) {
89- Serial.println (" pin_index" );
90118 XMC_PWM8_t *pwm8 = &mapping_pwm8[pin_index];
91119 XMC_CCU8_SLICE_COMPARE_CONFIG_t compare_config;
92120 memset (&compare_config, 0 , sizeof (compare_config));
@@ -108,10 +136,78 @@ class Tone {
108136 XMC_CCU8_EnableShadowTransfer (
109137 pwm8->ccu , XMC_CCU8_SHADOW_TRANSFER_SLICE_0 | XMC_CCU8_SHADOW_TRANSFER_SLICE_2 |
110138 XMC_CCU8_SHADOW_TRANSFER_SLICE_3 | XMC_CCU8_SHADOW_TRANSFER_SLICE_1);
139+ timer_interrupt_ccu8 = false ;
140+
111141 }
112142#endif
113143 }
114144
145+ void configureTimerInterrupt (unsigned long duration_ms) {
146+ timer_interrupt_ccu4 = false ;
147+ XMC_CCU4_Init (CCU43, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
148+ XMC_CCU4_SLICE_COMPARE_CONFIG_t timer_config;
149+ timer_config.timer_mode = XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA;
150+ timer_config.monoshot = XMC_CCU4_SLICE_TIMER_REPEAT_MODE_SINGLE;
151+ timer_config.prescaler_mode = XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL;
152+ timer_config.prescaler_initval = XMC_CCU4_SLICE_PRESCALER_32768;
153+ timer_config.float_limit = XMC_CCU4_SLICE_PRESCALER_32768;
154+ timer_config.passive_level = XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
155+ XMC_CCU4_SLICE_CompareInit (CCU43_CC40, &timer_config);
156+
157+ // Calculate period for the timer based on the duration
158+ uint32_t timer_ticks = (PCLK / 32768 ) * duration_ms / 1000 ;
159+ XMC_CCU4_SLICE_SetTimerPeriodMatch (CCU43_CC40, timer_ticks);
160+ XMC_CCU4_SetMultiChannelShadowTransferMode (CCU43, XMC_CCU4_MULTI_CHANNEL_SHADOW_TRANSFER_SW_SLICE0);
161+ XMC_CCU4_EnableShadowTransfer (CCU43,XMC_CCU4_SHADOW_TRANSFER_SLICE_0);
162+ XMC_CCU4_SLICE_SetInterruptNode (CCU43_CC40, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH, XMC_CCU4_SLICE_SR_ID_0);
163+ XMC_CCU4_SLICE_EnableEvent (CCU43_CC40, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
164+ XMC_CCU4_EnableClock (CCU43, 0 );
165+
166+ // Enable the NVIC interrupt
167+ XMC_CCU4_SLICE_SetTimerValue (CCU43_CC40, 0U );
168+
169+ // Start the timer
170+ XMC_CCU4_SLICE_StartTimer (CCU43_CC40);
171+ NVIC_SetPriority (CCU43_0_IRQn, NVIC_EncodePriority (NVIC_GetPriorityGrouping (), 63 , 0 ));
172+
173+ NVIC_EnableIRQ (CCU43_0_IRQn);
174+
175+ #if defined(CCU8V2) || defined(CCU8V1)
176+ timer_interrupt_ccu8 = false ;
177+ XMC_CCU8_Init (CCU81, XMC_CCU8_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
178+ XMC_CCU8_SLICE_COMPARE_CONFIG_t timer_config_ccu8;
179+ timer_config_ccu8.timer_mode = XMC_CCU8_SLICE_TIMER_COUNT_MODE_EA;
180+ timer_config_ccu8.monoshot = XMC_CCU8_SLICE_TIMER_REPEAT_MODE_SINGLE;
181+ timer_config_ccu8.prescaler_mode = XMC_CCU8_SLICE_PRESCALER_MODE_NORMAL;
182+ timer_config_ccu8.prescaler_initval = XMC_CCU8_SLICE_PRESCALER_32768;
183+ timer_config_ccu8.float_limit = XMC_CCU8_SLICE_PRESCALER_32768;
184+ timer_config_ccu8.passive_level_out0 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
185+ timer_config_ccu8.passive_level_out1 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
186+ timer_config_ccu8.passive_level_out2 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
187+ timer_config_ccu8.passive_level_out3 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
188+
189+ XMC_CCU8_SLICE_CompareInit (CCU81_CC80, &timer_config_ccu8);
190+
191+ // Calculate period for the timer based on the duration
192+ uint32_t timer_ticks_ccu8 = (PCLK / 32768 ) * duration_ms / 1000 ;
193+ XMC_CCU8_SLICE_SetTimerPeriodMatch (CCU81_CC80, timer_ticks_ccu8);
194+ XMC_CCU8_SetMultiChannelShadowTransferMode (CCU81, XMC_CCU8_MULTI_CHANNEL_SHADOW_TRANSFER_SW_SLICE0);
195+ XMC_CCU8_EnableShadowTransfer (CCU81,XMC_CCU8_SHADOW_TRANSFER_SLICE_0);
196+ XMC_CCU8_SLICE_SetInterruptNode (CCU81_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH, XMC_CCU8_SLICE_SR_ID_0);
197+ XMC_CCU8_SLICE_EnableEvent (CCU81_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
198+ XMC_CCU8_EnableClock (CCU81, 0 );
199+
200+ // Enable the NVIC interrupt
201+ XMC_CCU8_SLICE_SetTimerValue (CCU81_CC80, 0U );
202+
203+ // Start the timer
204+ XMC_CCU8_SLICE_StartTimer (CCU81_CC80);
205+ NVIC_SetPriority (CCU81_0_IRQn, NVIC_EncodePriority (NVIC_GetPriorityGrouping (), 63 , 0 ));
206+
207+ NVIC_EnableIRQ (CCU81_0_IRQn);
208+ #endif
209+ }
210+
115211 // Scan the pwm pin mapping table
116212 int16_t scanMapTable (const uint8_t table[][2 ], uint8_t pin) {
117213 int16_t i = 0 ;
0 commit comments