Skip to content

zephyrCommon: Implement analogWrite() #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "api/ArduinoAPI.h"

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/pwm.h>
#include <zephyr/kernel.h>

#include <variants.h>
Expand Down
52 changes: 52 additions & 0 deletions cores/arduino/zephyrCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@

#include <Arduino.h>

#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_pins); i++) {
if (arduino_pwm_pins[i] == pinNumber) {
return i;
}
}
return (size_t)-1;
}

#endif //CONFIG_PWM

}

void yield(void) {
k_yield();
}
Expand Down Expand Up @@ -49,3 +76,28 @@ unsigned long micros(void) {

unsigned long millis(void) { return k_uptime_get_32(); }

#ifdef CONFIG_PWM

void analogWrite(pin_size_t pinNumber, int value)
{
size_t idx = pwm_pin_index(pinNumber);

if (idx >= 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
12 changes: 12 additions & 0 deletions samples/fade/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
21 changes: 21 additions & 0 deletions samples/fade/README.rst
Original file line number Diff line number Diff line change
@@ -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
```
2 changes: 2 additions & 0 deletions samples/fade/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_ARDUINO_API=y
CONFIG_PWM=y
31 changes: 31 additions & 0 deletions samples/fade/src/app.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 TOKITA Hiroshi <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <Arduino.h>

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);
}
}
22 changes: 22 additions & 0 deletions variants/arduino_mkrzero/arduino_mkrzero.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <PA10F_TCC0_WO2>,
<PA11F_TCC0_WO3>;
};
};
};

&tcc0 {
status = "okay";
compatible = "atmel,sam0-tcc-pwm";
prescaler = <2>;
#pwm-cells = <2>;

pinctrl-0 = <&pwm_default>;
pinctrl-names = "default";
};
64 changes: 64 additions & 0 deletions variants/arduino_nano_33_ble/arduino_nano_33_ble.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <NRF_PSEL(PWM_OUT0, 1, 9)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 1, 12)>,
<NRF_PSEL(PWM_OUT2, 1, 13)>,
<NRF_PSEL(PWM_OUT3, 1, 14)>;
nordic,invert;
};
};

pwm1_sleep: pwm1_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 9)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 1, 12)>,
<NRF_PSEL(PWM_OUT2, 1, 13)>,
<NRF_PSEL(PWM_OUT3, 1, 14)>;
low-power-enable;
};
};

pwm2_default: pwm2_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 13)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 0, 27)>,
<NRF_PSEL(PWM_OUT2, 1, 2)>,
<NRF_PSEL(PWM_OUT3, 1, 1)>;
nordic,invert;
};
};

pwm2_sleep: pwm2_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 13)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 0, 27)>,
<NRF_PSEL(PWM_OUT2, 1, 2)>,
<NRF_PSEL(PWM_OUT3, 1, 1)>;
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";
};
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <NRF_PSEL(PWM_OUT0, 1, 9)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 1, 12)>,
<NRF_PSEL(PWM_OUT2, 1, 13)>,
<NRF_PSEL(PWM_OUT3, 1, 14)>;
nordic,invert;
};
};

pwm1_sleep: pwm1_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 9)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 1, 12)>,
<NRF_PSEL(PWM_OUT2, 1, 13)>,
<NRF_PSEL(PWM_OUT3, 1, 14)>;
low-power-enable;
};
};

pwm2_default: pwm2_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 13)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 0, 27)>,
<NRF_PSEL(PWM_OUT2, 1, 2)>,
<NRF_PSEL(PWM_OUT3, 1, 1)>;
nordic,invert;
};
};

pwm2_sleep: pwm2_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 13)>, /* keep original config */
<NRF_PSEL(PWM_OUT1, 0, 27)>,
<NRF_PSEL(PWM_OUT2, 1, 2)>,
<NRF_PSEL(PWM_OUT3, 1, 1)>;
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";
};
34 changes: 34 additions & 0 deletions variants/arduino_nano_33_iot/arduino_nano_33_iot.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <PA4E_TCC0_WO0>,
<PA5E_TCC0_WO1>,
<PA10F_TCC0_WO2>,
<PA19F_TCC0_WO3>,
<PB10F_TCC0_WO4>,
<PB11F_TCC0_WO5>,
<PA20F_TCC0_WO6>,
<PA21F_TCC0_WO7>;
};
};
};

&tcc0 {
status = "okay";
compatible = "atmel,sam0-tcc-pwm";
prescaler = <2>;
#pwm-cells = <2>;

pinctrl-0 = <&pwm_default>;
pinctrl-names = "default";
};
Loading