Skip to content
Open
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
9 changes: 4 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
cmake_minimum_required(VERSION 3.16)

project(rnode)

set(CMAKE_C_FLAGS_RELEASE "-O3")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

set(CMAKE_C_FLAGS_DEBUG "-O3")
set(CMAKE_CXX_FLAGS_DEBUG "-O3")

project(rnode)

add_executable(${PROJECT_NAME})

target_link_libraries(${PROJECT_NAME} PRIVATE gpiod m cyaml)

add_subdirectory(src)
add_subdirectory(sx126x)

include_directories(src)
include_directories(sx126x)

target_link_libraries(${PROJECT_NAME} PRIVATE m cyaml)

install(FILES rnode.yaml DESTINATION /mnt/rns)
install(TARGETS ${PROJECT_NAME} DESTINATION sbin)
4 changes: 2 additions & 2 deletions rnode.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Board RNS-Gate

spi: /dev/spidev1.0
cs: { port: 0, pin: 13 }
rst: { port: 0, pin: 6 }
cs: { port: 0, pin: 13 }
rst: { port: 0, pin: 6 }
busy: { port: 0, pin: 11 }
dio1: { port: 0, pin: 12 }
rx_en: { port: 0, pin: 2 }
Expand Down
12 changes: 12 additions & 0 deletions sx126x/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
find_package(PkgConfig REQUIRED)
pkg_check_modules(GPIOD libgpiod>=2.0)

if(GPIOD_FOUND)
target_sources(${PROJECT_NAME} PRIVATE gpio_hal_v2.c)
else()
pkg_check_modules(GPIOD REQUIRED libgpiod)
target_sources(${PROJECT_NAME} PRIVATE gpio_hal_v1.c)
endif()

target_link_libraries(${PROJECT_NAME} PRIVATE ${GPIOD_LIBRARIES})

target_sources(${PROJECT_NAME} PUBLIC
sx126x.c
)
42 changes: 42 additions & 0 deletions sx126x/gpio_hal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* GPIO HAL
*/

#pragma once

typedef struct gpio_line gpio_line_t;

typedef enum {
GPIO_DIR_OUTPUT,
GPIO_DIR_INPUT,
GPIO_DIR_INPUT_EDGE_RISING
} gpio_dir_t;

typedef enum {
GPIO_VALUE_INACTIVE = 0,
GPIO_VALUE_ACTIVE = 1
} gpio_value_t;

/* Allocate and configure a GPIO line. Returns NULL on failure. */
gpio_line_t *gpio_request(unsigned int chip,
unsigned int pin,
gpio_dir_t dir,
gpio_value_t initial,
const char *consumer);

/* Release a line obtained with gpio_request(). */
void gpio_release(gpio_line_t *line);

/* Read the current level of an input line. */
gpio_value_t gpio_get(gpio_line_t *line);

/* Drive an output line to the given level. */
void gpio_set(gpio_line_t *line, gpio_value_t val);

/*
* Block until one edge event is available on an edge-detection line.
* Returns: 1 - event received; 0 - no event (timeout); <0 - error
*/
int gpio_read_edge_rising(gpio_line_t *line);
97 changes: 97 additions & 0 deletions sx126x/gpio_hal_v1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* GPIO HAL (libgpiod v1 backend)
*/

#include <stdlib.h>
#include <errno.h>
#include <gpiod.h>

#include "gpio_hal.h"

struct gpio_line {
struct gpiod_line *line;
};

gpio_line_t *gpio_request(unsigned int chip,
unsigned int pin,
gpio_dir_t dir,
gpio_value_t initial,
const char *consumer)
{
struct gpiod_chip *chip_h = gpiod_chip_open_by_number(chip);
if (!chip) return NULL;

struct gpiod_line *line = gpiod_chip_get_line(chip_h, pin);
if (!line) {
gpiod_chip_close(chip_h);
return NULL;
}

int result;

switch (dir) {
case GPIO_DIR_OUTPUT:
result = gpiod_line_request_output(line, consumer,
initial == GPIO_VALUE_ACTIVE ? 1 : 0);
break;
case GPIO_DIR_INPUT:
result = gpiod_line_request_input(line, consumer);
break;
case GPIO_DIR_INPUT_EDGE_RISING: {
struct gpiod_line_request_config cfg = {
.consumer = consumer,
.request_type = GPIOD_LINE_REQUEST_EVENT_RISING_EDGE,
.flags = 0,
};
result = gpiod_line_request(line, &cfg, 0);
break;
}
default:
result = -1;
break;
}

gpiod_chip_close(chip_h);

if (result < 0) return NULL;

gpio_line_t *gpio = malloc(sizeof(*gpio));
if (!gpio) {
gpiod_line_release(line);
return NULL;
}

gpio->line = line;
return gpio;
}

void gpio_release(gpio_line_t *line) {
if (!line) return;
gpiod_line_release(line->line);
free(line);
}

gpio_value_t gpio_get(gpio_line_t *line) {
return gpiod_line_get_value(line->line) == 1
? GPIO_VALUE_ACTIVE
: GPIO_VALUE_INACTIVE;
}

void gpio_set(gpio_line_t *line, gpio_value_t val) {
gpiod_line_set_value(line->line, val == GPIO_VALUE_ACTIVE ? 1 : 0);
}

int gpio_read_edge_rising(gpio_line_t *line) {
struct timespec timeout = { .tv_sec = 60, .tv_nsec = 0 };
int res = gpiod_line_event_wait(line->line, &timeout);

if (res < 0) return -1;
if (res == 0) return 0; // timeout, no event

struct gpiod_line_event event;
if (gpiod_line_event_read(line->line, &event) < 0) return -1;

return (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE) ? 1 : 0;
}
133 changes: 133 additions & 0 deletions sx126x/gpio_hal_v2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* GPIO HAL (libgpiod v2 backend)
*/

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <gpiod.h>

#include "gpio_hal.h"

struct gpio_line {
struct gpiod_line_request *req;
unsigned int pin;
struct gpiod_edge_event_buffer *event_buf;
};

gpio_line_t *gpio_request(unsigned int chip,
unsigned int pin,
gpio_dir_t dir,
gpio_value_t initial,
const char *consumer)
{
char chip_path[32];
snprintf(chip_path, sizeof(chip_path), "/dev/gpiochip%u", chip);

struct gpiod_chip *chip_h = gpiod_chip_open(chip_path);
if (!chip_h) return NULL;

struct gpiod_line_settings *settings = gpiod_line_settings_new();
if (!settings) {
gpiod_chip_close(chip_h);
return NULL;
}

struct gpiod_line_config *line_cfg = gpiod_line_config_new();
if (!line_cfg) {
gpiod_line_settings_free(settings);
gpiod_chip_close(chip_h);
return NULL;
}

struct gpiod_request_config *req_cfg = gpiod_request_config_new();
if (!req_cfg) {
gpiod_line_config_free(line_cfg);
gpiod_line_settings_free(settings);
gpiod_chip_close(chip_h);
return NULL;
}

switch (dir) {
case GPIO_DIR_OUTPUT:
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_settings_set_output_value(settings,
initial == GPIO_VALUE_ACTIVE
? GPIOD_LINE_VALUE_ACTIVE
: GPIOD_LINE_VALUE_INACTIVE);
break;
case GPIO_DIR_INPUT:
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
break;
case GPIO_DIR_INPUT_EDGE_RISING:
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_RISING);
break;
}

unsigned int offsets[] = { pin };
gpiod_line_config_add_line_settings(line_cfg, offsets, 1, settings);
gpiod_request_config_set_consumer(req_cfg, consumer);

gpio_line_t *gpio = malloc(sizeof(*gpio));
if (gpio) {
gpio->req = gpiod_chip_request_lines(chip_h, req_cfg, line_cfg);
gpio->pin = pin;
gpio->event_buf = NULL;

if (!gpio->req) {
free(gpio);
gpio = NULL;
} else if (dir == GPIO_DIR_INPUT_EDGE_RISING) {
gpio->event_buf = gpiod_edge_event_buffer_new(1);
if (!gpio->event_buf) {
gpiod_line_request_release(gpio->req);
free(gpio);
gpio = NULL;
}
}
}

gpiod_line_settings_free(settings);
gpiod_line_config_free(line_cfg);
gpiod_request_config_free(req_cfg);
gpiod_chip_close(chip_h);

return gpio;
}

void gpio_release(gpio_line_t *line) {
if (!line) return;

if (line->event_buf) {
gpiod_edge_event_buffer_free(line->event_buf);
}
gpiod_line_request_release(line->req);
free(line);
}

gpio_value_t gpio_get(gpio_line_t *line) {
return gpiod_line_request_get_value(line->req, line->pin)
== GPIOD_LINE_VALUE_ACTIVE
? GPIO_VALUE_ACTIVE
: GPIO_VALUE_INACTIVE;
}

void gpio_set(gpio_line_t *line, gpio_value_t val) {
gpiod_line_request_set_value(line->req, line->pin,
val == GPIO_VALUE_ACTIVE
? GPIOD_LINE_VALUE_ACTIVE
: GPIOD_LINE_VALUE_INACTIVE);
}

int gpio_read_edge_rising(gpio_line_t *line) {
int res = gpiod_line_request_read_edge_events(line->req, line->event_buf, 1);

if (res < 0) return -1;
if (res == 0) return 0;

struct gpiod_edge_event *event = gpiod_edge_event_buffer_get_event(line->event_buf, 0);
return (gpiod_edge_event_get_event_type(event) == GPIOD_EDGE_EVENT_RISING_EDGE) ? 1 : 0;
}
Loading