From 5e27f4037ed1d083ffffa458104c9ea89e363f4f Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 23 May 2024 11:34:28 -0400 Subject: [PATCH] merge master to rpi_gpiod branch --- build.sh | 22 +++++-- defines.h | 2 +- gpio.cpp | 134 +++++++++++++++++++++++++++++++++++++++ opensprinkler_server.cpp | 32 ++++++---- 4 files changed, 171 insertions(+), 19 deletions(-) diff --git a/build.sh b/build.sh index a221645b..ae257c8d 100755 --- a/build.sh +++ b/build.sh @@ -13,25 +13,39 @@ echo "Building OpenSprinkler..." if [ "$1" == "demo" ]; then echo "Installing required libraries..." apt-get install -y libmosquitto-dev - echo "Compiling firmware..." + echo "Compiling demo firmware..." g++ -o OpenSprinkler -DDEMO -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto elif [ "$1" == "osbo" ]; then echo "Installing required libraries..." apt-get install -y libmosquitto-dev - echo "Compiling firmware..." + echo "Compiling osbo firmware..." g++ -o OpenSprinkler -DOSBO -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto else echo "Installing required libraries..." apt-get update apt-get install -y libmosquitto-dev apt-get install -y raspi-gpio + apt-get install -y libi2c-dev + apt-get install -y libssl-dev + apt-get install -y libgpiod-dev if ! command -v raspi-gpio &> /dev/null then echo "Command raspi-gpio is required and is not installed" exit 0 fi - echo "Compiling firmware..." - g++ -o OpenSprinkler -DOSPI -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto + + USEGPIO="" + GPIOLIB="" + + + if [ -h "/sys/class/gpio/gpiochip512" ]; then + echo "using libgpiod" + USEGPIO="-DLIBGPIOD" + GPIOLIB="-lgpiod" + fi + + echo "Compiling ospi firmware..." + g++ -o OpenSprinkler -DOSPI $USEGPIO -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto $GPIOLIB fi if [ ! "$SILENT" = true ] && [ -f OpenSprinkler.launch ] && [ ! -f /etc/init.d/OpenSprinkler.sh ]; then diff --git a/defines.h b/defines.h index d131ed45..8c758b26 100755 --- a/defines.h +++ b/defines.h @@ -36,7 +36,7 @@ typedef unsigned long ulong; // if this number is different from the one stored in non-volatile memory // a device reset will be automatically triggered -#define OS_FW_MINOR 3 // Firmware minor version +#define OS_FW_MINOR 4 // Firmware minor version /** Hardware version base numbers */ #define OS_HW_VERSION_BASE 0x00 // OpenSprinkler diff --git a/gpio.cpp b/gpio.cpp index 5b7378e2..aafc3a27 100644 --- a/gpio.cpp +++ b/gpio.cpp @@ -177,6 +177,8 @@ byte digitalReadExt(byte pin) { #elif defined(OSPI) || defined(OSBO) +#if !defined(LIBGPIOD) // use classic sysfs + #include #include #include @@ -442,6 +444,138 @@ void attachInterrupt(int pin, const char* mode, void (*isr)(void)) { delay(1) ; pthread_mutex_unlock (&pinMutex) ; } +#else // use GPIOD + +/** + * NEW GPIO Implementation for Raspberry Pi OS 12 (bookworm) + * + * Thanks to Jason Balonso + * https://github.com/jbalonso/ + * + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#define BUFFER_MAX 64 +#define GPIO_MAX 64 + +// GPIO interfaces +const char *gpio_chipname = "gpiochip0"; +const char *gpio_consumer = "opensprinkler"; + +struct gpiod_chip *chip = NULL; +struct gpiod_line* gpio_lines[] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, +}; + +int assert_gpiod_chip() { + if( !chip ) { + chip = gpiod_chip_open_by_name(gpio_chipname); + if( !chip ) { + DEBUG_PRINTLN("failed to open gpio chip"); + return -1; + } else { + DEBUG_PRINTLN("gpio chip opened"); + return 0; + } + } + return 0; +} + +int assert_gpiod_line(int pin) { + if( !gpio_lines[pin] ) { + if( assert_gpiod_chip() ) { return -1; } + gpio_lines[pin] = gpiod_chip_get_line(chip, pin); + if( !gpio_lines[pin] ) { + DEBUG_PRINT("failed to open gpio line "); + DEBUG_PRINTLN(pin); + return -1; + } else { + DEBUG_PRINT("opened gpio line "); + DEBUG_PRINT(pin); + return 0; + } + } + return 0; +} + +/** Set pin mode, in or out */ +void pinMode(int pin, byte mode) { + if( assert_gpiod_line(pin) ) { return; } + switch(mode) { + case INPUT: + gpiod_line_request_input(gpio_lines[pin], gpio_consumer); + break; + case INPUT_PULLUP: + gpiod_line_request_input_flags(gpio_lines[pin], gpio_consumer, GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP); + break; + case OUTPUT: + gpiod_line_request_output(gpio_lines[pin], gpio_consumer, LOW); + break; + default: + DEBUG_PRINTLN("invalid pin direction"); + break; + } + + return; +} + +/** Read digital value */ +byte digitalRead(int pin) { + if( !gpio_lines[pin] ) { + DEBUG_PRINT("tried to read uninitialized pin "); + DEBUG_PRINTLN(pin); + return 0; + } + int val = gpiod_line_get_value(gpio_lines[pin]); + if( val < 0 ) { + DEBUG_PRINT("failed to read value on pin "); + DEBUG_PRINTLN(pin); + return 0; + } + return val; +} + +/** Write digital value */ +void digitalWrite(int pin, byte value) { + if( !gpio_lines[pin] ) { + DEBUG_PRINT("tried to write uninitialized pin "); + DEBUG_PRINTLN(pin); + return; + } + + int res; + res = gpiod_line_set_value(gpio_lines[pin], value); + if( res ) { + DEBUG_PRINT("failed to write value on pin "); + DEBUG_PRINTLN(pin); + } +} + +void attachInterrupt(int pin, const char* mode, void (*isr)(void)) {} +void gpio_write(int fd, byte value) {} +int gpio_fd_open(int pin, int mode) {return 0;} +void gpio_fd_close(int fd) {} + +#endif + #else void pinMode(int pin, byte mode) {} diff --git a/opensprinkler_server.cpp b/opensprinkler_server.cpp index b61c2ea0..8d825373 100644 --- a/opensprinkler_server.cpp +++ b/opensprinkler_server.cpp @@ -2091,20 +2091,24 @@ void on_ap_upload() { on_sta_upload(); } void start_server_client() { if(!otf) return; - - otf->on("/", server_home); // handle home page - otf->on("/index.html", server_home); - otf->on("/update", on_sta_update, OTF::HTTP_GET); // handle firmware update - update_server->on("/update", HTTP_POST, on_sta_upload_fin, on_sta_upload); - - // set up all other handlers - char uri[4]; - uri[0]='/'; - uri[3]=0; - for(byte i=0;ion(uri, urls[i]); + static bool callback_initialized = false; + + if(!callback_initialized) { + otf->on("/", server_home); // handle home page + otf->on("/index.html", server_home); + otf->on("/update", on_sta_update, OTF::HTTP_GET); // handle firmware update + update_server->on("/update", HTTP_POST, on_sta_upload_fin, on_sta_upload); + + // set up all other handlers + char uri[4]; + uri[0]='/'; + uri[3]=0; + for(byte i=0;ion(uri, urls[i]); + } + callback_initialized = true; } update_server->begin(); }