From f1773981ecc99ab0f47a4a567a40b0999cd2f1f8 Mon Sep 17 00:00:00 2001 From: IFX-Anusha Date: Wed, 16 Jul 2025 15:31:43 +0530 Subject: [PATCH 1/4] Cores/psoc: SetAnalog frequency function. Signed-off-by: IFX-Anusha --- cores/psoc6/Arduino.h | 1 + cores/psoc6/analog_io.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cores/psoc6/Arduino.h b/cores/psoc6/Arduino.h index 180bc719..5605dd90 100644 --- a/cores/psoc6/Arduino.h +++ b/cores/psoc6/Arduino.h @@ -47,6 +47,7 @@ extern bool gpio_current_value[]; #define PWM_FREQUENCY_HZ 1000 // 1 kHz void analogWriteResolution(int res); void analogReadResolution(int res); +void setAnalogWriteFrequency(pin_size_t pinNumber, uint32_t frequency); #undef LITTLE_ENDIAN diff --git a/cores/psoc6/analog_io.c b/cores/psoc6/analog_io.c index 9abbbcc8..b7802700 100644 --- a/cores/psoc6/analog_io.c +++ b/cores/psoc6/analog_io.c @@ -24,6 +24,8 @@ typedef struct { typedef struct { cyhal_pwm_t pwm_obj; pin_size_t pin; + float duty_cycle_percent; + float frequency_hz; bool initialized; } pwm_t; @@ -146,8 +148,9 @@ void analogWriteResolution(int res) { } void analogWrite(pin_size_t pinNumber, int value) { + uint8_t pwm_index = 0; - uint8_t pwm_value = value; + int pwm_value = value; cy_rslt_t result = CY_RSLT_TYPE_ERROR; if (pinNumber > GPIO_PIN_COUNT) { @@ -179,12 +182,35 @@ void analogWrite(pin_size_t pinNumber, int value) { pwm_value = desiredWriteResolution; } - float duty_cycle_pertentage = (pwm_value / desiredWriteResolution) * 100.0f; - result = cyhal_pwm_set_duty_cycle(&pwm[pwm_index].pwm_obj, duty_cycle_pertentage, PWM_FREQUENCY_HZ); + float duty_cycle_percent = ((float)pwm_value / desiredWriteResolution) * 100.0f; + pwm[pwm_index].duty_cycle_percent = duty_cycle_percent; + + if (pwm[pwm_index].frequency_hz == 0) { + pwm[pwm_index].frequency_hz = PWM_FREQUENCY_HZ; + } + result = cyhal_pwm_set_duty_cycle(&pwm[pwm_index].pwm_obj, duty_cycle_percent, pwm[pwm_index].frequency_hz); pwm_assert(result); result = cyhal_pwm_start(&pwm[pwm_index].pwm_obj); pwm_assert(result); } } + +void setAnalogWriteFrequency(pin_size_t pinNumber, uint32_t frequency) { + if (pinNumber > GPIO_PIN_COUNT) { + return; // Invalid pin number + } + + for (uint8_t i = 0; i < PWM_HOWMANY; i++) { + if (pwm[i].initialized && pwm[i].pin == pinNumber) { + cy_rslt_t result = cyhal_pwm_set_duty_cycle(&pwm[i].pwm_obj, pwm[i].duty_cycle_percent, frequency); + if (result != CY_RSLT_SUCCESS) { + pwm_assert(result); + } + return; + } else { + pwm[i].frequency_hz = frequency; // Store the frequency for use in analogwrite + } + } +} From 681923567560abcf03487f314d5eaa58653b0617 Mon Sep 17 00:00:00 2001 From: IFX-Anusha Date: Wed, 23 Jul 2025 17:21:43 +0530 Subject: [PATCH 2/4] docs: Documentation of analogwritefrequency. Signed-off-by: IFX-Anusha --- docs/arduino-deviations.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/arduino-deviations.rst b/docs/arduino-deviations.rst index 3054d0ee..c46d1b57 100644 --- a/docs/arduino-deviations.rst +++ b/docs/arduino-deviations.rst @@ -52,6 +52,13 @@ Only the `DEFAULT` mode is supported and uses the internal reference voltage of The PWM resolution is fixed at 8 bits by default unless the user explicitly sets a different resolution using the `analogWriteResolution()` function. The default frequency of the PWM signal is fixed at **1 kHz** and cannot be changed. +.. code-block:: cpp + + void setAnalogWriteFrequency(int pin, uint32_t frequency) + +This function can be used to set the frequency of the AnalogWrite PWM signal. The allowed range is from 1Hz to 100MHz. This function will only set the frequency +and user has to explicitly call the `analogwrite()` to start the PWM signal with the frequency set. +If the user has already started the PWM using `analogwrite()` then user can call this function to change the frequency. .. code-block:: cpp From e7eb5b7b90be5da41a5f9ba23d0a8ff6b862bfba Mon Sep 17 00:00:00 2001 From: IFX-Anusha Date: Wed, 23 Jul 2025 19:26:48 +0530 Subject: [PATCH 3/4] cores/psoc6: Code Fix. Signed-off-by: IFX-Anusha --- cores/psoc6/analog_io.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cores/psoc6/analog_io.c b/cores/psoc6/analog_io.c index b7802700..0d99af96 100644 --- a/cores/psoc6/analog_io.c +++ b/cores/psoc6/analog_io.c @@ -203,14 +203,24 @@ void setAnalogWriteFrequency(pin_size_t pinNumber, uint32_t frequency) { } for (uint8_t i = 0; i < PWM_HOWMANY; i++) { - if (pwm[i].initialized && pwm[i].pin == pinNumber) { - cy_rslt_t result = cyhal_pwm_set_duty_cycle(&pwm[i].pwm_obj, pwm[i].duty_cycle_percent, frequency); - if (result != CY_RSLT_SUCCESS) { - pwm_assert(result); + if (pwm[i].pin == pinNumber) { + pwm[i].frequency_hz = frequency; + if (pwm[i].initialized) { + cy_rslt_t result = cyhal_pwm_set_duty_cycle(&pwm[i].pwm_obj, pwm[i].duty_cycle_percent, frequency); + if (result != CY_RSLT_SUCCESS) { + pwm_assert(result); + } } return; - } else { - pwm[i].frequency_hz = frequency; // Store the frequency for use in analogwrite + } + } + + // If not found, store for future use in the first available slot + for (uint8_t i = 0; i < PWM_HOWMANY; i++) { + if (!pwm[i].initialized) { + pwm[i].pin = pinNumber; + pwm[i].frequency_hz = frequency; + return; } } } From 171a385db0c95ec4c981bf583214137eb2fc19bd Mon Sep 17 00:00:00 2001 From: IFX-Anusha Date: Tue, 5 Aug 2025 13:28:16 +0530 Subject: [PATCH 4/4] cores/psoc6: Refactor pwm using pwm_alloc function. Signed-off-by: IFX-Anusha --- cores/psoc6/analog_io.c | 118 +++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 55 deletions(-) diff --git a/cores/psoc6/analog_io.c b/cores/psoc6/analog_io.c index 0d99af96..8b0ecd10 100644 --- a/cores/psoc6/analog_io.c +++ b/cores/psoc6/analog_io.c @@ -27,6 +27,7 @@ typedef struct { float duty_cycle_percent; float frequency_hz; bool initialized; + bool used; } pwm_t; // Static Variables @@ -147,80 +148,87 @@ void analogWriteResolution(int res) { } } -void analogWrite(pin_size_t pinNumber, int value) { - - uint8_t pwm_index = 0; - int pwm_value = value; - cy_rslt_t result = CY_RSLT_TYPE_ERROR; - +static pwm_t * pwm_alloc(pin_size_t pinNumber) { if (pinNumber > GPIO_PIN_COUNT) { - return; // Invalid pin number + return NULL; // Invalid pin number } - // Find existing channel or initialize a new one - for (pwm_index = 0; pwm_index < PWM_HOWMANY; pwm_index++) { - if (pwm[pwm_index].initialized) { - if (pwm[pwm_index].pin == pinNumber) { - // Found an existing channel for the pin - break; - } - } else { - // Found an uninitialized channel, initialize it - result = cyhal_pwm_init(&pwm[pwm_index].pwm_obj, mapping_gpio_pin[pinNumber], NULL); - pwm_assert(result); - pwm[pwm_index].pin = pinNumber; - pwm[pwm_index].initialized = true; - break; + // First, look for existing allocation for this pin + for (uint8_t i = 0; i < PWM_HOWMANY; i++) { + if (pwm[i].used && pwm[i].pin == pinNumber) { + return &pwm[i]; } } - if (pwm_index < PWM_HOWMANY) { - if (pwm_value <= 0) { - pwm_value = 0; - } - if (pwm_value > desiredWriteResolution) { - pwm_value = desiredWriteResolution; + // If not found, look for unused slot + for (uint8_t i = 0; i < PWM_HOWMANY; i++) { + if (!pwm[i].used) { + // Allocate this slot + pwm[i].pin = pinNumber; + pwm[i].used = true; + pwm[i].frequency_hz = 0; + pwm[i].duty_cycle_percent = 0; + pwm[i].initialized = false; + return &pwm[i]; } + } + return NULL; // No slots available +} - float duty_cycle_percent = ((float)pwm_value / desiredWriteResolution) * 100.0f; - pwm[pwm_index].duty_cycle_percent = duty_cycle_percent; +void analogWrite(pin_size_t pinNumber, int value) { + // Allocate or find existing PWM slot + pwm_t *pwm = pwm_alloc(pinNumber); + if (pwm == NULL) { + return; + } - if (pwm[pwm_index].frequency_hz == 0) { - pwm[pwm_index].frequency_hz = PWM_FREQUENCY_HZ; - } - result = cyhal_pwm_set_duty_cycle(&pwm[pwm_index].pwm_obj, duty_cycle_percent, pwm[pwm_index].frequency_hz); + if (!pwm->initialized) { + cy_rslt_t result = cyhal_pwm_init(&pwm->pwm_obj, mapping_gpio_pin[pinNumber], NULL); pwm_assert(result); + pwm->initialized = true; + } - result = cyhal_pwm_start(&pwm[pwm_index].pwm_obj); - pwm_assert(result); + int pwm_value = value; + if (pwm_value <= 0) { + pwm_value = 0; } + if (pwm_value > desiredWriteResolution) { + pwm_value = desiredWriteResolution; + } + + // Calculate duty cycle + float duty_cycle_percent = ((float)pwm_value / desiredWriteResolution) * 100.0f; + pwm->duty_cycle_percent = duty_cycle_percent; + + // Use pre-configured frequency or default + if (pwm->frequency_hz == 0) { + pwm->frequency_hz = PWM_FREQUENCY_HZ; + } + + // Set duty cycle and start PWM + cy_rslt_t result = cyhal_pwm_set_duty_cycle(&pwm->pwm_obj, duty_cycle_percent, pwm->frequency_hz); + pwm_assert(result); + + result = cyhal_pwm_start(&pwm->pwm_obj); + pwm_assert(result); } void setAnalogWriteFrequency(pin_size_t pinNumber, uint32_t frequency) { - if (pinNumber > GPIO_PIN_COUNT) { - return; // Invalid pin number + // Allocate or find existing PWM slot + pwm_t *pwm = pwm_alloc(pinNumber); + if (pwm == NULL) { + return; } - for (uint8_t i = 0; i < PWM_HOWMANY; i++) { - if (pwm[i].pin == pinNumber) { - pwm[i].frequency_hz = frequency; - if (pwm[i].initialized) { - cy_rslt_t result = cyhal_pwm_set_duty_cycle(&pwm[i].pwm_obj, pwm[i].duty_cycle_percent, frequency); - if (result != CY_RSLT_SUCCESS) { - pwm_assert(result); - } - } - return; - } - } + // Set frequency + pwm->frequency_hz = frequency; - // If not found, store for future use in the first available slot - for (uint8_t i = 0; i < PWM_HOWMANY; i++) { - if (!pwm[i].initialized) { - pwm[i].pin = pinNumber; - pwm[i].frequency_hz = frequency; - return; + // If already initialized, update the hardware immediately + if (pwm->initialized) { + cy_rslt_t result = cyhal_pwm_set_duty_cycle(&pwm->pwm_obj, pwm->duty_cycle_percent, frequency); + if (result != CY_RSLT_SUCCESS) { + pwm_assert(result); } } }