From c965ce3de68d3f848e9aa3f0461001123afbbdb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= Date: Mon, 21 Jun 2021 17:41:30 +0200 Subject: [PATCH 1/4] boards/common/arduino-atmega: define F_CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the following error: $ BOARD=arduino-mega2560 make -C tests/pkg_arduino_sdi_12/ [...] [...]/RIOT/build/pkg/arduino_sdi_12/src/SDI12_boards.cpp:35:16: error: ‘preSDI12_TCCR2B’ defined but not used [-Werror=unused-variable 35 | static uint8_t preSDI12_TCCR2B; --- .../arduino-atmega/include/arduino_board.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/boards/common/arduino-atmega/include/arduino_board.h b/boards/common/arduino-atmega/include/arduino_board.h index ee7a01866701..29ac70f6daf3 100644 --- a/boards/common/arduino-atmega/include/arduino_board.h +++ b/boards/common/arduino-atmega/include/arduino_board.h @@ -170,6 +170,22 @@ static const arduino_pwm_t arduino_pwm_list[] = { #endif }; +/** + * @brief F_CPU defines the CPU frequency in Hz. + * + * This is used in AVR's libc delay.h and setbaud.h + * + * In RIOT delay() has a different implementation using ztimer, and F_CPU is + * already defined when using setbaud.h (see cpu/atmega_common/periph/uart.c) + * + * However Arduino libraries and sketches may expect F_CPU to be defined and + * fail otherwise (for example the Arduino SDI-12 package expects this, for AVR + * cpus). For this reason we define F_CPU here, if not already defined. + */ +#ifndef F_CPU +#define F_CPU CLOCK_CORECLOCK +#endif + #ifdef __cplusplus } #endif From a651315fbe28e6b33a514e163e132ea35d755cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= Date: Fri, 21 May 2021 11:30:31 +0200 Subject: [PATCH 2/4] sys/arduino: add interrupts/noInterrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the error: $ BOARD=arduino-mega2560 make -C tests/pkg_arduino_sdi_12/ [...] [...]/RIOT/build/pkg/arduino_sdi_12/src/SDI12.cpp:379:7: error: ‘interrupts’ was not declared in this scope --- sys/arduino/include/arduino.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sys/arduino/include/arduino.hpp b/sys/arduino/include/arduino.hpp index 782b8685d8eb..9117bfa74f25 100644 --- a/sys/arduino/include/arduino.hpp +++ b/sys/arduino/include/arduino.hpp @@ -23,6 +23,7 @@ extern "C" { #include +#include "irq.h" #include "periph/gpio.h" #include "arduino_board.h" } @@ -165,5 +166,21 @@ int analogRead(int pin); void analogWrite(int pin, int value); #endif +/** + * @brief Enables interrupts + */ +static inline void interrupts(void) +{ + irq_enable(); +} + +/** + * @brief Disables interrupts + */ +static inline void noInterrupts(void) +{ + irq_disable(); +} + #endif /* ARDUINO_HPP */ /** @} */ From d70ffc69fb57f973816815586ac88c25dd84fa7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= Date: Thu, 28 Oct 2021 16:16:45 +0200 Subject: [PATCH 3/4] pkg/arduino_api: add new package From https://github.com/arduino/ArduinoCore-API Required by pkg/arduino_sdi_12 Improves compatibility with Arduino --- pkg/arduino_api/Kconfig | 4 + pkg/arduino_api/Makefile | 11 +++ pkg/arduino_api/Makefile.dep | 1 + pkg/arduino_api/Makefile.include | 3 + pkg/arduino_api/doc.txt | 6 ++ .../0001-Chages-for-RIOT-integration.patch | 95 +++++++++++++++++++ 6 files changed, 120 insertions(+) create mode 100644 pkg/arduino_api/Kconfig create mode 100644 pkg/arduino_api/Makefile create mode 100644 pkg/arduino_api/Makefile.dep create mode 100644 pkg/arduino_api/Makefile.include create mode 100644 pkg/arduino_api/doc.txt create mode 100644 pkg/arduino_api/patches/0001-Chages-for-RIOT-integration.patch diff --git a/pkg/arduino_api/Kconfig b/pkg/arduino_api/Kconfig new file mode 100644 index 000000000000..ca6b4cd312fa --- /dev/null +++ b/pkg/arduino_api/Kconfig @@ -0,0 +1,4 @@ +config PACKAGE_ARDUINO_API + bool "Arduino API package" + depends on TEST_KCONFIG + depends on MODULE_ARDUINO diff --git a/pkg/arduino_api/Makefile b/pkg/arduino_api/Makefile new file mode 100644 index 000000000000..6aef8114a056 --- /dev/null +++ b/pkg/arduino_api/Makefile @@ -0,0 +1,11 @@ +PKG_NAME=arduino_api +PKG_URL=https://github.com/arduino/ArduinoCore-API +PKG_VERSION=e03b65374c614130aa1b11597e07b3b5089a726d +PKG_LICENSE=LGPL-2.1 + +GITAMFLAGS = --3way + +include $(RIOTBASE)/pkg/pkg.mk + +all: + $(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/api -f $(RIOTBASE)/Makefile.base MODULE=$(PKG_NAME) diff --git a/pkg/arduino_api/Makefile.dep b/pkg/arduino_api/Makefile.dep new file mode 100644 index 000000000000..60bad41674b4 --- /dev/null +++ b/pkg/arduino_api/Makefile.dep @@ -0,0 +1 @@ +USEMODULE += arduino diff --git a/pkg/arduino_api/Makefile.include b/pkg/arduino_api/Makefile.include new file mode 100644 index 000000000000..d8d5bd0cbecb --- /dev/null +++ b/pkg/arduino_api/Makefile.include @@ -0,0 +1,3 @@ +INCLUDES += -I$(PKGDIRBASE)/arduino_api/api + +CXXEXFLAGS += -std=c++11 diff --git a/pkg/arduino_api/doc.txt b/pkg/arduino_api/doc.txt new file mode 100644 index 000000000000..67238b210024 --- /dev/null +++ b/pkg/arduino_api/doc.txt @@ -0,0 +1,6 @@ +/** + * @defgroup pkg_arduino_api Hardware independent layer of the Arduino cores + * @ingroup pkg + * @brief Hardware independent layer of the Arduino cores + * @see https://github.com/arduino/ArduinoCore-API + */ diff --git a/pkg/arduino_api/patches/0001-Chages-for-RIOT-integration.patch b/pkg/arduino_api/patches/0001-Chages-for-RIOT-integration.patch new file mode 100644 index 000000000000..9760cc7c80d8 --- /dev/null +++ b/pkg/arduino_api/patches/0001-Chages-for-RIOT-integration.patch @@ -0,0 +1,95 @@ +From 450ac61995792240213e2d05ab83039e4ef07df0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= +Date: Wed, 13 Oct 2021 09:25:24 +0200 +Subject: [PATCH 1/1] Chages for RIOT integration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +- Fix "has not been declared" errors +- Remove attach/detach interrupt funcions + +Signed-off-by: J. David Ibáñez +--- + api/Common.h | 3 --- + api/Interrupts.h | 44 -------------------------------------------- + api/Stream.h | 2 +- + 3 files changed, 1 insertion(+), 48 deletions(-) + +diff --git api/Common.h api/Common.h +index c40a35a..c2d9de4 100644 +--- api/Common.h ++++ api/Common.h +@@ -109,9 +109,6 @@ unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout); + void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val); + uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder); + +-void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode); +-void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void* param); +-void detachInterrupt(pin_size_t interruptNumber); + + void setup(void); + void loop(void); +diff --git api/Interrupts.h api/Interrupts.h +index e306fc7..e69de29 100644 +--- api/Interrupts.h ++++ api/Interrupts.h +@@ -1,44 +0,0 @@ +-#ifndef W_INTERRUPTS_CPP +-#define W_INTERRUPTS_CPP +-#ifdef __cplusplus +- +-#include +-#include +-#include +-#include "Common.h" +- +-namespace arduino { +- +-template +-using voidTemplateFuncPtrParam = void (*)(T param); +- +-template struct __container__ { +- void* param; +- voidTemplateFuncPtrParam function; +-}; +- +-// C++ only overloaded version of attachInterrupt function +-template void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam userFunc, PinStatus mode, T& param) { +- +- struct __container__ *cont = new __container__(); +- cont->param = ¶m; +- cont->function = userFunc; +- +- // TODO: check lambda scope +- // TODO: add structure to delete(__container__) when detachInterrupt() is called +- auto f = [](void* a) -> void +- { +- T param = *(T*)((struct __container__*)a)->param; +- (((struct __container__*)a)->function)(param); +- }; +- +- attachInterruptParam(interruptNum, f, mode, cont); +-} +- +-template void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam userFunc, PinStatus mode, T* param) { +- attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, (void*)param); +-} +- +-} +-#endif +-#endif +diff --git api/Stream.h api/Stream.h +index e81c71b..b22d0b2 100644 +--- api/Stream.h ++++ api/Stream.h +@@ -130,4 +130,4 @@ class Stream : public Print + + } + +-using arduino::Stream; +\ No newline at end of file ++using namespace arduino; +-- +2.32.0 + From 5ce514a10597686cf008ac005f25c4cab25f3d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= Date: Thu, 20 May 2021 13:39:09 +0200 Subject: [PATCH 4/4] pkg/arduino_sdi_12: add new package From https://github.com/EnviroDIY/Arduino-SDI-12 --- pkg/Kconfig | 1 + pkg/arduino_sdi_12/Kconfig | 4 + pkg/arduino_sdi_12/Makefile | 11 ++ pkg/arduino_sdi_12/Makefile.dep | 4 + pkg/arduino_sdi_12/Makefile.include | 1 + pkg/arduino_sdi_12/doc.txt | 6 + ...gpio-to-handle-pin-change-interrupts.patch | 62 ++++++++++ tests/pkg_arduino_sdi_12/Makefile | 10 ++ tests/pkg_arduino_sdi_12/README.md | 42 +++++++ tests/pkg_arduino_sdi_12/main.cpp | 114 ++++++++++++++++++ 10 files changed, 255 insertions(+) create mode 100644 pkg/arduino_sdi_12/Kconfig create mode 100644 pkg/arduino_sdi_12/Makefile create mode 100644 pkg/arduino_sdi_12/Makefile.dep create mode 100644 pkg/arduino_sdi_12/Makefile.include create mode 100644 pkg/arduino_sdi_12/doc.txt create mode 100644 pkg/arduino_sdi_12/patches/0001-Use-RIOT-s-gpio-to-handle-pin-change-interrupts.patch create mode 100644 tests/pkg_arduino_sdi_12/Makefile create mode 100644 tests/pkg_arduino_sdi_12/README.md create mode 100644 tests/pkg_arduino_sdi_12/main.cpp diff --git a/pkg/Kconfig b/pkg/Kconfig index 04a9f4999666..83b9b1517e57 100644 --- a/pkg/Kconfig +++ b/pkg/Kconfig @@ -6,6 +6,7 @@ # menu "Packages" +rsource "arduino_sdi_12/Kconfig" rsource "c25519/Kconfig" rsource "cayenne-lpp/Kconfig" rsource "cifra/Kconfig" diff --git a/pkg/arduino_sdi_12/Kconfig b/pkg/arduino_sdi_12/Kconfig new file mode 100644 index 000000000000..9ff459a2e55c --- /dev/null +++ b/pkg/arduino_sdi_12/Kconfig @@ -0,0 +1,4 @@ +config PACKAGE_ARDUINO_SDI_12 + bool "Arduino SDI-12 package" + depends on TEST_KCONFIG + depends on PACKAGE_ARDUINO_API diff --git a/pkg/arduino_sdi_12/Makefile b/pkg/arduino_sdi_12/Makefile new file mode 100644 index 000000000000..bc4e253f625e --- /dev/null +++ b/pkg/arduino_sdi_12/Makefile @@ -0,0 +1,11 @@ +PKG_NAME=arduino_sdi_12 +PKG_URL=https://github.com/EnviroDIY/Arduino-SDI-12 +PKG_VERSION=fd9699b390edeac3a8681e2a6d4fe2ba8b1f9a51 +PKG_LICENSE=BSD-3-Clause + +GITAMFLAGS = --3way + +include $(RIOTBASE)/pkg/pkg.mk + +all: + $(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/src -f $(RIOTBASE)/Makefile.base MODULE=$(PKG_NAME) diff --git a/pkg/arduino_sdi_12/Makefile.dep b/pkg/arduino_sdi_12/Makefile.dep new file mode 100644 index 000000000000..d1f5055aab5a --- /dev/null +++ b/pkg/arduino_sdi_12/Makefile.dep @@ -0,0 +1,4 @@ +FEATURES_REQUIRED += periph_gpio_irq +USEMODULE += atmega_pcint + +USEPKG += arduino_api diff --git a/pkg/arduino_sdi_12/Makefile.include b/pkg/arduino_sdi_12/Makefile.include new file mode 100644 index 000000000000..0dc824d92c30 --- /dev/null +++ b/pkg/arduino_sdi_12/Makefile.include @@ -0,0 +1 @@ +INCLUDES += -I$(PKGDIRBASE)/arduino_sdi_12/src diff --git a/pkg/arduino_sdi_12/doc.txt b/pkg/arduino_sdi_12/doc.txt new file mode 100644 index 000000000000..465a7694a160 --- /dev/null +++ b/pkg/arduino_sdi_12/doc.txt @@ -0,0 +1,6 @@ +/** + * @defgroup pkg_arduino_sdi_12 Arduino library for SDI-12 communication + * @ingroup pkg + * @brief Implements support for the SDI-12 serial communications protocol + * @see https://github.com/EnviroDIY/Arduino-SDI-12 + */ diff --git a/pkg/arduino_sdi_12/patches/0001-Use-RIOT-s-gpio-to-handle-pin-change-interrupts.patch b/pkg/arduino_sdi_12/patches/0001-Use-RIOT-s-gpio-to-handle-pin-change-interrupts.patch new file mode 100644 index 000000000000..947ebabf4b93 --- /dev/null +++ b/pkg/arduino_sdi_12/patches/0001-Use-RIOT-s-gpio-to-handle-pin-change-interrupts.patch @@ -0,0 +1,62 @@ +From 03139fbb7f311fa210b9f0dbfd10899a8a336af9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= +Date: Thu, 7 Oct 2021 19:35:14 +0200 +Subject: [PATCH] Use RIOT's gpio to handle pin change interrupts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: J. David Ibáñez +--- + src/SDI12.cpp | 8 +++++--- + src/SDI12.h | 4 ++-- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git src/SDI12.cpp src/SDI12.cpp +index c71e998..257eb5a 100644 +--- src/SDI12.cpp ++++ src/SDI12.cpp +@@ -349,10 +349,11 @@ void SDI12::setPinInterrupts(bool enable) { + // We don't detach the function from the interrupt for AVR processors + } + #else ++ gpio_t pin = arduino_pinmap[_dataPin]; + if (enable) { +- return; ++ gpio_init_int(pin, GPIO_IN, GPIO_BOTH, handleInterrupt, NULL); + } else { +- return; ++ gpio_irq_disable(pin); + } + #endif + } +@@ -557,7 +558,8 @@ void ICACHE_RAM_ATTR SDI12::handleInterrupt() { + if (_activeObject) _activeObject->receiveISR(); + } + #else +-void SDI12::handleInterrupt() { ++void SDI12::handleInterrupt(void *arg) { ++ (void)arg; + if (_activeObject) _activeObject->receiveISR(); + } + #endif +diff --git src/SDI12.h src/SDI12.h +index ec949e3..6469c7b 100644 +--- src/SDI12.h ++++ src/SDI12.h +@@ -971,10 +971,10 @@ class SDI12 : public Stream { + * + * On espressif boards (ESP8266 and ESP32), the ISR must be stored in IRAM + */ +- static void handleInterrupt(); ++ static void handleInterrupt(void *arg = NULL); + + /** on AVR boards, uncomment to use your own PCINT ISRs */ +- // #define SDI12_EXTERNAL_PCINT ++ #define SDI12_EXTERNAL_PCINT + /**@}*/ + }; + +-- +2.32.0 + diff --git a/tests/pkg_arduino_sdi_12/Makefile b/tests/pkg_arduino_sdi_12/Makefile new file mode 100644 index 000000000000..cd66097236ad --- /dev/null +++ b/tests/pkg_arduino_sdi_12/Makefile @@ -0,0 +1,10 @@ +include ../Makefile.tests_common + +USEPKG += arduino_sdi_12 + +BOARD_WHITELIST := \ + arduino-leonardo \ + arduino-mega2560 \ + # + +include $(RIOTBASE)/Makefile.include diff --git a/tests/pkg_arduino_sdi_12/README.md b/tests/pkg_arduino_sdi_12/README.md new file mode 100644 index 000000000000..0f4cde0083a6 --- /dev/null +++ b/tests/pkg_arduino_sdi_12/README.md @@ -0,0 +1,42 @@ +The purpose of this test program is to verify that the `arduino_sdi_12` package +works. + +To test it you will need a SDI-12 sensor. The SDI-12 protocol uses 3 wires: +power, ground, and data. Use the D13 pin for the data line. + +The program will loop forever. In every loop it: + +- Tries to find the address of the attached sensor (sends the `?!` command); +- Asks the sensor to identify itself (sends the `aI!` command); +- Asks the sensor to start a measurement (sends the `aM!` command); +- Waits for as many seconds as the sensor said in its response to the + measurement command; +- Asks the sensor for the data, the result of the measurement (sends the `aD0!` + command); +- Waits 5 seconds and starts the loop again. + +This is an example, with the Arduino Mega2560 board and the Decagon CTD-10 +sensor: + + $ BOARD=arduino-mega2560 make -C tests/pkg_arduino_sdi_12 all flash term + [...] + 2021-09-28 12:14:57,492 # main(): This is RIOT! (Version: 2021.10-devel-776-gc7af21-sdi12) + 2021-09-28 12:14:57,496 # Testing the Arduino-SDI-12 package + 2021-09-28 12:14:57,995 # + 2021-09-28 12:14:58,007 # Send: ?! + 2021-09-28 12:14:58,352 # Recv: 0 + 2021-09-28 12:14:58,364 # Send: 0I! + 2021-09-28 12:14:58,749 # Recv: 013DECAGON CTD-103991059303507 + 2021-09-28 12:14:58,761 # Send: 0M! + 2021-09-28 12:14:59,118 # Recv: 00013 + 2021-09-28 12:15:00,129 # Send: 0D0! + 2021-09-28 12:15:00,502 # Recv: 0+35+26.4+0 + 2021-09-28 12:15:05,507 # + 2021-09-28 12:15:05,519 # Send: ?! + 2021-09-28 12:15:05,863 # Recv: 0 + 2021-09-28 12:15:05,875 # Send: 0I! + 2021-09-28 12:15:06,260 # Recv: 013DECAGON CTD-103991059303507 + 2021-09-28 12:15:06,268 # Send: 0M! + 2021-09-28 12:15:06,629 # Recv: 00013 + 2021-09-28 12:15:07,641 # Send: 0D0! + 2021-09-28 12:15:08,013 # Recv: 0+36+26.4+0 diff --git a/tests/pkg_arduino_sdi_12/main.cpp b/tests/pkg_arduino_sdi_12/main.cpp new file mode 100644 index 000000000000..9919703ffd78 --- /dev/null +++ b/tests/pkg_arduino_sdi_12/main.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2021 J. David Ibáñez + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Tests the Arduino-SDI-12 package + * + * @author J. David Ibáñez + * + * @} + */ + +#include +#include + +#ifndef SDI12_DATA_PIN +#define SDI12_DATA_PIN 13 +#endif + +SDI12 sdi12(SDI12_DATA_PIN); + +void sendCommand(const char *cmd) +{ + print_str("Send: "); + print_str(cmd); + print_str("\n"); + sdi12.clearBuffer(); + sdi12.sendCommand(cmd); + delay(300); +} + +void readResponse(char *buffer) +{ + int i = 0; + while (sdi12.available()) { + char c = sdi12.read(); + if (c == '\0') { + continue; + } + + buffer[i++] = c; + } + buffer[i] = '\0'; + + print_str("Recv: "); + print_str(buffer); + + // Responses from SDI-12 end by \r\n + if (buffer[0] == '\0') { + print_str("\n"); + } +} + +int main(void) +{ + char cmd[10]; + char out[50]; + + print_str("Testing the Arduino-SDI-12 package\n"); + + sdi12.begin(); + delay(500); // allow things to settle + + while (1) { + print_str("\n"); + + // Address query command (?!) + sendCommand("?!"); + readResponse(out); + if (strlen(out) == 0) { + continue; + } + + // For the rest of the loop the first command char will always be the + // device address + cmd[0] = out[0]; + + // Identification command (aI!) + cmd[1] = 'I'; + cmd[2] = '!'; + cmd[3] = '\0'; + sendCommand(cmd); + readResponse(out); + + // Start measurement (aM!) + cmd[1] = 'M'; + sendCommand(cmd); + readResponse(out); // atttn + + // Wait ttt seconds + unsigned int ttt; + ttt = (out[1] - '0') * 100 + (out[2] - '0') * 10 + (out[3] - '0'); + delay(ttt * 1000); + + // Data command (aD0!) + cmd[1] = 'D'; + cmd[2] = '0'; + cmd[3] = '!'; + cmd[4] = '\0'; + sendCommand(cmd); + readResponse(out); + + // Repeat in 5 seconds + delay(5000); + } +}