From 38109b55e3afabbb9f9cf7f9eb1cabd8acbded4e Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Wed, 27 Jul 2022 01:02:08 -0400 Subject: [PATCH] Start on the abstract packet radio API --- flake.nix | 30 +++++++----- packet-radio/radio.c | 113 +++++++++++++++++++++++++++++++++++++++++++ packet-radio/radio.h | 63 ++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 13 deletions(-) create mode 100644 packet-radio/radio.c create mode 100644 packet-radio/radio.h diff --git a/flake.nix b/flake.nix index ebb44c3..3c6f32a 100644 --- a/flake.nix +++ b/flake.nix @@ -85,22 +85,10 @@ paths = [ (packages."x86_64-linux"."prime-tx" { gcc = "${avr.gcc}/bin/avr-gcc"; cflags = mcu_cflags atmega32u4; }) (packages."x86_64-linux"."radio-rx" { gcc = "${avr.gcc}/bin/avr-gcc"; cflags = mcu_cflags atmega32u4; }) + (packages."x86_64-linux"."packet-radio" { gcc = "${avr.gcc}/bin/avr-gcc"; cflags = mcu_cflags atmega32u4; }) ]; }; - /* packages."x86_64-linux"."dio-attiny85" = (packages."x86_64-linux"."dio" attiny85); */ - - /* - packages."x86_64-linux"."dio" = - let - pkgs = import nixpkgs { system = "x86_64-linux"; }; - in mkLibrary { - mkDerivation = pkgs.stdenv.mkDerivation; - gcc = - cflags = - name = - */ - packages."x86_64-linux"."dio" = { gcc, cflags }: let @@ -214,6 +202,22 @@ ]; }; + packages."x86_64-linux"."packet-radio" = + { gcc, cflags }: + let + pkgs = import nixpkgs { system = "x86_64-linux"; }; + in mkLibrary { + pkgs = pkgs; + gcc = gcc; + cflags = cflags; + pname = "display"; + psrc = ./display; + pbuildInputs = [ + (packages."x86_64-linux"."dio" { inherit gcc cflags; }) + (packages."x86_64-linux"."shift-register" { inherit gcc cflags; }) + ]; + }; + packages."x86_64-linux"."prime-tx" = { gcc, cflags }: let diff --git a/packet-radio/radio.c b/packet-radio/radio.c new file mode 100644 index 0000000..5f7561c --- /dev/null +++ b/packet-radio/radio.c @@ -0,0 +1,113 @@ + +#include "radio.h" +#include +#include + +typedef enum { + data, + ack, + retry, +} packet_type_e; + +typedef struct { + bool packet_sent; + bool packet_ready; +} flags_t; + +typedef struct { + packet_type_e type; + uint16_t count; + uint8_t sender; + uint8_t receiver; + size_t size; + char message[60]; +} packet_t; + +struct conn_s { + uint16_t packet_counter; + uint8_t address; + + packet_t outgoing_buffer[5]; + size_t outgoing_bottom; + size_t outgoing_top; + + packet_t incoming_buffer[5]; + size_t incoming_bottom; + size_t incoming_top; + + void (*set_mode)(void *, radio_mode_e, radio_status_e *); + flags_t (*get_flags)(void *, radio_status_e *); + void (*transmit)(void *, packet_t *, radio_status_e *); + void (*receive)(void *, uint8_t data[66], radio_status_e *); + + void *radio; +}; + + +void conn_set_address(conn_t *self, uint8_t addr, radio_status_e *status) { + if (!IS_OK(status)) return; + self->address = addr; +} + +void conn_set_mode(conn_t *self, radio_mode_e mode, radio_status_e *status) { + if (!IS_OK(status)) return; + self->set_mode(self->radio, mode, status); +} + +void conn_send(conn_t *self, uint8_t dest, msg_t *message, radio_status_e *status) { + if (!IS_OK(status)) return; + + if (message->length > MAX_MESSAGE_LENGTH) { + *status = message_too_long; + return; + } + + if (self->outgoing_top == self->outgoing_bottom) { + *status = outgoing_full; + return; + } + + self->outgoing_buffer[self->outgoing_top].type = data; + self->outgoing_buffer[self->outgoing_top].count = self->packet_counter; + self->outgoing_buffer[self->outgoing_top].sender = self->address; + self->outgoing_buffer[self->outgoing_top].receiver = dest; + self->outgoing_buffer[self->outgoing_top].size = message->length; + memcpy(self->outgoing_buffer[self->outgoing_top].message, message->data, message->length); + + self->transmit(self->radio, &self->outgoing_buffer[self->outgoing_top], status); + if (IS_OK(status)) self->outgoing_top++; + + return; +} + +received_msg_t * conn_receive(conn_t *self, radio_status_e *status) { + if (!IS_OK(status)) return NULL; + + if (self->incoming_bottom == self->incoming_top) { + return NULL; + } + + size_t length = self->incoming_buffer[self->incoming_bottom].size; + received_msg_t *msg = malloc(sizeof(received_msg_t) + length); + msg->sender = self->incoming_buffer[self->incoming_bottom].sender; + msg->message.length = self->incoming_buffer[self->incoming_bottom].size; + memcpy(msg->message.data, self->incoming_buffer[self->incoming_bottom].message, msg->message.length); + + self->incoming_bottom++; + + return msg; +} + +void conn_handle_interrupt(conn_t *self) { + radio_status_e *status = ok; + + flags_t flags = self->get_flags(self->radio, status); + if (!IS_OK(status)) return; + + if (flags.packet_ready) { + uint8_t data[66]; + self->receive(self->radio, data, status); + if (!IS_OK(status)) return; + } +} + diff --git a/packet-radio/radio.h b/packet-radio/radio.h new file mode 100644 index 0000000..c1f0731 --- /dev/null +++ b/packet-radio/radio.h @@ -0,0 +1,63 @@ +/* +Copyright 2022, Savanni D'Gerinel + +This file is part of Savanni's AVR library. + +This AVR library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This AVR library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this AVR library. If not, see . +*/ + +#ifndef __RADIO_H__ +#define __RADIO_H__ + +#include + +#ifdef __AVR__ + +#else +#include +#include +#endif + +#define MAX_MESSAGE_LENGTH 60 +#define IS_OK(val) (val == NULL || !*val) + +typedef struct { + size_t length; + char data[0]; +} msg_t; + +typedef struct { + uint16_t sender; + msg_t message; +} received_msg_t; + +typedef enum { + ok, + not_found, + message_too_long, + outgoing_full, +} radio_status_e; + +typedef struct conn_s conn_t; + +typedef enum { + sleep, + standby, + tx, + rx, + listen +} radio_mode_e; + +void conn_set_address(conn_t *, uint8_t, radio_status_e *); +void conn_set_mode(conn_t *, radio_mode_e, radio_status_e *); + +void conn_send(conn_t *, uint8_t, msg_t *, radio_status_e *); +received_msg_t * conn_receive(conn_t *, radio_status_e *); + +// void radio_broadcast(conn_t *, uint16_t, msg_t *, radio_status_e *); + +#endif