114 lines
3.0 KiB
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;
|
|
}
|
|
}
|
|
|