Skip to content

Commit

Permalink
Add Pico RP2040 (non-mbed) support (#36)
Browse files Browse the repository at this point in the history
* Add Pico RP2040 (non-mbed) support

* uniforming license

* author in license

---------

Co-authored-by: Fabiano Riccardi <[email protected]>
  • Loading branch information
adisbladis and fabianoriccardi authored Nov 21, 2023
1 parent 2b92b6e commit dda54f7
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 18 deletions.
10 changes: 8 additions & 2 deletions .github/workflows/LibraryBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ jobs:

# define each specific configuration
include:

# if the current configuration contains the parameter "config-name" and it is equal to "esp8266-v2",
# add the following parameters to this configuration. If board-type is never matched,
# add the following parameters to this configuration. If board-type is never matched,
# a new singular configuration is created
- config-name: esp8266-v2
platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
Expand Down Expand Up @@ -65,6 +65,12 @@ jobs:
arduino-boards-fqbn: arduino:samd:nano_33_iot
sketches-exclude: 3_dimmable_light_5_light, 5_dimmable_manager_n_lights

- config-name: rpi-pico
platform-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
arduino-platform: rp2040:[email protected]
arduino-boards-fqbn: rp2040:rp2040:rpipico
sketches-exclude: 3_dimmable_light_5_light, 5_dimmable_manager_n_lights

# Do not cancel all jobs / architectures if one job fails
fail-fast: false

Expand Down
3 changes: 3 additions & 0 deletions examples/4_lights_manager/4_lights_manager.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const int pins[N] = { 3, 4, 5 };
#elif defined(ARDUINO_ARCH_SAMD)
const int syncPin = 2;
const int pins[N] = { 3, 4, 5 };
#elif (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
const int syncPin = 2;
const int pins[N] = { 3, 4, 5 };
#endif

DimmableLightManager dlm;
Expand Down
2 changes: 2 additions & 0 deletions examples/6_8_lights_effects/effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ extern DimmableLightLinearized
lights[N_LIGHTS] = { { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 10 } };
#elif defined(ARDUINO_ARCH_SAMD)
lights[N_LIGHTS] = { { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 10 } };
#elif (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
lights[N_LIGHTS] = { { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }, { 9 }, { 10 } };
#endif

/**
Expand Down
2 changes: 2 additions & 0 deletions examples/6_8_lights_effects/effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const int syncPin = 23;
const int syncPin = 2;
#elif defined(ARDUINO_ARCH_SAMD)
const int syncPin = 2;
#elif (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
const int syncPin = 2;
#endif

#if defined(RAW_VALUES)
Expand Down
5 changes: 3 additions & 2 deletions library.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"espressif8266",
"espressif32",
"atmelavr",
"atmelsam"
"atmelsam",
"raspberrypi"
],
"dependencies": [
{
Expand Down Expand Up @@ -97,4 +98,4 @@
]
}
]
}
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ sentence=This library allows to easily control dimmers (also known as thyristors
paragraph=This library was born to control dimmable light bulbs, but actually dimmers are fully compatible with other AC loads like electrical heaters and motors (be aware of what you are doing!). Actually it works on ESP8266, ESP32, AVR and SAMD.
category=Device Control
url=https://github.com/fabianoriccardi/dimmable-light
architectures=esp8266,esp32,avr,samd
architectures=esp8266,esp32,avr,samd,rp2040
depends=ArduinoSTL
10 changes: 8 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ framework = arduino
platform = [email protected]
board = uno
framework = arduino
lib_deps =
lib_deps =
${env.lib_deps}
mike-matera/ArduinoSTL@^1.3.3
upload_speed = 115200
Expand All @@ -40,7 +40,7 @@ upload_speed = 115200
platform = [email protected]
board = megaatmega2560
framework = arduino
lib_deps =
lib_deps =
${env.lib_deps}
mike-matera/ArduinoSTL@^1.3.3
upload_speed = 115200
Expand All @@ -49,3 +49,9 @@ upload_speed = 115200
platform = [email protected]
board = nano_33_iot
framework = arduino

[env:rpipico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = pico
framework = arduino
board_build.core = earlephilhower
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This brief overview gives a glimpse of the variety of properties to consider whi
## Features

1. Control multiple thyristors using a single hardware timer
2. Compatible with multiple platforms (ESP8266/ESP32/AVR/SAMD)
2. Compatible with multiple platforms (ESP8266/ESP32/AVR/SAMD/RP2040)
3. Interrupt optimization (trigger interrupts only if necessary, no periodic interrupt)
4. Control the load by 2 measurement unit: gate activation time or linearized relative power
5. Documented parameters to finely tune the library on your hardware and requirements
Expand All @@ -29,7 +29,7 @@ Here the comparison against 3 similar and popular libraries:
|----------------------------------- |--------------------------------------------- |----------------------------------------------------- |---------------------------------- |---------------------------------- |
| Multiple dimmers | yes | yes | yes | 2 |
| Supported frequencies | 50/60Hz | 50Hz | 50/60Hz | 50/60Hz |
| Supported architectures | AVR, SAMD, ESP8266, ESP32 | AVR, SAMD, ESP8266, ESP32, STM32F1, STM32F4, SAM | AVR | AVR |
| Supported architectures | AVR, SAMD, ESP8266, ESP32, RP2040 | AVR, SAMD, ESP8266, ESP32, STM32F1, STM32F4, SAM | AVR | AVR |
| Control *effective* delivered power | yes, dynamic calculation | no | yes, static lookup table | no |
| Predefined effects | no | yes, automatic fade to new value | yes, swipe effect | no |
| Optional zero-crossing mode | no | no | yes | no |
Expand Down
6 changes: 3 additions & 3 deletions src/dimmable_light_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

bool DimmableLightManager::add(String lightName, uint8_t pin) {
const char* temp = lightName.c_str();
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD)
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040)
std::unordered_map<std::string, DimmableLight*>::const_iterator it = dla.find(temp);
#elif defined(AVR)
std::map<std::string, DimmableLight*>::const_iterator it = dla.find(temp);
Expand All @@ -37,7 +37,7 @@ bool DimmableLightManager::add(String lightName, uint8_t pin) {

DimmableLight* DimmableLightManager::get(String lightName) {
const char* temp = lightName.c_str();
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD)
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040)
std::unordered_map<std::string, DimmableLight*>::const_iterator it = dla.find(temp);
#elif defined(AVR)
std::map<std::string, DimmableLight*>::const_iterator it = dla.find(temp);
Expand All @@ -50,7 +50,7 @@ DimmableLight* DimmableLightManager::get(String lightName) {
}

std::pair<String, DimmableLight*> DimmableLightManager::get() {
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD)
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040)
static std::unordered_map<std::string, DimmableLight*>::const_iterator it = dla.begin();
#elif defined(AVR)
static std::map<std::string, DimmableLight*>::const_iterator it = dla.begin();
Expand Down
4 changes: 2 additions & 2 deletions src/dimmable_light_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#include "dimmable_light.h"

#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD)
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040)
// Unfortunately Arduino defines max/min macros, those create conflicts with the one
// defined by C++/STL environment
#undef max
Expand Down Expand Up @@ -68,7 +68,7 @@ class DimmableLightManager {
}

private:
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD)
#if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040)
std::unordered_map<std::string, DimmableLight*> dla;
#elif defined(AVR)
std::map<std::string, DimmableLight*> dla;
Expand Down
54 changes: 54 additions & 0 deletions src/hw_timer_pico.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/******************************************************************************
* This file is part of Dimmable Light for Arduino, a library to control *
* dimmers. *
* *
* Copyright (C) 2018-2023 Fabiano Riccardi *
* *
* Dimmable Light for Arduino is free software; you can redistribute *
* it and/or modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, see <http://www.gnu.org/licenses/>. *
******************************************************************************/

#if defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)

#include "hw_timer_pico.h"
#include <Arduino.h>

static void (*timer_callback)() = nullptr;
static alarm_id_t alarm_id;
static alarm_pool_t *alarm_pool;

void timerBegin() {
alarm_pool = alarm_pool_get_default();
}

void timerSetCallback(void (*callback)()) {
timer_callback = callback;
}

void timerStart(uint64_t t) {
if (alarm_id) {
cancel_alarm(alarm_id);
alarm_id = 0;
}

alarm_id = alarm_pool_add_alarm_in_us(
alarm_pool, t,
[](alarm_id_t, void *) -> int64_t {
if (timer_callback != nullptr) { timer_callback(); }
alarm_id = 0;
return 0; // Do not reschedule alarm
},
NULL, true);
}

#endif // END ARDUINO_ARCH_RP2040
45 changes: 45 additions & 0 deletions src/hw_timer_pico.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/******************************************************************************
* This file is part of Dimmable Light for Arduino, a library to control *
* dimmers. *
* *
* Copyright (C) 2023 Adam Hoese *
* *
* Dimmable Light for Arduino is free software; you can redistribute *
* it and/or modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, see <http://www.gnu.org/licenses/>. *
******************************************************************************/

#if defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)

#ifndef HW_TIMER_PICO_H
#define HW_TIMER_PICO_H

#include <stdint.h>

/**
* Initialize the timer.
*/
void timerBegin();

/**
* Set callback function on timer triggers
*/
void timerSetCallback(void (*callback)());

/**
* Start the timer to trigger after the specified number of microseconds.
*/
void timerStart(uint64_t t);

#endif // HW_TIMER_PICO_H

#endif // ARDUINO_ARCH_RP2040
30 changes: 26 additions & 4 deletions src/thyristor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
#include "hw_timer_avr.h"
#elif defined(ARDUINO_ARCH_SAMD)
#include "hw_timer_samd.h"
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
#include "hw_timer_pico.h"
#else
#error "only ESP8266, ESP32, AVR, SAMD architectures are supported"
#error "only ESP8266, ESP32, AVR, SAMD & RP2040 (non-mbed) architectures are supported"
#endif

// Ignore zero-cross interrupts when they occurs too early w.r.t semi-period ideal length.
Expand Down Expand Up @@ -192,7 +194,7 @@ void activate_thyristors() {
if (thyristorManaged < Thyristor::nThyristors) {
int delayAbsolute = pinDelay[thyristorManaged].delay;

#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD)
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD) || (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
int delayRelative = delayAbsolute - pinDelay[firstToBeUpdated].delay;
#endif

Expand All @@ -204,6 +206,10 @@ void activate_thyristors() {
timerSetAlarm(microsecond2Tick(delayRelative));
#elif defined(ARDUINO_ARCH_SAMD)
timerStart(microsecond2Tick(delayRelative));
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
timerStart(delayRelative);
#else
#error "Not implemented"
#endif
} else {

Expand All @@ -217,12 +223,14 @@ void activate_thyristors() {
stopTimer();
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD)
// Given actual HAL, AVR and SAMD counter automatically stops on interrupt
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
// Timer callback is not rescheduled
#endif
#else
// If there are not more thyristors to serve, set timer to turn off gates' signal
uint16_t delayAbsolute = semiPeriodLength - gateTurnOffTime;

#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD)
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD) || (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
uint16_t delayRelative = delayAbsolute - pinDelay[firstToBeUpdated].delay;
#endif

Expand All @@ -238,6 +246,11 @@ void activate_thyristors() {
#elif defined(ARDUINO_ARCH_SAMD)
timerSetCallback(turn_off_gates_int);
timerStart(microsecond2Tick(delayRelative));
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
timerSetCallback(turn_off_gates_int);
timerStart(delayRelative);
#else
#error "Not implemented"
#endif
#endif
}
Expand Down Expand Up @@ -438,6 +451,11 @@ void zero_cross_int() {
#elif defined(ARDUINO_ARCH_SAMD)
timerSetCallback(activate_thyristors);
timerStart(microsecond2Tick(delayAbsolute));
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
timerSetCallback(activate_thyristors);
timerStart(pinDelay[thyristorManaged].delay);
#else
# error "Not implemented"
#endif
} else {

Expand All @@ -457,6 +475,8 @@ void zero_cross_int() {
timerStop();
#elif defined(ARDUINO_ARCH_SAMD)
// Given actual HAL, and SAMD counter automatically stops on interrupt
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
// Timer callback is not rescheduled
#endif
}
}
Expand Down Expand Up @@ -601,9 +621,11 @@ void Thyristor::begin() {
T1I = 0;
#elif defined(ARDUINO_ARCH_ESP32)
timerInit(isr_selector);
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD)
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_SAMD) || (defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
timerSetCallback(activate_thyristors);
timerBegin();
#else
#error "Not implemented"
#endif

#ifdef MONITOR_FREQUENCY
Expand Down

0 comments on commit dda54f7

Please sign in to comment.