diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 951330a..f1afbb3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p
Please ensure to specify the following:
* Arduino IDE version (e.g. 1.8.19) or Platform.io version
-* `RP2040` Core Version (e.g. Arduino-mbed RP2040 v2.7.2 or arduino-pico core v1.13.0)
+* `RP2040` Core Version (e.g. Arduino-mbed RP2040 v3.0.1 or arduino-pico core v1.13.1)
* `RP2040` Board type (e.g. NANO_RP2040_CONNECT, RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040, GENERIC_RP2040, etc.)
* Contextual information (e.g. what you were trying to achieve)
* Simplest possible steps to reproduce
@@ -28,10 +28,10 @@ Please ensure to specify the following:
```
Arduino IDE version: 1.8.19
-Arduino-mbed mbed_nano v2.7.2
+Arduino-mbed mbed_nano v3.0.1
NANO_RP2040_CONNECT Module
OS: Ubuntu 21.04 LTS
-Linux kh-Inspiron-3593 5.13.0-30-generic #33-Ubuntu SMP Fri Feb 4 17:03:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
+Linux kh-Inspiron-3593 5.13.0-39-generic #44~20.04.1-Ubuntu SMP Thu Mar 24 16:43:35 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Context:
I encountered a crash while using TimerInterrupt.
diff --git a/README.md b/README.md
index 2e1c286..3459a9b 100644
--- a/README.md
+++ b/README.md
@@ -31,11 +31,13 @@
* [1. Create PWM Instance with Pin, Frequency and dutycycle](#1-Create-PWM-Instance-with-Pin-Frequency-and-dutycycle)
* [2. Initialize PWM Instance](#2-Initialize-PWM-Instance)
* [3. Set or change PWM frequency or dutyCycle](#3-set-or-change-PWM-frequency-or-dutyCycle)
+ * [4. Set or change PWM frequency and dutyCycle manually and efficiently in waveform creation](#4-Set-or-change-PWM-frequency-and-dutyCycle-manually-and-efficiently-in-waveform-creation)
* [Examples](#examples)
* [ 1. PWM_Multi](examples/PWM_Multi)
* [ 2. PWM_DynamicFreq](examples/PWM_DynamicFreq)
* [ 3. PWM_DynamicDutyCycle](examples/PWM_DynamicDutyCycle)
- * [ 4. PWM_MultiChannel](examples/PWM_MultiChannel) **New**
+ * [ 4. PWM_MultiChannel](examples/PWM_MultiChannel)
+ * [ 5. PWM_Waveform](examples/PWM_Waveform) **New**
* [Example PWM_Multi](#example-PWM_Multi)
* [Debug Terminal Output Samples](#debug-terminal-output-samples)
* [1. PWM_Multi on MBED RaspberryPi Pico](#1-PWM_Multi-on-MBED-RaspberryPi-Pico)
@@ -109,8 +111,8 @@ Functions using normal software-based PWMs, relying on loop() and calling millis
## Prerequisites
1. [`Arduino IDE 1.8.19+` for Arduino](https://www.arduino.cc/en/Main/Software)
- 2. [`ArduinoCore-mbed mbed_nano or mbed_rp2040 core 2.7.2`](https://github.com/arduino/ArduinoCore-mbed) for Arduino **NANO_RP2040_CONNECT, RASPBERRY_PI_PICO** boards. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest)
- 3. [`Earle Philhower's arduino-pico core v1.13.0+`](https://github.com/earlephilhower/arduino-pico) for RP2040-based boards such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040, ADAFRUIT_ITSYBITSY_RP2040, CYTRON_MAKER_NANO_RP2040, SPARKFUN_PROMICRO_RP2040, CHALLENGER_2040_WIFI_RP2040, ILABS_2040_RPICO32_RP2040, MELOPERO_SHAKE_RP2040, SOLDERPARTY_RP2040_STAMP, UPESY_RP2040_DEVKIT, WIZNET_5100S_EVB_PICO, GENERIC_RP2040**, etc. [![GitHub release](https://img.shields.io/github/release/earlephilhower/arduino-pico.svg)](https://github.com/earlephilhower/arduino-pico/releases/latest)
+ 2. [`ArduinoCore-mbed mbed_nano or mbed_rp2040 core 3.0.1+`](https://github.com/arduino/ArduinoCore-mbed) for Arduino **NANO_RP2040_CONNECT, RASPBERRY_PI_PICO** boards. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest)
+ 3. [`Earle Philhower's arduino-pico core v1.13.1+`](https://github.com/earlephilhower/arduino-pico) for RP2040-based boards such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040, ADAFRUIT_ITSYBITSY_RP2040, CYTRON_MAKER_NANO_RP2040, SPARKFUN_PROMICRO_RP2040, CHALLENGER_2040_WIFI_RP2040, ILABS_2040_RPICO32_RP2040, MELOPERO_SHAKE_RP2040, SOLDERPARTY_RP2040_STAMP, UPESY_RP2040_DEVKIT, WIZNET_5100S_EVB_PICO, GENERIC_RP2040**, etc. [![GitHub release](https://img.shields.io/github/release/earlephilhower/arduino-pico.svg)](https://github.com/earlephilhower/arduino-pico/releases/latest)
---
@@ -219,6 +221,13 @@ if (PWM_Instance)
PWM_Instance->setPWM(PWM_Pins, new_frequency, new_dutyCycle, true);
```
+#### 4. Set or change PWM frequency and dutyCycle manually and efficiently in waveform creation
+
+```
+PWM_Instance->setPWM_manual(PWM_Pins, new_top, new_div, new_level, true)
+```
+
+
---
---
@@ -226,8 +235,10 @@ PWM_Instance->setPWM(PWM_Pins, new_frequency, new_dutyCycle, true);
1. [PWM_Multi](examples/PWM_Multi)
2. [PWM_DynamicFreq](examples/PWM_DynamicFreq)
- 3. [PWM_DynamicDutyCycle](examples/PWM_DynamicDutyCycle).
- 4. [PWM_MultiChannel](examples/PWM_MultiChannel). **New**
+ 3. [PWM_DynamicDutyCycle](examples/PWM_DynamicDutyCycle)
+ 4. [PWM_MultiChannel](examples/PWM_MultiChannel)
+ 5. [PWM_Waveform](examples/PWM_Waveform). **New**
+
---
---
@@ -249,7 +260,7 @@ The following is the sample terminal output when running example [PWM_Multi](exa
```
Starting PWM_Multi on RaspberryPi Pico
-RP2040_PWM v1.1.1
+RP2040_PWM v1.2.0
=============================================================
Index Pin PWM_freq DutyCycle Actual Freq
=============================================================
@@ -272,7 +283,7 @@ The following is the sample terminal output when running example [**PWM_Multi**]
```
Starting PWM_Multi on RASPBERRY_PI_PICO
-RP2040_PWM v1.1.1
+RP2040_PWM v1.2.0
=============================================================
Index Pin PWM_freq DutyCycle Actual Freq
=============================================================
@@ -295,7 +306,7 @@ The following is the sample terminal output when running example [**PWM_DynamicF
```
Starting PWM_DynamicFreq on Nano RP2040 Connect
-RP2040_PWM v1.1.1
+RP2040_PWM v1.2.0
[PWM] _PWM_config.top = 12499 , _actualFrequency = 1000.00
[PWM] PWM enabled, frequency = 1000.00
=============================================================
@@ -340,7 +351,7 @@ The following is the sample terminal output when running example [**PWM_DynamicD
```
Starting PWM_DynamicDutyCycle on RASPBERRY_PI_PICO
-RP2040_PWM v1.1.1
+RP2040_PWM v1.2.0
[PWM] _PWM_config.top = 12499 , _actualFrequency = 1000.00
[PWM] PWM enabled, frequency = 1000.00
=============================================================
@@ -377,7 +388,7 @@ The following is the sample terminal output when running example [**PWM_MultiCha
```
Starting PWM_MultiChannel on RASPBERRY_PI_PICO
-RP2040_PWM v1.1.1
+RP2040_PWM v1.2.0
=============================================================
Index Pin PWM_freq DutyCycle Actual Freq
=============================================================
@@ -386,6 +397,55 @@ Index Pin PWM_freq DutyCycle Actual Freq
=============================================================
```
+---
+
+### 6. PWM_Waveform on RASPBERRY_PI_PICO
+
+The following is the sample terminal output when running example [**PWM_Waveform**](examples/PWM_Waveform) on **RASPBERRY_PI_PICO**, running [`Earle Philhower's arduino-pico core`](https://github.com/earlephilhower/arduino-pico), to demonstrate how to use new `setPWM_manual()` function in wafeform creation
+
+
+```
+Starting PWM_Waveform on RASPBERRY_PI_PICO
+RP2040_PWM v1.2.0
+[PWM] _PWM_config.top = 12499 , _actualFrequency = 1000.00
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 0
+=============================================================
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 0
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 50
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 100
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 200
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 300
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 400
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 500
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 600
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 700
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 800
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 900
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 1000
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 0
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 50
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 100
+[PWM] pin = 10 , PWM_CHAN = 0
+[PWM] PWM enabled, slice = 5 , top = 1000 , div = 10 , level = 200
+...
+```
+
---
---
@@ -427,13 +487,15 @@ Submit issues to: [RP2040_PWM issues](https://github.com/khoih-prog/RP2040_PWM/i
## DONE
-1. Basic hardware-based multi-channel PWMs for **RP2040-based boards** such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, etc. using either RP2040 [**ArduinoCore-mbed mbed_nano or mbed_rp2040** core](https://github.com/arduino/ArduinoCore-mbed) or [**Earle Philhower's arduino-pico core**](https://github.com/earlephilhower/arduino-pico)
-2. Add Table of Contents
-3. Split `changelog.md`
-4. Permit PWM output for both channels of PWM slice.
-5. Use float `instead` of `double` for frequency and duty-cycle
-6. Add example [PWM_MultiChannel](https://github.com/khoih-prog/RP2040_PWM/tree/main/examples/PWM_MultiChannel) to demonstrate how to use both channels of PWM slice.
-
+ 1. Basic hardware-based multi-channel PWMs for **RP2040-based boards** such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, etc. using either RP2040 [**ArduinoCore-mbed mbed_nano or mbed_rp2040** core](https://github.com/arduino/ArduinoCore-mbed) or [**Earle Philhower's arduino-pico core**](https://github.com/earlephilhower/arduino-pico)
+ 2. Add Table of Contents
+ 3. Split `changelog.md`
+ 4. Permit PWM output for both channels of PWM slice.
+ 5. Use float `instead` of `double` for frequency and duty-cycle
+ 6. Add example [PWM_MultiChannel](https://github.com/khoih-prog/RP2040_PWM/tree/main/examples/PWM_MultiChannel) to demonstrate how to use both channels of PWM slice.
+ 7. Add efficient `setPWM_manual()` function to use in wafeform creation using PWM
+ 8. Add example [PWM_Waveform](https://github.com/khoih-prog/RP2040_PWM/tree/main/examples/PWM_Waveform) to demonstrate how to use new `setPWM_manual()` function in wafeform creation
+ 9. Optimize library code and examples by using **reference-passing instead of value-passing**.
---
---
@@ -445,17 +507,17 @@ Many thanks for everyone for bug reporting, new feature suggesting, testing and
1. Thanks to [americodias](https://github.com/americodias) to report bugs in
- [Wrong frequency #1](https://github.com/khoih-prog/RP2040_PWM/issues/1) leading to v1.0.1
- [Change the PWM frequency #2](https://github.com/khoih-prog/RP2040_PWM/issues/2) leading to v1.0.2
-
2. Thanks to [Austin K. Litman](https://github.com/AKLitman) to report bugs in
- [Attempting to Alter the Duty Cycle w/o changing any other values #3](https://github.com/khoih-prog/RP2040_PWM/issues/3) leading to v1.0.5
- [Request for Clarification on PWM Slices and A/B sides #5](https://github.com/khoih-prog/RP2040_PWM/issues/5) leading to v1.1.0
-
-
+3. Thanks to [Joerg Starkmuth](https://github.com/Laserjones) to propose enhancement in
+- [Duty cycle as integer rather than float #6](https://github.com/khoih-prog/RP2040_PWM/issues/6) leading to v1.2.0
diff --git a/changelog.md b/changelog.md
index 225706a..dcda2ca 100644
--- a/changelog.md
+++ b/changelog.md
@@ -12,6 +12,7 @@
## Table of Contents
* [Changelog](#changelog)
+ * [Releases v1.2.0](#Releases-v120)
* [Releases v1.1.1](#Releases-v111)
* [Releases v1.1.0](#Releases-v110)
* [Releases v1.0.5](#Releases-v105)
@@ -26,6 +27,12 @@
## Changelog
+### Releases v1.2.0
+
+1. Add efficient `setPWM_manual()` function to use in wafeform creation using PWM. Check [Duty cycle as integer rather than float #6](https://github.com/khoih-prog/RP2040_PWM/issues/6)
+2. Add example [PWM_Waveform](https://github.com/khoih-prog/RP2040_PWM/tree/main/examples/PWM_Waveform) to demonstrate how to use new `setPWM_manual()` function in wafeform creation
+3. Optimize library code and examples by using **reference-passing instead of value-passing**.
+
### Releases v1.1.1
1. Fix compiler warnings.
diff --git a/examples/PWM_Waveform/PWM_Waveform.ino b/examples/PWM_Waveform/PWM_Waveform.ino
new file mode 100644
index 0000000..39e6386
--- /dev/null
+++ b/examples/PWM_Waveform/PWM_Waveform.ino
@@ -0,0 +1,130 @@
+/****************************************************************************************************************************
+ PWM_Waveform.ino
+ For RP2040 boards
+ Written by Khoi Hoang
+
+ Built by Khoi Hoang https://github.com/khoih-prog/RP2040_PWM
+ Licensed under MIT license
+
+ The RP2040 PWM block has 8 identical slices. Each slice can drive two PWM output signals, or measure the frequency
+ or duty cycle of an input signal. This gives a total of up to 16 controllable PWM outputs. All 30 GPIO pins can be driven
+ by the PWM block
+*****************************************************************************************************************************/
+
+// This example to demo the new function setPWM_manual(uint8_t pin, uint16_t top, uint8_t div, uint16_t level, bool phaseCorrect = false)
+// used to generate a waveform. Check https://github.com/khoih-prog/RP2040_PWM/issues/6
+
+#define _PWM_LOGLEVEL_ 2
+
+#if ( defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || \
+ defined(ARDUINO_GENERIC_RP2040) ) && defined(ARDUINO_ARCH_MBED)
+
+ #if(_PWM_LOGLEVEL_>3)
+ #warning USING_MBED_RP2040_PWM
+ #endif
+
+#elif ( defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || \
+ defined(ARDUINO_GENERIC_RP2040) ) && !defined(ARDUINO_ARCH_MBED)
+
+ #if(_PWM_LOGLEVEL_>3)
+ #warning USING_RP2040_PWM
+ #endif
+#else
+ #error This code is intended to run on the RP2040 mbed_nano, mbed_rp2040 or arduino-pico platform! Please check your Tools->Board setting.
+#endif
+
+#include "RP2040_PWM.h"
+
+#define LED_ON LOW
+#define LED_OFF HIGH
+
+#define pinLed 25 // GP25, On-board BUILTIN_LED
+#define pin0 16 // GP16, PWM channel 4B (D2)
+#define pin10 10 // PWM channel 5A
+#define pin11 11 // PWM channel 5B
+
+#define pinToUse pin10
+
+RP2040_PWM* PWM_Instance;
+
+typedef struct
+{
+ uint16_t top;
+ uint8_t div;
+ uint16_t level;
+} PWD_Data;
+
+#define NUM_PWM_POINTS 12
+
+// PWM Freq = 12487 Hz
+PWD_Data PWM_data[NUM_PWM_POINTS] =
+{
+ { 1000, 10, 0 },
+ { 1000, 10, 50 },
+ { 1000, 10, 100 },
+ { 1000, 10, 200 },
+ { 1000, 10, 300 },
+ { 1000, 10, 400 },
+ { 1000, 10, 500 },
+ { 1000, 10, 600 },
+ { 1000, 10, 700 },
+ { 1000, 10, 800 },
+ { 1000, 10, 900 },
+ { 1000, 10, 1000 },
+};
+
+float frequency;
+
+// You can select any value
+PWD_Data PWM_data_idle = PWM_data[0];
+
+char dashLine[] = "=============================================================";
+
+void setup()
+{
+ Serial.begin(115200);
+ while (!Serial && millis() < 5000);
+
+ delay(100);
+
+ Serial.print(F("\nStarting PWM_Waveform on ")); Serial.println(BOARD_NAME);
+ Serial.println(RP2040_PWM_VERSION);
+
+ frequency = 1000;
+
+ // Create a dummy instance
+ PWM_Instance = new RP2040_PWM(pinToUse, frequency, 0);
+
+ if (PWM_Instance)
+ {
+ // setPWM_manual(uint8_t pin, uint16_t top, uint8_t div, uint16_t level, bool phaseCorrect = false)
+ PWM_Instance->setPWM_manual(pinToUse, PWM_data_idle.top, PWM_data_idle.div, PWM_data_idle.level, true);
+ }
+
+ Serial.println(dashLine);
+}
+
+void printPWMInfo(RP2040_PWM* PWM_Instance)
+{
+ uint32_t div = PWM_Instance->get_DIV();
+ uint32_t top = PWM_Instance->get_TOP();
+
+ // PWM_Freq = ( F_CPU ) / [ ( TOP + 1 ) * ( DIV + DIV_FRAC/16) ]
+ PWM_LOGINFO1("Actual PWM Frequency = ", PWM_Instance->get_freq_CPU() / ( (PWM_Instance->get_TOP() + 1) * (PWM_Instance->get_DIV() ) ) );
+
+ PWM_LOGDEBUG5("TOP =", top, ", DIV =", div, ", CPU_freq =", PWM_Instance->get_freq_CPU());
+}
+
+void loop()
+{
+ for (int index = 0; index < NUM_PWM_POINTS; index++)
+ {
+ PWM_Instance->setPWM_manual(pinToUse, PWM_data[index].top, PWM_data[index].div, PWM_data[index].level, true);
+
+ // Use at low freq to check
+ //printPWMInfo(PWM_Instance);
+
+ // delay something here between data
+ delay(100);
+ }
+}
diff --git a/keywords.txt b/keywords.txt
index 6772d07..9e38c3b 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -14,6 +14,7 @@ PWM_slice KEYWORD1
###################################
setPWM KEYWORD2
+setPWM_manual KEYWORD2
setPWM_Period KEYWORD2
enablePWM KEYWORD2
disablePWM KEYWORD2
diff --git a/library.json b/library.json
index 3fcaa4c..8478579 100644
--- a/library.json
+++ b/library.json
@@ -1,8 +1,8 @@
{
"name": "RP2040_PWM",
- "version": "1.1.1",
+ "version": "1.2.0",
"keywords": "timing, device, control, timer, pwm, pwm-slice, hardware-based-pwm, high-frequency-pwm, hardware-pwm, mission-critical, accuracy, non-blocking, mbed, mbed-nano, mbed-rp2040, rpi-pico, rp2040, nano-rp2040-connect, duty-cycle, hardware",
- "description": "This library enables you to use Hardware-based PWM channels on RP2040-based boards, such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, with either Arduino-mbed (mbed_nano or mbed_rp2040) or arduino-pico core to create and output PWM any GPIO pin. The most important feature is they're purely hardware-based PWM channels, supporting very high PWM frequencies. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware-based PWMs, still work even if other software functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software-based PWM using ISR, millis() or micros(). That's necessary if you need to control devices requiring high precision",
+ "description": "This library enables you to use Hardware-based PWM channels on RP2040-based boards, such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, with either Arduino-mbed (mbed_nano or mbed_rp2040) or arduino-pico core to create and output PWM any GPIO pin. The most important feature is they're purely hardware-based PWM channels, supporting very high PWM frequencies. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware-based PWMs, still work even if other software functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software-based PWM using ISR, millis() or micros(). That's necessary if you need to control devices requiring high precision. New efficient setPWM_manual function to facilitate waveform creation using PWM",
"authors":
{
"name": "Khoi Hoang",
diff --git a/library.properties b/library.properties
index 84d1085..6b99c68 100644
--- a/library.properties
+++ b/library.properties
@@ -1,9 +1,9 @@
name=RP2040_PWM
-version=1.1.1
+version=1.2.0
author=Khoi Hoang
maintainer=Khoi Hoang
sentence=his library enables you to use Hardware-based PWM channels on RP2040-based boards, such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, with either Arduino-mbed (mbed_nano or mbed_rp2040) or arduino-pico core to create and output PWM to any GPIO pin.
-paragraph=TThe most important feature is they're purely hardware-based PWM channels, supporting very high PWM frequencies. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware-based PWMs, still work even if other software functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software-based PWM using ISR, millis() or micros(). That's necessary if you need to control devices requiring high precision
+paragraph=The most important feature is they're purely hardware-based PWM channels, supporting very high PWM frequencies. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware-based PWMs, still work even if other software functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software-based PWM using ISR, millis() or micros(). That's necessary if you need to control devices requiring high precision. New efficient setPWM_manual function to facilitate waveform creation using PWM
category=Device Control
url=https://github.com/khoih-prog/RP2040_PWM
architectures=mbed,mbed_nano,ArduinoCore-mbed,rp2040,mbed_rp2040
diff --git a/src/PWM_Generic_Debug.h b/src/PWM_Generic_Debug.h
index 4534f78..d72e070 100644
--- a/src/PWM_Generic_Debug.h
+++ b/src/PWM_Generic_Debug.h
@@ -12,7 +12,7 @@
Therefore, their executions are not blocked by bad-behaving functions / tasks.
This important feature is absolutely necessary for mission-critical tasks.
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,6 +24,7 @@
1.0.5 K Hoang 06/01/2022 Permit changing dutyCycle and keep same frequency on-the-fly
1.1.0 K Hoang 24/02/2022 Permit PWM output for both channels of PWM slice. Use float instead of double
1.1.1 K Hoang 06/03/2022 Fix compiler warnings. Display informational warning when debug level > 3
+ 1.2.0 K Hoang 16/04/2022 Add manual setPWM function to use in wafeform creation
*****************************************************************************************************************************/
#pragma once
@@ -71,7 +72,7 @@ const char PWM_SP[] = " ";
#define PWM_LOGERROR2(x,y,z) if(_PWM_LOGLEVEL_>0) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINTLN(z); }
#define PWM_LOGERROR3(x,y,z,w) if(_PWM_LOGLEVEL_>0) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINTLN(w); }
#define PWM_LOGERROR5(x,y,z,w,xx,yy) if(_PWM_LOGLEVEL_>0) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINTLN(yy); }
-#define PWM_LOGERROR7(x,y,z,w,xx,yy,zz,ww) if(_PWM_LOGLEVEL_>0) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINT(yy); PWM_PRINT_SP; PWM_PRINT(zz); PWM_PRINTLN(ww); }
+#define PWM_LOGERROR7(x,y,z,w,xx,yy,zz,ww) if(_PWM_LOGLEVEL_>0) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINT(yy); PWM_PRINT_SP; PWM_PRINT(zz); PWM_PRINT_SP; PWM_PRINTLN(ww); }
//////////////////////////////////////////
@@ -93,7 +94,7 @@ const char PWM_SP[] = " ";
#define PWM_LOGINFO2(x,y,z) if(_PWM_LOGLEVEL_>2) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINTLN(z); }
#define PWM_LOGINFO3(x,y,z,w) if(_PWM_LOGLEVEL_>2) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINTLN(w); }
#define PWM_LOGINFO5(x,y,z,w,xx,yy) if(_PWM_LOGLEVEL_>2) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINTLN(yy); }
-#define PWM_LOGINFO7(x,y,z,w,xx,yy,zz,ww) if(_PWM_LOGLEVEL_>2) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINT(yy); PWM_PRINT_SP; PWM_PRINT(zz); PWM_PRINTLN(ww); }
+#define PWM_LOGINFO7(x,y,z,w,xx,yy,zz,ww) if(_PWM_LOGLEVEL_>2) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINT(yy); PWM_PRINT_SP; PWM_PRINT(zz); PWM_PRINT_SP; PWM_PRINTLN(ww); }
//////////////////////////////////////////
@@ -104,7 +105,7 @@ const char PWM_SP[] = " ";
#define PWM_LOGDEBUG2(x,y,z) if(_PWM_LOGLEVEL_>3) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINTLN(z); }
#define PWM_LOGDEBUG3(x,y,z,w) if(_PWM_LOGLEVEL_>3) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINTLN(w); }
#define PWM_LOGDEBUG5(x,y,z,w,xx,yy) if(_PWM_LOGLEVEL_>3) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINTLN(yy); }
-#define PWM_LOGDEBUG7(x,y,z,w,xx,yy,zz,ww) if(_PWM_LOGLEVEL_>3) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINT(yy); PWM_PRINT_SP; PWM_PRINT(zz); PWM_PRINTLN(ww); }
+#define PWM_LOGDEBUG7(x,y,z,w,xx,yy,zz,ww) if(_PWM_LOGLEVEL_>3) { PWM_PRINT_MARK; PWM_PRINT(x); PWM_PRINT_SP; PWM_PRINT(y); PWM_PRINT_SP; PWM_PRINT(z); PWM_PRINT_SP; PWM_PRINT(w); PWM_PRINT_SP; PWM_PRINT(xx); PWM_PRINT_SP; PWM_PRINT(yy); PWM_PRINT_SP; PWM_PRINT(zz); PWM_PRINT_SP; PWM_PRINTLN(ww); }
//////////////////////////////////////////
diff --git a/src/RP2040_PWM.h b/src/RP2040_PWM.h
index 9c00787..2adb776 100644
--- a/src/RP2040_PWM.h
+++ b/src/RP2040_PWM.h
@@ -12,7 +12,7 @@
Therefore, their executions are not blocked by bad-behaving functions / tasks.
This important feature is absolutely necessary for mission-critical tasks.
- Version: 1.1.1
+ Version: 1.2.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -24,6 +24,7 @@
1.0.5 K Hoang 06/01/2022 Permit changing dutyCycle and keep same frequency on-the-fly
1.1.0 K Hoang 24/02/2022 Permit PWM output for both channels of PWM slice. Use float instead of double
1.1.1 K Hoang 06/03/2022 Fix compiler warnings. Display informational warning when debug level > 3
+ 1.2.0 K Hoang 16/04/2022 Add manual setPWM function to use in wafeform creation
*****************************************************************************************************************************/
#pragma once
@@ -63,13 +64,13 @@
#endif
#ifndef RP2040_PWM_VERSION
- #define RP2040_PWM_VERSION "RP2040_PWM v1.1.1"
+ #define RP2040_PWM_VERSION "RP2040_PWM v1.2.0"
#define RP2040_PWM_VERSION_MAJOR 1
- #define RP2040_PWM_VERSION_MINOR 1
- #define RP2040_PWM_VERSION_PATCH 1
+ #define RP2040_PWM_VERSION_MINOR 2
+ #define RP2040_PWM_VERSION_PATCH 0
- #define RP2040_PWM_VERSION_INT 1001001
+ #define RP2040_PWM_VERSION_INT 1002000
#endif
#include
@@ -96,7 +97,7 @@ typedef struct
bool channelA_Active;
bool channelB_Active;
} PWM_slice;
-
+
static PWM_slice PWM_slice_data[NUM_PWM_SLICES] =
{
{ 0, 0, 0, false, false },
@@ -108,6 +109,28 @@ static PWM_slice PWM_slice_data[NUM_PWM_SLICES] =
{ 0, 0, 0, false, false },
{ 0, 0, 0, false, false }
};
+
+// Not using float for waveform creating
+typedef struct
+{
+ uint16_t channelA_div;
+ uint16_t channelB_div;
+ bool channelA_Active;
+ bool channelB_Active;
+} PWM_slice_manual;
+
+// Default to 0% PWM
+static PWM_slice_manual PWM_slice_manual_data[NUM_PWM_SLICES] =
+{
+ { 0, 0, false, false },
+ { 0, 0, false, false },
+ { 0, 0, false, false },
+ { 0, 0, false, false },
+ { 0, 0, false, false },
+ { 0, 0, false, false },
+ { 0, 0, false, false },
+ { 0, 0, false, false }
+};
///////////////////////
///////////////////////////////////////////////////////////////////
@@ -116,7 +139,7 @@ class RP2040_PWM
{
public:
- RP2040_PWM(uint8_t pin, float frequency, float dutycycle, bool phaseCorrect = false)
+ RP2040_PWM(const uint8_t& pin, const float& frequency, const float& dutycycle, bool phaseCorrect = false)
{
#if defined(F_CPU)
freq_CPU = F_CPU;
@@ -129,16 +152,18 @@ class RP2040_PWM
_dutycycle = dutycycle;
_phaseCorrect = phaseCorrect;
-
+
if (!calc_TOP_and_DIV(frequency))
{
_frequency = 0;
}
+ else
+ {
+ _frequency = frequency;
+ }
- _pin = pin;
- _frequency = frequency;
- _dutycycle = dutycycle;
-
+ _pin = pin;
+ _dutycycle = dutycycle;
_phaseCorrect = phaseCorrect;
_enabled = false;
@@ -157,7 +182,85 @@ class RP2040_PWM
///////////////////////////////////////////
- bool setPWM(uint8_t pin, float frequency, float dutycycle, bool phaseCorrect = false)
+ bool setPWM_manual(const uint8_t& pin, const uint16_t& top, const uint8_t& div,
+ uint16_t& level, bool phaseCorrect = false)
+ {
+ _pin = pin;
+
+ _PWM_config.top = top;
+ _PWM_config.div = div;
+
+ // Limit level <= top
+ if (level > top)
+ level = top;
+
+ gpio_set_function(_pin, GPIO_FUNC_PWM);
+
+ _slice_num = pwm_gpio_to_slice_num(_pin);
+
+ pwm_config config = pwm_get_default_config();
+
+ // Set phaseCorrect
+ pwm_set_phase_correct(_slice_num, phaseCorrect);
+
+ pwm_config_set_clkdiv_int(&config, _PWM_config.div);
+ pwm_config_set_wrap(&config, _PWM_config.top);
+
+ // auto start running once configured
+ pwm_init(_slice_num, &config, true);
+ pwm_set_gpio_level(_pin, level);
+
+ // From v1.1.0
+ ////////////////////////////////
+ // Update PWM_slice_manual_data[]
+ //PWM_slice_manual_data[_slice_num].freq = _frequency;
+
+ if ( (pwm_gpio_to_channel(_pin)) == PWM_CHAN_A)
+ {
+ PWM_slice_manual_data[_slice_num].channelA_div = level;
+ PWM_slice_manual_data[_slice_num].channelA_Active = true;
+
+ // If B is active, set the data now
+ if (PWM_slice_manual_data[_slice_num].channelB_Active)
+ {
+ pwm_set_chan_level(_slice_num, PWM_CHAN_B, PWM_slice_manual_data[_slice_num].channelB_div);
+ }
+ }
+ else if ( (pwm_gpio_to_channel(_pin)) == PWM_CHAN_B)
+ {
+ PWM_slice_manual_data[_slice_num].channelB_div = level;
+ PWM_slice_manual_data[_slice_num].channelB_Active = true;
+
+ // If A is active, set the data now
+ if (PWM_slice_manual_data[_slice_num].channelA_Active)
+ {
+ pwm_set_chan_level(_slice_num, PWM_CHAN_A, PWM_slice_manual_data[_slice_num].channelA_div);
+ }
+ }
+ else
+ {
+ PWM_LOGERROR1("Error, not correct PWM pin = ", _pin);
+
+ return false;
+ }
+
+ pwm_set_enabled(_slice_num, true);
+
+ PWM_LOGINFO3("pin = ", _pin, ", PWM_CHAN =", pwm_gpio_to_channel(_pin));
+
+ ////////////////////////////////
+
+ _enabled = true;
+
+ PWM_LOGINFO7("PWM enabled, slice =", _slice_num, ", top =", _PWM_config.top,
+ ", div =", _PWM_config.div, ", level =", level);
+
+ return true;
+ }
+
+ ///////////////////////////////////////////
+
+ bool setPWM(const uint8_t& pin, const float& frequency, const float& dutycycle, bool phaseCorrect = false)
{
bool newFreq = false;
bool newDutyCycle = false;
@@ -270,7 +373,7 @@ class RP2040_PWM
///////////////////////////////////////////
- bool setPWM_Period(uint8_t pin, float period_us, float dutycycle, bool phaseCorrect = false)
+ bool setPWM_Period(const uint8_t& pin, const float& period_us, const float& dutycycle, bool phaseCorrect = false)
{
return setPWM(pin, 1000000.0f / period_us, dutycycle, phaseCorrect);
}
@@ -293,28 +396,28 @@ class RP2040_PWM
///////////////////////////////////////////
- uint32_t get_TOP()
+ inline uint32_t get_TOP()
{
return _PWM_config.top;
}
///////////////////////////////////////////
- uint32_t get_DIV()
+ inline uint32_t get_DIV()
{
return _PWM_config.div;
}
///////////////////////////////////////////
- float getActualFreq()
+ inline float getActualFreq()
{
return _actualFrequency;
}
///////////////////////////////////////////
- uint32_t get_freq_CPU()
+ inline uint32_t get_freq_CPU()
{
return freq_CPU;
}
@@ -384,6 +487,5 @@ class RP2040_PWM
///////////////////////////////////////////
-
#endif // RP2040_PWM_H