Skip to content
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

zephyrCommon: Implement analogRead()/analogReference() #54

Merged
merged 2 commits into from
Oct 5, 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 @@ -8,6 +8,7 @@

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

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

#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

#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),

const struct pwm_dt_spec arduino_pwm[] =
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) };

Expand All @@ -31,6 +31,33 @@ size_t pwm_pin_index(pin_size_t pinNumber) {

#endif //CONFIG_PWM

#ifdef CONFIG_ADC

#define ADC_DT_SPEC(n,p,i) ADC_DT_SPEC_GET_BY_IDX(n, i),
#define ADC_PINS(n,p,i) DT_PROP_BY_IDX(n, p, i),
#define ADC_CH_CFG(n,p,i) arduino_adc[i].channel_cfg,

const struct adc_dt_spec arduino_adc[] =
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_DT_SPEC) };

/* io-channel-pins node provides a mapping digital pin numbers to adc channels */
const pin_size_t arduino_analog_pins[] =
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channel_pins, ADC_PINS) };

struct adc_channel_cfg channel_cfg[ARRAY_SIZE(arduino_analog_pins)] =
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_CH_CFG) };

size_t analog_pin_index(pin_size_t pinNumber) {
for(size_t i=0; i<ARRAY_SIZE(arduino_analog_pins); i++) {
if (arduino_analog_pins[i] == pinNumber) {
return i;
}
}
return (size_t)-1;
}

#endif //CONFIG_ADC

}

void yield(void) {
Expand Down Expand Up @@ -101,3 +128,56 @@ void analogWrite(pin_size_t pinNumber, int value)
}

#endif

#ifdef CONFIG_ADC

void analogReference(uint8_t mode)
{
/*
* The Arduino API not clearly defined what means of
* the mode argument of analogReference().
* Treat the value as equivalent to zephyr's adc_reference.
*/
size_t idx;
for (size_t i=0; i<ARRAY_SIZE(channel_cfg); i++) {
channel_cfg[i].reference = static_cast<adc_reference>(mode);
}
}

int analogRead(pin_size_t pinNumber)
{
int err;
int16_t buf;
struct adc_sequence seq = { .buffer = &buf, .buffer_size = sizeof(buf) };
size_t idx = analog_pin_index(pinNumber);

if (idx >= ARRAY_SIZE(arduino_adc) ) {
return -EINVAL;
}

/*
* ADC that is on MCU supported by Zephyr exists
* only 16bit resolution, currently.
*/
if (arduino_adc[idx].resolution > 16) {
return -ENOTSUP;
}

err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg);
if (err < 0) {
return err;
}

seq.channels = BIT(arduino_adc[idx].channel_id);
seq.resolution = arduino_adc[idx].resolution;
seq.oversampling = arduino_adc[idx].oversampling;

err = adc_read(arduino_adc[idx].dev, &seq);
if (err < 0) {
return err;
}

return buf;
}

#endif
11 changes: 11 additions & 0 deletions samples/analog_input/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 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(analog_input)

target_sources(app PRIVATE src/main.cpp)
zephyr_compile_options(-Wno-unused-variable -Wno-comment)
24 changes: 24 additions & 0 deletions samples/analog_input/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.. _analog_input:

Analog Input
############

Overview
********

The analog_input sample blinks the LED with control of the period
by the voltage of the input pin.
Inputting high voltage to blink the LED slowly.
Blink the LED fast on input voltage is low.
When the input is 0V, LED light.

Building and Running
********************

Build and flash analog_input sample as follows,

```sh
$> west build -p -b arduino_nano_33_ble sample/analog_input/

$> west flash --bossac=/home/$USER/.arduino15/packages/arduino/tools/bossac/1.9.1-arduino2/bossac
```
2 changes: 2 additions & 0 deletions samples/analog_input/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_ADC=y
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all this can be shifted into the project's global KConfig

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it.

CONFIG_ARDUINO_API=y
29 changes: 29 additions & 0 deletions samples/analog_input/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 TOKITA Hiroshi <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <Arduino.h>

const int analog_input = A0; // select the input pin for the potentiometer
const int ledPin = LED_BUILTIN; // select the pin for the LED
const float wait_factor = 1.f;

void setup() {
pinMode(ledPin, OUTPUT);
}

void loop() {
int value = 0;

value = analogRead(analog_input);

/* Blinks slowly when the input voltage is high */

digitalWrite(ledPin, HIGH);
delay(value * wait_factor);

digitalWrite(ledPin, LOW);
delay(value * wait_factor);
}
121 changes: 109 additions & 12 deletions variants/arduino_mkrzero/arduino_mkrzero.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/dt-bindings/adc/adc.h>

/ {
zephyr,user {
d0_gpios = <&arduino_mkr_header 0 0>;
Expand All @@ -27,27 +30,121 @@
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>;

io-channels = <&adc 0>,
<&adc 10>,
<&adc 11>,
<&adc 4>,
<&adc 5>,
<&adc 6>,
<&adc 7>;
io-channel-pins = <15 16 17 18 19 20 21>;
};
};

&pinctrl {
pwm_default: pwm_default {
group1 {
pinmux = <PA10F_TCC0_WO2>,
<PA11F_TCC0_WO3>;
};
};
pwm_default: pwm_default {
group1 {
pinmux = <PA10F_TCC0_WO2>,
<PA11F_TCC0_WO3>;
};
};

adc_default: adc_default {
group1 {
pinmux = <PA2B_ADC_AIN0>,
<PB2B_ADC_AIN10>,
<PB3B_ADC_AIN11>,
<PA4B_ADC_AIN4>,
<PA5B_ADC_AIN5>,
<PA6B_ADC_AIN6>,
<PA7B_ADC_AIN7>;
};
};
};

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

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

&adc {
status = "okay";
pinctrl-0 = <&adc_default>;
pinctrl-names = "default";

#address-cells = <1>;
#size-cells = <0>;

channel@0 {
reg = <0>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <0>;
};

channel@4 {
reg = <4>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <4>;
};

channel@5 {
reg = <5>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <5>;
};

channel@6 {
reg = <6>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <6>;
};

channel@7 {
reg = <7>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <7>;
};

pinctrl-0 = <&pwm_default>;
pinctrl-names = "default";
channel@10 {
reg = <10>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <10>;
};

channel@11 {
reg = <11>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <10>;
zephyr,input-positive = <11>;
};
};
Loading