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/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); + } +} 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"; +};