avr/packet-radio/radio.c

114 lines
3.0 KiB
C

#include "radio.h"
#include <string.h>
#include <stdlib.h>
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;
}
}