update link layer manager + rip + rmt

This commit is contained in:
Justin Chow
2025-07-10 00:48:37 -04:00
committed by Johnathon Slightham
parent 3691ca4697
commit 732f141e45
9 changed files with 342 additions and 271 deletions

View File

@@ -39,7 +39,7 @@ static const uint16_t crc16_table[256] = {
class DataLinkManager{
public:
DataLinkManager(uint8_t board_id);
DataLinkManager(uint8_t board_id, uint8_t num_channels);
~DataLinkManager();
esp_err_t send(uint8_t dest_board, uint8_t* data, uint16_t data_len, FrameType type, uint8_t curr_channel);
esp_err_t start_receive_frames(uint8_t curr_channel);
@@ -48,7 +48,8 @@ class DataLinkManager{
esp_err_t send_discover_frame();
private:
uint8_t this_board_id = 0;
std::priority_queue<Frame, std::vector<Frame>, FrameCompare> frame_queue; //create a priority queue
uint8_t num_channels = MAX_CHANNELS;
//std::priority_queue<Frame, std::vector<Frame>, FrameCompare> frame_queue; //create a priority queue - not in use
std::unique_ptr<RMTManager> phys_comms;
std::unordered_map<uint8_t, uint16_t> sequence_num_map;
@@ -56,7 +57,7 @@ class DataLinkManager{
esp_err_t get_board_id(uint8_t& board_id);
void print_binary(uint8_t byte);
void print_buffer_binary(const uint8_t* buffer, size_t length);
esp_err_t get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size);
esp_err_t get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, frame_header* header);
esp_err_t geneate_crc_16(uint8_t* data, size_t data_len, uint16_t* crc);
//==== RIP related functions ====
@@ -69,7 +70,7 @@ class DataLinkManager{
*/
void init_rip();
esp_err_t rip_find_entry(uint8_t board_id, RIPRow** entry);
esp_err_t rip_find_entry(uint8_t board_id, RIPRow** entry, bool reserve_row);
esp_err_t rip_update_entry(uint8_t new_hop, uint8_t channel, RIPRow** entry);
esp_err_t rip_add_entry(uint8_t board_id, uint8_t hops, uint8_t channel, RIPRow** entry);
esp_err_t rip_reset_entry_ttl(uint8_t board_id);
@@ -77,13 +78,12 @@ class DataLinkManager{
//this is stored locally with metadata `ttl`
// std::unordered_map<uint8_t, RIPRow> rip_table; //using a hash map to store the routes to other boards - will be used as we scale up
RIPRow rip_table[RIP_MAX_ROUTES]; //temp using a static array
uint8_t rip_table_valid_rows = 0;
void start_rip_tasks();
esp_err_t broadcast_rip_frame();
esp_err_t broadcast_rip_frame(bool manual_broadcast);
[[noreturn]] static void rip_broadcast_timer_function(void* args);
[[noreturn]] static void rip_ttl_decrement_task(void* args);
QueueHandle_t manual_broadcasts;
esp_err_t route_frame(uint8_t dest_id, uint8_t* channel_to_send);
};

View File

@@ -9,8 +9,8 @@
#define START_OF_FRAME 0xAB //0b1010_1011 - denotes the start of frame
#define MAX_GENERIC_DATA_LEN (180) //Max 180B
#define MAX_CONTROL_DATA_LEN (1 << 5) // Max 32B
#define MAX_GENERIC_DATA_LEN (1 << 16) //Max 65.5KiB
#define MAX_CONTROL_DATA_LEN (1 << 8) // Max 256B
//Flags
#define FLAG_FRAG 0x8 //0b1000 //this fragmented frame is part of a larger frame
@@ -24,6 +24,7 @@
#define IS_CONTROL_FRAME(x) (((x) & 0x80) != 0)
#define CONTROL_FRAME_OVERHEAD 9
#define GENERIC_FRAME_OVERHEAD 12
#define CONTROL_FRAME_TYPE 0x80 //if the frame type MSB is set to 1, use the control frame
//Types (total 2^4 = 16 different types)
@@ -45,10 +46,10 @@ typedef struct _control_frame{
uint8_t receiver_id; //receiver board id
uint16_t seq_num; //sequence number to differentiate frames being sent from sender to receiver
uint8_t type_flag; //(type << 4) | flag - both are 4 bits
uint8_t data_len; //Data Length (max 32B)
uint16_t data_len; //Data Length (max 256B)
uint8_t data[MAX_CONTROL_DATA_LEN]; //Variable Length of Data
uint16_t crc_16; //CRC-16
} control_frame; //this will have a max size of 9 + 32B = 41B
} control_frame; //this will have a max size of 9 + 256B = 265B
typedef struct _data_link_frame{
uint8_t preamble; //Start of Frame
@@ -60,39 +61,17 @@ typedef struct _data_link_frame{
uint16_t data_len; //Data Length (max 178B)
uint8_t data[MAX_GENERIC_DATA_LEN]; //Variable Length of Data
uint16_t crc_16; //CRC-16
} data_link_frame; //this will have a max size of 12 + 180 B = 192B
} data_link_frame; //this will have a max size of ~65.5KiB
#pragma pack(pop)
using Frame = std::variant<control_frame, data_link_frame>;
//defining a comparison operation for comparing two frames -- not tested
struct FrameCompare {
bool operator()(const Frame& a, const Frame& b) const {
auto msb_set = [](uint8_t type_flag) {
return (type_flag & 0x80) != 0; // 0x80 == 1000 0000
};
auto get_type_flag = [](const Frame& pkt) -> uint8_t {
return std::visit([](auto&& p) -> uint8_t {
return p.type_flag;
}, pkt);
};
uint8_t type_flag_a = get_type_flag(a);
uint8_t type_flag_b = get_type_flag(b);
bool a_msb = msb_set(type_flag_a);
bool b_msb = msb_set(type_flag_b);
if (a_msb != b_msb) {
return !a_msb; // Frame with MSB set (true) should come first
}
// Tie-breaker: use seq_num if MSB is the same
return std::visit([](auto&& p1, auto&& p2) {
return p1.seq_num > p2.seq_num; // smaller seq_num = higher priority (older)
}, a, b);
}
};
typedef struct _header{
uint8_t preamble; //Start of Frame
uint8_t sender_id; //sender board id
uint8_t receiver_id; //receiver board id
uint16_t seq_num; //sequence number to differentiate frames being sent from sender to receiver
uint8_t type_flag; //(type << 4) | flag - both are 4 bits
uint16_t frag_info; //(total_frag_num << 8) | frag_num - total_frag_num denotes the total number of fragmented frames to expect for this sequence number(?) and frag_num denotes the fragment frame num
uint16_t data_len; //Data Length (max 178B)
uint16_t crc_16; //CRC-16
} frame_header;
#endif //DATA_LINK

View File

@@ -5,11 +5,14 @@
#define RIP_MAX_HOPS 15 //16 or more is infinite
#define RIP_MAX_ROUTES 10 //for the demo we will use up to 10 boards in total (9 other boards will be connected = 9 rows)
#define RIP_INVALID_ROW 0
// #define RIP_BROADCAST_INTERVAL 30000 //broadcast every 30 seconds (30000ms)
#define RIP_BROADCAST_INTERVAL 3000 //temp broadcast every 3 seconds (3000ms)
#define RIP_VALID_ROW 1
#define RIP_NEW_ROW 2
#define RIP_BROADCAST_INTERVAL 30000 //broadcast every 30 seconds (30000ms)
// #define RIP_BROADCAST_INTERVAL 3000 //temp broadcast every 3 seconds (3000ms)
#define RIP_TTL_START 180 //seconds
#define RIP_MS_TO_SEC 1000 //1000 ms to 1 sec
#define RIP_MAX_SEM_WAIT 30
#define RIP_FLUSH_COUNT 8 //flush after 8*30 seconds = 240 seconds
/**
* @brief Routing data to a board
@@ -25,6 +28,7 @@ typedef struct _rip_row{
uint8_t channel; //rmt channel
uint8_t ttl; //how long this entry is valid for. starting value is 180 seconds
uint8_t valid; //is this a valid entry?
uint8_t ttl_flush; //if hops is invalid, this would count the amount of time until this entry would be invalid (in multiples of 30 seconds)
StaticSemaphore_t mutex_buf; //where mutex state is stored
SemaphoreHandle_t row_sem; //mutex sem handle of mutex_buf
} RIPRow;