From 2b9e811d0c5af9a72cc9ba2fb4df8ee14485314a Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Thu, 22 Sep 2022 07:14:33 +0900 Subject: [PATCH 1/2] zephyrCommon: Implement analogWrite() The 'pwms' node under the 'zephyr,user' defines available PWM channels. The 'pwm-pins' defines the mapping of PWM channels to pin numbers. API looks up the 'pwm-pins' when querying the PWM channel by digital pin number. So it should be in the same order as 'pwms' node. PWM channels should configure and tied to the output pins. The period property of the PWM channel is used as resolution as PWM. For original Arduino API compatibility, it should be 255. The period property and API argument determines the duty ratio. Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 1 + cores/arduino/zephyrCommon.cpp | 52 +++++++++++++++ .../arduino_mkrzero/arduino_mkrzero.overlay | 22 +++++++ .../arduino_nano_33_ble.overlay | 64 +++++++++++++++++++ .../arduino_nano_33_ble_sense.overlay | 64 +++++++++++++++++++ .../arduino_nano_33_iot.overlay | 34 ++++++++++ .../nrf52840dk_nrf52840.overlay | 61 ++++++++++++++++++ 7 files changed, 298 insertions(+) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 63013f9c..d54908f3 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -7,6 +7,7 @@ #include "api/ArduinoAPI.h" #include +#include #include #include diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 94b58674..1b830431 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -6,6 +6,33 @@ #include +#define PWM_DT_SPEC(n,p,i) PWM_DT_SPEC_GET_BY_IDX(n, i), +#define PWM_PINS(n,p,i) DT_PROP_BY_IDX(n, p, i), + +namespace { + +#ifdef CONFIG_PWM + +const struct pwm_dt_spec arduino_pwm[] = + { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) }; + +/* pwm-pins node provides a mapping digital pin numbers to pwm channels */ +const pin_size_t arduino_pwm_pins[] = + { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pins, PWM_PINS) }; + +size_t pwm_pin_index(pin_size_t pinNumber) { + for(size_t i=0; i= ARRAY_SIZE(arduino_pwm) ) { + return; + } + + if (((uint32_t)value) > arduino_pwm[idx].period) { + value = arduino_pwm[idx].period; + } else if (value < 0) { + value = 0; + } + + /* + * A duty ratio determines by the period value defined in dts + * and the value arguments. So usually the period value sets as 255. + */ + (void)pwm_set_cycles(arduino_pwm[idx].dev, arduino_pwm[idx].channel, + arduino_pwm[idx].period, value, arduino_pwm[idx].flags); +} + +#endif diff --git a/variants/arduino_mkrzero/arduino_mkrzero.overlay b/variants/arduino_mkrzero/arduino_mkrzero.overlay index 57f281ce..4b8f2508 100644 --- a/variants/arduino_mkrzero/arduino_mkrzero.overlay +++ b/variants/arduino_mkrzero/arduino_mkrzero.overlay @@ -27,5 +27,27 @@ d19_gpios = <&arduino_mkr_header 19 0>; /* D19 / A5 / I2C-SCL */ d20_gpios = <&arduino_mkr_header 20 0>; d21_gpios = <&arduino_mkr_header 21 0>; + pwms = <&tcc0 2 255>, + <&tcc0 3 255>; + pwm-pins = <2 3>; }; }; + +&pinctrl { + pwm_default: pwm_default { + group1 { + pinmux = , + ; + }; + }; +}; + +&tcc0 { + status = "okay"; + compatible = "atmel,sam0-tcc-pwm"; + prescaler = <2>; + #pwm-cells = <2>; + + pinctrl-0 = <&pwm_default>; + pinctrl-names = "default"; +}; diff --git a/variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay b/variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay index b1dc2d0c..d943c28b 100644 --- a/variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay +++ b/variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay @@ -22,5 +22,69 @@ d19_gpios = <&arduino_nano_header 19 0>; /* D19 / A5 / I2C-SCL */ d20_gpios = <&arduino_nano_header 20 0>; d21_gpios = <&arduino_nano_header 21 0>; + pwms = <&pwm1 1 255 PWM_POLARITY_NORMAL>, + <&pwm1 2 255 PWM_POLARITY_NORMAL>, + <&pwm1 3 255 PWM_POLARITY_NORMAL>, + <&pwm2 0 255 PWM_POLARITY_NORMAL>, + <&pwm2 1 255 PWM_POLARITY_NORMAL>, + <&pwm2 2 255 PWM_POLARITY_NORMAL>, + <&pwm2 3 255 PWM_POLARITY_NORMAL>; + pwm-pins = <3 5 6 13 9 10 11>; }; }; + +&pinctrl { + pwm1_default: pwm1_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm1_sleep: pwm1_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; + + pwm2_default: pwm2_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm2_sleep: pwm2_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; +}; + +&pwm1 { + status = "okay"; + pinctrl-0 = <&pwm1_default>; + pinctrl-1 = <&pwm1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm2 { + status = "okay"; + pinctrl-0 = <&pwm2_default>; + pinctrl-1 = <&pwm2_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/variants/arduino_nano_33_ble_sense/arduino_nano_33_ble_sense.overlay b/variants/arduino_nano_33_ble_sense/arduino_nano_33_ble_sense.overlay index b1dc2d0c..d943c28b 100644 --- a/variants/arduino_nano_33_ble_sense/arduino_nano_33_ble_sense.overlay +++ b/variants/arduino_nano_33_ble_sense/arduino_nano_33_ble_sense.overlay @@ -22,5 +22,69 @@ d19_gpios = <&arduino_nano_header 19 0>; /* D19 / A5 / I2C-SCL */ d20_gpios = <&arduino_nano_header 20 0>; d21_gpios = <&arduino_nano_header 21 0>; + pwms = <&pwm1 1 255 PWM_POLARITY_NORMAL>, + <&pwm1 2 255 PWM_POLARITY_NORMAL>, + <&pwm1 3 255 PWM_POLARITY_NORMAL>, + <&pwm2 0 255 PWM_POLARITY_NORMAL>, + <&pwm2 1 255 PWM_POLARITY_NORMAL>, + <&pwm2 2 255 PWM_POLARITY_NORMAL>, + <&pwm2 3 255 PWM_POLARITY_NORMAL>; + pwm-pins = <3 5 6 13 9 10 11>; }; }; + +&pinctrl { + pwm1_default: pwm1_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm1_sleep: pwm1_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; + + pwm2_default: pwm2_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm2_sleep: pwm2_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; +}; + +&pwm1 { + status = "okay"; + pinctrl-0 = <&pwm1_default>; + pinctrl-1 = <&pwm1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm2 { + status = "okay"; + pinctrl-0 = <&pwm2_default>; + pinctrl-1 = <&pwm2_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/variants/arduino_nano_33_iot/arduino_nano_33_iot.overlay b/variants/arduino_nano_33_iot/arduino_nano_33_iot.overlay index b1dc2d0c..80fa3f77 100644 --- a/variants/arduino_nano_33_iot/arduino_nano_33_iot.overlay +++ b/variants/arduino_nano_33_iot/arduino_nano_33_iot.overlay @@ -22,5 +22,39 @@ d19_gpios = <&arduino_nano_header 19 0>; /* D19 / A5 / I2C-SCL */ d20_gpios = <&arduino_nano_header 20 0>; d21_gpios = <&arduino_nano_header 21 0>; + pwms = <&tcc0 0 255>, + <&tcc0 1 255>, + <&tcc0 2 255>, + <&tcc0 3 255>, + <&tcc0 4 255>, + <&tcc0 5 255>, + <&tcc0 6 255>, + <&tcc0 7 255>; + pwm-pins = <6 5 17 12 2 3 9 10>; }; }; + +&pinctrl { + pwm_default: pwm_default { + group1 { + pinmux = , + , + , + , + , + , + , + ; + }; + }; +}; + +&tcc0 { + status = "okay"; + compatible = "atmel,sam0-tcc-pwm"; + prescaler = <2>; + #pwm-cells = <2>; + + pinctrl-0 = <&pwm_default>; + pinctrl-names = "default"; +}; diff --git a/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay b/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay index 6d2ee2ba..93fc03eb 100644 --- a/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay +++ b/variants/nrf52840dk_nrf52840/nrf52840dk_nrf52840.overlay @@ -23,5 +23,66 @@ d20_gpios = <&arduino_header 4 0>; d21_gpios = <&arduino_header 5 0>; d22_gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + pwms = <&pwm0 1 255 PWM_POLARITY_NORMAL>, + <&pwm0 2 255 PWM_POLARITY_NORMAL>, + <&pwm0 3 255 PWM_POLARITY_NORMAL>, + <&pwm1 0 255 PWM_POLARITY_NORMAL>, + <&pwm1 1 255 PWM_POLARITY_NORMAL>, + <&pwm1 2 255 PWM_POLARITY_NORMAL>; + pwm-pins = <22 3 5 6 9 10 11>; }; }; + +&pinctrl { + pwm0_default: pwm0_default { + group1 { + psels = , /* keep original config */ + , + , + ; + nordic,invert; + }; + }; + + pwm0_sleep: pwm0_sleep { + group1 { + psels = , /* keep original config */ + , + , + ; + low-power-enable; + }; + }; + + pwm1_default: pwm1_default { + group1 { + psels = , + , + ; + nordic,invert; + }; + }; + + pwm1_sleep: pwm1_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-1 = <&pwm0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm1 { + status = "okay"; + pinctrl-0 = <&pwm1_default>; + pinctrl-1 = <&pwm1_sleep>; + pinctrl-names = "default", "sleep"; +}; From 386d541872d86e26b541e7241c625e0ba84c5628 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Thu, 22 Sep 2022 13:12:05 +0900 Subject: [PATCH 2/2] samples: Added fade sample Added a fade sample to demonstrate how to use analogWrite API Signed-off-by: TOKITA Hiroshi --- samples/fade/CMakeLists.txt | 12 ++++++++++++ samples/fade/README.rst | 21 +++++++++++++++++++++ samples/fade/prj.conf | 2 ++ samples/fade/src/app.cpp | 31 +++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 samples/fade/CMakeLists.txt create mode 100644 samples/fade/README.rst create mode 100644 samples/fade/prj.conf create mode 100644 samples/fade/src/app.cpp diff --git a/samples/fade/CMakeLists.txt b/samples/fade/CMakeLists.txt new file mode 100644 index 00000000..a1142a94 --- /dev/null +++ b/samples/fade/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(DTC_OVERLAY_FILE $ENV{ZEPHYR_BASE}/../modules/lib/Arduino-Zephyr-API/variants/${BOARD}/${BOARD}.overlay) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(fade) + +target_sources(app PRIVATE src/app.cpp) + +zephyr_compile_options(-Wno-unused-variable -Wno-comment) diff --git a/samples/fade/README.rst b/samples/fade/README.rst new file mode 100644 index 00000000..8de33953 --- /dev/null +++ b/samples/fade/README.rst @@ -0,0 +1,21 @@ +.. _fade: + +Fade +#### + +Overview +******** + +The Fade sample gradually increases/decreases the voltage of the output pin. +When connecting the LED to the output pin, the LED blinks gradually. + +Building and Running +******************** + +Build and flash Fade sample as follows, + +```sh +$> west build -p -b arduino_nano_33_ble samples/basic/fade/ -DZEPHYR_EXTRA_MODULES=/home/$USER/zephyrproject/modules/lib/Arduino-Core-Zephyr + +$> west flash --bossac=/home/$USER/.arduino15/packages/arduino/tools/bossac/1.9.1-arduino2/bossac +``` diff --git a/samples/fade/prj.conf b/samples/fade/prj.conf new file mode 100644 index 00000000..cd969855 --- /dev/null +++ b/samples/fade/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ARDUINO_API=y +CONFIG_PWM=y diff --git a/samples/fade/src/app.cpp b/samples/fade/src/app.cpp new file mode 100644 index 00000000..e812dcd0 --- /dev/null +++ b/samples/fade/src/app.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +const int led = 3; // PWM output pin. +const int increments = 5; +const int wait_ms = 10; + +void setup() { + /* Pin that use as the PWM output need not be configured by pinMode() */ +} + +void loop() { + int value = 0; + while (value < 256) { + analogWrite(led, value); + value += increments; + delay(wait_ms); + } + + value = 255; + while (value >= 0) { + analogWrite(led, value); + value -= increments; + delay(wait_ms); + } +}