diff --git a/ci-build-matrix.json b/ci-build-matrix.json index 7d833bf..300a881 100644 --- a/ci-build-matrix.json +++ b/ci-build-matrix.json @@ -8,7 +8,7 @@ ], "example" : [ "extras/arduino-examples/examples/01.Basics/Blink/Blink.ino", - "extras/arduino-examples/examples/03.Analog/AnalogInput/AnalogInput.ino", + "extras/arduino-examples/examples/03.Analog/AnalogInOutSerial/AnalogInOutSerial.ino", "libraries/SPI/examples/master/master.ino", "libraries/SPI/examples/slave/slave.ino", "libraries/WiFi/examples/ConnectNoEncryption/ConnectNoEncryption.ino", diff --git a/cores/psoc6/Arduino.h b/cores/psoc6/Arduino.h index 1319e54..9c28c3a 100644 --- a/cores/psoc6/Arduino.h +++ b/cores/psoc6/Arduino.h @@ -42,6 +42,8 @@ extern const uint8_t GPIO_PIN_COUNT; #define GPIO_INTERRUPT_PRIORITY 3 // GPIO interrupt priority #define digitalPinToInterrupt(p) ((p) < GPIO_PIN_COUNT ? (p) : -1) +#define PWM_FREQUENCY_HZ 1000 // 1 kHz +void analogWriteResolution(int res); #undef LITTLE_ENDIAN diff --git a/cores/psoc6/analog_io.c b/cores/psoc6/analog_io.c index b10442c..df0024c 100644 --- a/cores/psoc6/analog_io.c +++ b/cores/psoc6/analog_io.c @@ -1,24 +1,42 @@ #include "Arduino.h" #include "cyhal_adc.h" +#include "cyhal_pwm.h" // Constants and Macros + #define MIN_ACQUISITION_TIME 220 #define adc_assert(cy_ret) if (cy_ret != CY_RSLT_SUCCESS) { return 0xff; } +#define pwm_assert(cy_ret) if (cy_ret != CY_RSLT_SUCCESS) { return; } + +#define PWM_RESOLUTION_8_BIT 255.0 +#define PWM_RESOLUTION_10_BIT 1023.0 +#define PWM_RESOLUTION_12_BIT 4095.0 +#define PWM_RESOLUTION_16_BIT 65535.0 // Type Definitions + typedef struct { pin_size_t pin; cyhal_adc_channel_t chan_obj; bool initialized; } adc_channel_t; +typedef struct { + cyhal_pwm_t pwm_obj; + pin_size_t pin; + bool initialized; +} pwm_t; + // Static Variables + static cyhal_adc_t adc_obj = {0}; static cyhal_adc_vref_t desiredVRef = CYHAL_ADC_REF_VDDA; static bool adc_initialized = false; static adc_channel_t adc_channel[ADC_HOWMANY] = {0}; +static float desiredWriteResolution = PWM_RESOLUTION_8_BIT; +static pwm_t pwm[PWM_HOWMANY] = {0}; + -// Helper Function: Initialize ADC hardware if not already done static cy_rslt_t initialize_adc(pin_size_t pinNumber) { if (!adc_initialized) { cy_rslt_t status = cyhal_adc_init(&adc_obj, mapping_gpio_pin[pinNumber], NULL); @@ -89,3 +107,56 @@ int analogRead(pin_size_t pinNumber) { void analogReference(uint8_t mode) { desiredVRef = CYHAL_ADC_REF_VDDA; } + +void analogWriteResolution(int res) { + if (res > 12) { + desiredWriteResolution = PWM_RESOLUTION_16_BIT; + } else if (res > 10) { + desiredWriteResolution = PWM_RESOLUTION_12_BIT; + } else if (res > 8) { + desiredWriteResolution = PWM_RESOLUTION_10_BIT; + } else { + desiredWriteResolution = PWM_RESOLUTION_8_BIT; + } +} + +void analogWrite(pin_size_t pinNumber, int value) { + uint8_t pwm_index = 0; + cy_rslt_t result = CY_RSLT_TYPE_ERROR; + + if (pinNumber > GPIO_PIN_COUNT) { + return; // 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; + } + } + + if (value < 0) { + value = 0; + } + if (value > desiredWriteResolution) { + value = desiredWriteResolution; + } + + float duty_cycle_pertentage = (value / desiredWriteResolution) * 100.0f; + + result = cyhal_pwm_set_duty_cycle(&pwm[pwm_index].pwm_obj, duty_cycle_pertentage, PWM_FREQUENCY_HZ); + pwm_assert(result); + + result = cyhal_pwm_start(&pwm[pwm_index].pwm_obj); + pwm_assert(result); +} diff --git a/docs/arduino-deviations.rst b/docs/arduino-deviations.rst index 2e4e091..d5978bb 100644 --- a/docs/arduino-deviations.rst +++ b/docs/arduino-deviations.rst @@ -3,13 +3,14 @@ Arduino API Deviations This section documents the differences between the standard Arduino Language Reference and `PSoC6-for-Arduino`. -ADC ---- +Analog IO +--------- Once a pin is configured and used as an ADC input, it may no longer be available for use with any other peripheral (e.g., PWM, I2C, SPI, GPIO, etc.). The `PSoC6-for-Arduino` core does not support the following Arduino APIs: + .. code-block:: cpp void analogReadResolution(uint8_t bits) @@ -24,3 +25,24 @@ For applications requiring lower effective resolutions (e.g., 8-bit or 10-bit), void analogReference(uint8_t mode) Only the `DEFAULT` mode is supported and uses the internal reference voltage of the PSoC6 device, which is typically 3.3V. + + +.. code-block:: cpp + + void analogWrite(int pin, int value) + +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 analogWriteResolution(int res) + +The input resolution is selected from following fixed options: + +- Resolutions greater than 12 bits mapped to **16-bit PWM**. +- Resolutions greater than 10 bits mapped to **12-bit PWM**. +- Resolutions greater than 8 bits mapped to **10-bit PWM**. +- Resolutions of 8 bits or less mapped to **8-bit PWM**. + diff --git a/tests/cy8ckit-062s2-ai-hil-test-table.md b/tests/cy8ckit-062s2-ai-hil-test-table.md index ada0d39..cf9dd2b 100644 --- a/tests/cy8ckit-062s2-ai-hil-test-table.md +++ b/tests/cy8ckit-062s2-ai-hil-test-table.md @@ -31,7 +31,7 @@ | SPI | P9_0 | P9_1 | MOSI and MISO shorted | | | P9_2 | NC | SCLK to SCLK | | | | | | -| ADC | P10.0 | VDDA 3.3V | A0 connected to VDDA 3.3V | +| Analog IO ADC | P10.0 | VDDA 3.3V | A0 connected to VDDA 3.3V | | | P10.1 | VoltageDivider | A1 connected to Voltage | | | | | divider circuit as below: | | | | | | @@ -45,3 +45,6 @@ | | | | | | | | | | GND (0V) | | | | | | +| Analog IO PWM | P9.6 | P9.7 | IO6 (PWM feedback) to | +| | | | IO7 (PWM Output) | +| | | | | diff --git a/tests/test_config.h b/tests/test_config.h index b3df2b8..5bec86f 100644 --- a/tests/test_config.h +++ b/tests/test_config.h @@ -13,17 +13,17 @@ #include // Test Pin Definitions -#define TEST_DIGITALIO_OUTPUT 7 // IO_4 -#define TEST_DIGITALIO_INPUT 6 // IO_3 -#define TEST_SYNC_INPUT_OUTPUT 4 // IO_1 +#define TEST_PIN_DIGITAL_IO_OUTPUT 7 // IO_4 +#define TEST_PIN_DIGITAL_IO_INPUT 6 // IO_3 -#define TEST_SPI_SLAVE_SELECT 3 // IO_0 +#define TEST_PIN_SYNC_IO 4 // IO_1 -#define TEST_ANALOG_IO_VREF A0 // Pin connected to VREF -#define TEST_ANALOG_IO_DIVIDER A1 // Pin connected to voltage divider +#define TEST_PIN_SPI_SSEL 3 // IO_0 -#define VDDA 3.3f // Assume VDDA is 3.3V -#define RESOLUTION 2048 // 11-bit resolution +#define TEST_PIN_ANALOG_IO_VREF A0 // Pin connected to VREF +#define TEST_PIN_ANALOG_IO_DIVIDER A1 // Pin connected to voltage divider + +#define TEST_ADC_RESOLUTION 2048 // 11-bit resolution #endif // TEST_CONFIG_H \ No newline at end of file diff --git a/variants/CY8CKIT-062S2-AI/pins_arduino.h b/variants/CY8CKIT-062S2-AI/pins_arduino.h index 4a1489b..983c937 100644 --- a/variants/CY8CKIT-062S2-AI/pins_arduino.h +++ b/variants/CY8CKIT-062S2-AI/pins_arduino.h @@ -63,6 +63,8 @@ static const uint8_t SCK = PIN_SPI_SCK; static const uint8_t A0 = PIN_A0; static const uint8_t A1 = PIN_A1; +#define PWM_HOWMANY 14 // Number of output pins that can be PWM channels + #define LED1 12 // Additional LED1 #define LED_BUILTIN LED1 // Standard Arduino LED: Uses LED1 #define LED2 13 // Additional LED2 @@ -79,19 +81,19 @@ extern "C" { // Mapping of digital pins and comments const cyhal_gpio_t mapping_gpio_pin[] = { - /* 0 */ P9_0, // SPI-MOSI - /* 1 */ P9_1, // SPI-MISO - /* 2 */ P9_2, // SPI-SCLK - /* 3 */ P9_3, // IO_0 - /* 4 */ P9_4, // IO_1 - /* 5 */ P9_5, // IO_2 / PWM1 - /* 6 */ P9_6, // IO_3 / PWM2 - /* 7 */ P9_7, // IO_4 + /* 0 */ P9_0, // SPI-MOSI / PWM + /* 1 */ P9_1, // SPI-MISO / PWM + /* 2 */ P9_2, // SPI-SCLK / PWM + /* 3 */ P9_3, // IO_0 / PWM + /* 4 */ P9_4, // IO_1 / PWM + /* 5 */ P9_5, // IO_2 / PWM + /* 6 */ P9_6, // IO_3 / PWM + /* 7 */ P9_7, // IO_4 / PWM - /* 8 */ P0_2, // I2C-SCL - /* 9 */ P0_3, // I2C-SDA - /* 10 */ P10_1,// A1 / UART_TX - /* 11 */ P10_0,// A0 / UART_RX + /* 8 */ P0_2, // I2C-SCL / PWM + /* 9 */ P0_3, // I2C-SDA / PWM + /* 10 */ P10_1,// A1 / UART_TX / PWM + /* 11 */ P10_0,// A0 / UART_RX / PWM // on board LEDs and USER BUTTON @@ -101,22 +103,22 @@ const cyhal_gpio_t mapping_gpio_pin[] = { // Additional pins for expansion IO connector - J15 starting here - /* 15 */ P13_0,// SDHC_DATA00 / SPI-MOSI / UART_RX / I2C-SCL - /* 16 */ P13_1,// SDHC_DATA01 / SPI-MISO / UART_TX / I2C-SDA + /* 15 */ P13_0,// SDHC_DATA00 / SPI-MOSI / UART_RX / I2C-SCL / PWM + /* 16 */ P13_1,// SDHC_DATA01 / SPI-MISO / UART_TX / I2C-SDA / PWM /* 17 */ P13_2,// SDHC_DATA02 / SPI-SCLK / IO / PWM /* 18 */ P13_3,// SDHC_DATA03 / IO / PWM - /* 19 */ P13_4,// SDHC_DATA10 / UART_RX / I2C-SCL - /* 20 */ P13_5,// SDHC_DATA11 / UART_TX / I2C-SDA + /* 19 */ P13_4,// SDHC_DATA10 / UART_RX / I2C-SCL / PWM + /* 20 */ P13_5,// SDHC_DATA11 / UART_TX / I2C-SDA / PWM /* 21 */ P13_6,// SDHC_DATA12 / IO / PWM /* 22 */ P13_7,// SDHC_DATA13 / IO / PWM - /* 23 */ P8_2,// SPI-SCLK / IO /PWM + /* 23 */ P8_2,// SPI-SCLK / IO / PWM /* 24 */ P8_1,// SPI-MISO / UART_TX / I2C-SDA / IO / PWM /* 25 */ P8_0,// SPI-MOSI / UART_RX / I2C-SCL / IO / PWM /* 26 */ P8_3,// IO / PWM - /* 27 */ P8_4,// UART_RX / I2C-SCL / IO /PWM - /* 28 */ P8_5,// UART_TX / I2C-SDA / IO /PWM - /* 29 */ P12_4,// SDHC_CMD / IO /PWM - /* 30 */ P12_5,// SDHC_CLK / IO /PWM + /* 27 */ P8_4,// UART_RX / I2C-SCL / IO / PWM + /* 28 */ P8_5,// UART_TX / I2C-SDA / IO / PWM + /* 29 */ P12_4,// SDHC_CMD / IO / PWM + /* 30 */ P12_5,// SDHC_CLK / IO / PWM // Debugger Serial UART pins (not available on connector)