Skip to content
Merged
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
1 change: 1 addition & 0 deletions cores/psoc6/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
104 changes: 74 additions & 30 deletions cores/psoc6/analog_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ typedef struct {
typedef struct {
cyhal_pwm_t pwm_obj;
pin_size_t pin;
float duty_cycle_percent;
float frequency_hz;
bool initialized;
bool used;
} pwm_t;

// Static Variables
Expand Down Expand Up @@ -145,46 +148,87 @@ void analogWriteResolution(int res) {
}
}

void analogWrite(pin_size_t pinNumber, int value) {
uint8_t pwm_index = 0;
uint8_t 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];
}
}

float duty_cycle_pertentage = (pwm_value / desiredWriteResolution) * 100.0f;
return NULL; // No slots available
}

result = cyhal_pwm_set_duty_cycle(&pwm[pwm_index].pwm_obj, duty_cycle_pertentage, PWM_FREQUENCY_HZ);
pwm_assert(result);
void analogWrite(pin_size_t pinNumber, int value) {
// Allocate or find existing PWM slot
pwm_t *pwm = pwm_alloc(pinNumber);
if (pwm == NULL) {
return;
}

result = cyhal_pwm_start(&pwm[pwm_index].pwm_obj);
if (!pwm->initialized) {
cy_rslt_t result = cyhal_pwm_init(&pwm->pwm_obj, mapping_gpio_pin[pinNumber], NULL);
pwm_assert(result);
pwm->initialized = true;
}

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) {
// Allocate or find existing PWM slot
pwm_t *pwm = pwm_alloc(pinNumber);
if (pwm == NULL) {
return;
}

// Set frequency
pwm->frequency_hz = frequency;

// 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);
}
}
}
7 changes: 7 additions & 0 deletions docs/arduino-deviations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading