Skip to content

Core api update tone #351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: core-api-update
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cores/xmc/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ extern "C" {

#define interrupts() __enable_irq()
#define noInterrupts() __disable_irq()
#define ENABLED 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these defines used?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In pins_arduino.h for ADC and PWM pins configurationsL like here: https://github.com/Infineon/XMC-for-Arduino/blob/master/variants/XMC4700/config/XMC4700_Relax_Kit/pins_arduino.h#L331
Maybe modify macro to be XMC_ENABLED or simply use false/true for all xmc struct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the naming is too generic for potential conflict with any other code not coming from XMC deciding to declare such.
We have already experienced that with macros like GPIO, ADC and such.
They help to understand more what that flag/variable does. But this is also not user level code, so maybe the simplest is to stay with true and false :)

#define DISABLED 0

#define DEFAULT XMC_VADC_CHANNEL_REF_INTREF /*< Default ADC reference voltage type */

Expand Down
198 changes: 198 additions & 0 deletions cores/xmc/Tone.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#include "Arduino.h"

XMC_PWM4_t *pwm4;

class Tone {
public:
Tone() {}

~Tone() {}

void play(pin_size_t pin, unsigned int frequency) { play(pin, frequency, 0); }

void play(pin_size_t pin, unsigned int frequency, unsigned long duration) {
int pin_index;
if ((pin_index = scanMapTable(mapping_pin_PWM4, pin)) >= 0) {
XMC_PWM4_t *pwm4 = &mapping_pwm4[pin_index];
configureTone(pin, frequency);
XMC_GPIO_SetMode(pwm4->port_pin.port, pwm4->port_pin.pin,
(XMC_GPIO_MODE_t)(XMC_GPIO_MODE_OUTPUT_PUSH_PULL | pwm4->port_mode));
XMC_CCU4_SLICE_StartTimer(pwm4->slice);
// count pulses for stop the timer once reached required pulses
// if (duration > 0) {
// uint32_t required_pulses = frequency * duration / 1000;
// for (uint32_t i = 0; i < required_pulses; i++) {
// while (
// !XMC_CCU4_SLICE_GetEvent(pwm4->slice,
// XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH)) {
// }
// XMC_CCU4_SLICE_ClearEvent(pwm4->slice, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
// }
// XMC_CCU4_SLICE_StopTimer(pwm4->slice);
// }
// if(duration >0) {
// unsigned long start_time = millis();
// while(millis() - start_time < duration) {
// delay(1);
// }
// XMC_CCU4_SLICE_StopTimer(pwm4->slice);
// }
if (duration > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if a duration is set the function is blocking or?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, I will change the logic. before, I used timer but one test case got failed due to time variation(100ms)
I will revisit and change.

configureTimerInterrupt(duration);
}
}
#if defined(CCU8V2) || defined(CCU8V1)
else if ((pin_index = scanMapTable(mapping_pin_PWM8, pin)) >= 0) {
XMC_PWM8_t *pwm8 = &mapping_pwm8[pin_index];
configureTone(pin, frequency);
XMC_GPIO_SetMode(pwm8->port_pin.port, pwm8->port_pin.pin,
(XMC_GPIO_MODE_t)(XMC_GPIO_MODE_OUTPUT_PUSH_PULL | pwm8->port_mode));
XMC_CCU8_SLICE_StartTimer(pwm8->slice);
// calculate pulses
// if (duration > 0) {
// uint32_t required_pulses = frequency * duration / 1000;
// for (uint32_t i = 0; i < required_pulses; i++) {
// while (
// !XMC_CCU8_SLICE_GetEvent(pwm8->slice,
// XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH)) {
// }
// XMC_CCU8_SLICE_ClearEvent(pwm8->slice, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
// }
// XMC_CCU8_SLICE_StopTimer(pwm8->slice);
// }
// if(duration >0) {
// unsigned long start_time = millis();
// while(millis() - start_time < duration) {
// delay(1);
// }
// XMC_CCU8_SLICE_StopTimer(pwm8->slice);
// }
if (duration > 0) {
configureTimerInterrupt(duration);
}
}
#endif
}

void stop(pin_size_t pin) {
int pin_index;
if ((pin_index = scanMapTable(mapping_pin_PWM4, pin)) >= 0) {
XMC_PWM4_t *_XMC_pwm4_config = &mapping_pwm4[pin_index];
XMC_CCU4_SLICE_StopTimer(_XMC_pwm4_config->slice); // stop the timer
XMC_CCU4_DisableClock(_XMC_pwm4_config->ccu,
_XMC_pwm4_config->slice_num); // Disable the clock
}
#if defined(CCU8V2) || defined(CCU8V1)
else if ((pin_index = scanMapTable(mapping_pin_PWM8, pin)) >= 0) {
XMC_PWM8_t *pwm8 = &mapping_pwm8[pin_index];
XMC_CCU8_SLICE_StopTimer(pwm8->slice); // stop the timer
XMC_CCU8_DisableClock(pwm8->ccu, pwm8->slice_num); // Disable the clock
}
#endif
}

private:
void configureTone(pin_size_t pin, unsigned int frequency) {
int pin_index;
if ((pin_index = scanMapTable(mapping_pin_PWM4, pin)) >= 0) {
XMC_PWM4_t *pwm4 = &mapping_pwm4[pin_index];
XMC_CCU4_SLICE_COMPARE_CONFIG_t compare_config;
memset(&compare_config, 0, sizeof(compare_config));
compare_config.prescaler_initval = pwm4->prescaler;
compare_config.passive_level = XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;

XMC_CCU4_Init(pwm4->ccu, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU4_SLICE_CompareInit(pwm4->slice, &compare_config);
XMC_CCU4_EnableClock(pwm4->ccu, pwm4->slice_num);

uint32_t period = (PCLK / 64) / frequency; // calculate period
XMC_CCU4_SLICE_SetTimerPeriodMatch(pwm4->slice, period);
XMC_CCU4_SLICE_SetTimerCompareMatch(pwm4->slice, period / 2);

XMC_CCU4_EnableShadowTransfer(
pwm4->ccu, XMC_CCU4_SHADOW_TRANSFER_SLICE_0 | XMC_CCU4_SHADOW_TRANSFER_SLICE_2 |
XMC_CCU4_SHADOW_TRANSFER_SLICE_3 | XMC_CCU4_SHADOW_TRANSFER_SLICE_1);
}
#if defined(CCU8V2) || defined(CCU8V1)
else if ((pin_index = scanMapTable(mapping_pin_PWM8, pin)) >= 0) {
Serial.println("pin_index");
XMC_PWM8_t *pwm8 = &mapping_pwm8[pin_index];
XMC_CCU8_SLICE_COMPARE_CONFIG_t compare_config;
memset(&compare_config, 0, sizeof(compare_config));

compare_config.prescaler_initval = pwm8->prescaler;
compare_config.passive_level_out0 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
compare_config.passive_level_out1 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
compare_config.passive_level_out2 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
compare_config.passive_level_out3 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;

XMC_CCU8_Init(pwm8->ccu, XMC_CCU8_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU8_SLICE_CompareInit(pwm8->slice, &compare_config);
XMC_CCU8_EnableClock(pwm8->ccu, pwm8->slice_num);

uint32_t period = (PCLK / 64) / frequency; // calculate period
XMC_CCU8_SLICE_SetTimerPeriodMatch(pwm8->slice, period);
XMC_CCU8_SLICE_SetTimerCompareMatch(pwm8->slice, pwm8->slice_channel, period / 2);

XMC_CCU8_EnableShadowTransfer(
pwm8->ccu, XMC_CCU8_SHADOW_TRANSFER_SLICE_0 | XMC_CCU8_SHADOW_TRANSFER_SLICE_2 |
XMC_CCU8_SHADOW_TRANSFER_SLICE_3 | XMC_CCU8_SHADOW_TRANSFER_SLICE_1);
}
#endif
}

// Scan the pwm pin mapping table
int16_t scanMapTable(const uint8_t table[][2], uint8_t pin) {
int16_t i = 0;
while (table[i][0] != 255) {
if (table[i][0] == pin) {
return table[i][1];
}
i++;
}
return -1;
}

void configureTimerInterrupt(unsigned long duration_ms) {
XMC_CCU4_SLICE_COMPARE_CONFIG_t timer_config;
memset(&timer_config, 0, sizeof(timer_config));
timer_config.prescaler_initval = XMC_CCU4_SLICE_PRESCALER_64;
timer_config.passive_level = XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;

XMC_CCU4_SLICE_CompareInit(CCU40_CC42, &timer_config);

// Calculate period for the timer based on the duration
uint32_t timer_ticks = (PCLK / 64) * duration_ms / 1000;
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU40_CC42, timer_ticks);

XMC_CCU4_SLICE_EnableEvent(CCU40_CC42, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
XMC_CCU4_SLICE_SetInterruptNode(CCU40_CC42, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH,
XMC_CCU4_SLICE_SR_ID_0);

// Enable the NVIC interrupt
NVIC_EnableIRQ(CCU40_2_IRQn);

// Start the timer
XMC_CCU4_SLICE_StartTimer(CCU40_CC42);
}
};

static Tone inst_Tone;

void tone(pin_size_t pin, unsigned int frequency) { inst_Tone.play(pin, frequency); }

void tone(pin_size_t pin, unsigned int frequency, unsigned long duration) {
inst_Tone.play(pin, frequency, duration);
}

void noTone(pin_size_t pin) { inst_Tone.stop(pin); }
#ifdef __cplusplus
extern "C" {
#endif
void CCU40_2_IRQHandler(void) {
XMC_CCU4_SLICE_StopTimer(CCU40_CC42);
XMC_CCU4_SLICE_ClearEvent(CCU40_CC42, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
}
#ifdef __cplusplus
}
#endif
1 change: 0 additions & 1 deletion variants/XMC4700/config/XMC4700_Relax_Kit/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ extern const uint8_t NUM_ANALOG_OUTPUTS;
#define NUM_TASKS_VARIANT 32
#define NUM_SPI 3
#define NUM_I2C 2

// to use SPI_for_xmc_SD if desired by user
#define XMC_SPI_for_xmc_SD XMC_SPI_1
#define SDCARD_SPI SPI1
Expand Down
Loading