Add support for ACK response for Generic Frame Fragments

This commit is contained in:
Justin Chow
2026-01-06 14:33:01 -05:00
committed by Johnathon Slightham
parent 53d3c775ba
commit 7984b8a89f
21 changed files with 2002 additions and 452 deletions

View File

@@ -4,43 +4,34 @@ file(GLOB_RECURSE ALL_SRCS
"${CMAKE_CURRENT_SOURCE_DIR}/*.S"
)
if(DEFINED RMT_TEST AND RMT_TEST EQUAL 1)
message(STATUS "Building for testing RMT/Link Layer Functionality with main_rmt_test.cpp")
list(REMOVE_ITEM ALL_SRCS
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
)
idf_build_set_property(COMPILE_DEFINITIONS RMT_TEST APPEND)
else()
list(REMOVE_ITEM ALL_SRCS
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
)
endif()
idf_component_register(SRCS ${ALL_SRCS}
PRIV_REQUIRES esp_psram spi_flash nvs_flash esp_event rpc constants config rmt esp_driver_gptimer dataLink flatbuffers esp_driver_ledc
INCLUDE_DIRS "include")
if(DEFINED BOARD_NAME AND BOARD_NAME)
message(STATUS "Building for board name: " ${BOARD_NAME})
idf_build_set_property(COMPILE_DEFINITIONS BOARD_${BOARD_NAME} APPEND)
if(DEFINED SRC_BOARD AND SRC_BOARD)
message(STATUS "Building for source board id: " ${SRC_BOARD})
idf_build_set_property(COMPILE_DEFINITIONS SRC_BOARD=${SRC_BOARD} APPEND)
endif()
if(DEFINED TIME_TEST AND TIME_TEST)
message(STATUS "Building with TIME_TEST: " ${TIME_TEST})
idf_build_set_property(COMPILE_DEFINITIONS TIME_TEST APPEND)
if(DEFINED RECEIVER_BOARD AND RECEIVER_BOARD)
message(STATUS "Building for receiver board id: " ${RECEIVER_BOARD})
idf_build_set_property(COMPILE_DEFINITIONS RECEIVER_BOARD=${RECEIVER_BOARD} APPEND)
endif()
if(DEFINED MANCHESTER_40 AND MANCHESTER_40)
message(STATUS "Building with MANCHESTER_40: " ${MANCHESTER_40})
idf_build_set_property(COMPILE_DEFINITIONS MANCHESTER_40 APPEND)
if(DEFINED RECEIVE_ONLY AND RECEIVE_ONLY)
message(STATUS "Building for receive only")
idf_build_set_property(COMPILE_DEFINITIONS RECEIVE_ONLY=${RECEIVE_ONLY} APPEND)
endif()
if(DEFINED NRZ_INVERTED AND NRZ_INVERTED)
message(STATUS "Building with NRZ_INVERTED: " ${NRZ_INVERTED})
idf_build_set_property(COMPILE_DEFINITIONS NRZ_INVERTED APPEND)
endif()
if(DEFINED NRZ_INVERTED_10 AND NRZ_INVERTED_10)
message(STATUS "Building with NRZ_INVERTED_10: " ${NRZ_INVERTED_10})
idf_build_set_property(COMPILE_DEFINITIONS NRZ_INVERTED_10 APPEND)
endif()
if(DEFINED NRZ_INVERTED_20 AND NRZ_INVERTED_20)
message(STATUS "Building with NRZ_INVERTED_20: " ${NRZ_INVERTED_20})
idf_build_set_property(COMPILE_DEFINITIONS NRZ_INVERTED_20 APPEND)
endif()
if(DEFINED NRZ_INVERTED_2 AND NRZ_INVERTED_2)
message(STATUS "Building with NRZ_INVERTED_2: " ${NRZ_INVERTED_2})
idf_build_set_property(COMPILE_DEFINITIONS NRZ_INVERTED_2 APPEND)
endif()
if(DEFINED NRZ_INVERTED_40_HZ AND NRZ_INVERTED_40_HZ)
message(STATUS "Building with NRZ_INVERTED_40_HZ: " ${NRZ_INVERTED_40_HZ})
idf_build_set_property(COMPILE_DEFINITIONS NRZ_INVERTED_40_HZ APPEND)
endif()
if(DEFINED VERIFY_RECEIVE AND VERIFY_RECEIVE)
message(STATUS "Building with VERIFY_RECEIVE: " ${VERIFY_RECEIVE})
idf_build_set_property(COMPILE_DEFINITIONS VERIFY_RECEIVE APPEND)
endif()

View File

@@ -1,3 +1,58 @@
# Main
Use `main.cpp` to start the control loop.
# Data Link Sample Code
See `main_rmt_test.cpp` for more details for Data Link Layer usage.
See `main_rmt_test.cpp` for more details for Data Link Layer usage.
To run the sample code, add the compiler variable `RMT_TEST=1` when compiling: `idf.py build -D RMT_TEST=1`. To run the main program, simply set `RMT_TEST` to 0 or perform a `fullclean` and rebuild without the compiler variable.
## Testing with Multiple Boards
With `main_rmt_test.cpp`, flash one or more boards, ensuring that `BOARD_ID` are unique and `RECEIVER_BOARD_ID` is a board that exists and is connected on the same network.
### Example Usage:
Board A: `idf.py -B ./build_A build -D SRC_BOARD=1 -D RECEIVER_BOARD=69 -D RMT_TEST=1 flash monitor -p COM3`
Board B: `idf.py -B ./build_B build -D SRC_BOARD=69 -D RECEIVER_BOARD=1 -D RMT_TEST=1 flash monitor -p COM4`
### Receive Only
A board can be set to only receive frames by setting the compiler flag `RECEIVE_ONLY=1` (and conversely unset by setting to `0`).
## VSCode Intellisense Parsing
With the preprocessor if blocks, intellisense may gray out certain code blocks. To change this behaviour, modify your C/C++ configuration under `Defines` or modify your `.vscode/c_cpp_properties.json` file itself to make certain code blocks visible.
## Expected Behaviour
When monitoring both boards, you should see `Received message '%.*s' on channel %d from board %d seq num %d` when a board received a message (usually after the message `Sent %zu B sized in %" PRIu64 " us from channel %d` on the other board). When RIP frames are broadcasted, the other boards should receive that RIP frame (usually accompanied with a debug message) and broadcast their own table.
The specific message being sent can vary depending on the setup (determined at compile time). Simply changing the `snprintf` on the `send_buf` and/or `FrameType` argument of `send()` will change the message/frames being sent (from the perspective of the user).
# cat
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⡷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠋⠈⠻⣮⣳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⡿⠋⠀⠀⠀⠀⠙⣿⣿⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⡿⠟⠛⠉⠀⠀⠀⠀⠀⠀⠀⠈⠛⠛⠿⠿⣿⣷⣶⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣾⡿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠻⠿⣿⣶⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣀⣠⣤⣤⣀⡀⠀⠀⣀⣴⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣷⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣄⠀⠀
⢀⣤⣾⡿⠟⠛⠛⢿⣿⣶⣾⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣷⣦⣀⣀⣤⣶⣿⡿⠿⢿⣿⡀⠀
⣿⣿⠏⠀⢰⡆⠀⠀⠉⢿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⢿⡿⠟⠋⠁⠀⠀⢸⣿⠇⠀
⣿⡟⠀⣀⠈⣀⡀⠒⠃⠀⠙⣿⡆⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠇⠀
⣿⡇⠀⠛⢠⡋⢙⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀
⣿⣧⠀⠀⠀⠓⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠋⠀⠀⢸⣧⣤⣤⣶⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⡿⠀⠀
⣿⣿⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠻⣷⣶⣶⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⠁⠀⠀
⠈⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⡏⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⡄⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠛⠻⠿⢿⣿⣷⣶⣦⣤⣄⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠛⠛⠿⠿⣿⣷⣶⣶⣤⣤⣀⡀⠀⠀⠀⢀⣴⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⡿⣄
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠛⠛⠿⠿⣿⣷⣶⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣹
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⠀⢸⣧
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣆⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⣶⣾⣿⣿⣿⣿⣤⣄⣀⡀⠀⠀⠀⣿
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢿⣻⣷⣶⣾⣿⣿⡿⢯⣛⣛⡋⠁⠀⠀⠉⠙⠛⠛⠿⣿⣿⡷⣶⣿
good kitty

View File

@@ -1,3 +1,4 @@
#if !defined(RMT_TEST) || (defined(RMT_TEST) && RMT_TEST == 0)
// #include <cstdio>
// #include <memory>
@@ -19,3 +20,4 @@ extern "C" [[noreturn]] void app_main(void) {
"metadata_tx", 3096, loop_manager.get(), 3, nullptr);
loop_manager->control_loop();
}
#endif

View File

@@ -1,292 +1,313 @@
// //Used for link layer testing (change name to main.cpp to use)
// #include <cstdio>
// #include <memory>
#if defined(RMT_TEST) && RMT_TEST == 1
//Used for link layer testing (change name to main.cpp to use)
#include <cstdio>
#include <memory>
// #include "sdkconfig.h"
// #include "freertos/FreeRTOS.h"
// #include "freertos/task.h"
// #include "esp_flash.h"
// #include "nvs_flash.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_flash.h"
#include "nvs_flash.h"
// #include "RMTManager.h"
// #include "DataLinkManager.h"
#include "RMTManager.h"
#include "DataLinkManager.h"
// #include <esp_netif.h>
// #include <esp_event.h>
// #include <freertos/semphr.h>
// #include "driver/gptimer.h"
// #include "esp_log.h"
#include <esp_netif.h>
#include <esp_event.h>
#include <freertos/semphr.h>
#include "driver/gptimer.h"
#include "esp_log.h"
// #define DATA_SIZE_TEST 270
// //current board id
// #define BOARD_ID 69
// //board id to send to
// #define RECEIVER_BOARD_ID 1
#define DATA_SIZE_TEST 600
// struct TaskArgs{
// DataLinkManager* link_layer_obj;
// uint8_t task_id;
// uint8_t receiver_id;
// QueueHandle_t receive_queue;
// };
//current board id
#ifdef SRC_BOARD
#define BOARD_ID SRC_BOARD
#else
#define BOARD_ID 1
#endif
// struct ReceviedFrame{
// uint8_t buf[MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD]; //max 41B
// size_t len;
// FrameHeader header;
// };
//board id to send to
#ifdef RECEIVER_BOARD
#define RECEIVER_BOARD_ID RECEIVER_BOARD
#else
#define RECEIVER_BOARD_ID 69
#endif
// void receive_frames(void* arg){
// TaskArgs* args = (TaskArgs*)arg;
struct TaskArgs{
DataLinkManager* link_layer_obj;
uint8_t task_id;
uint8_t receiver_id;
QueueHandle_t receive_queue;
};
struct ReceviedFrame{
uint8_t buf[DATA_SIZE_TEST + GENERIC_FRAME_OVERHEAD];
size_t len;
FrameHeader header;
};
void receive_frames(void* arg){
TaskArgs* args = (TaskArgs*)arg;
// DataLinkManager* obj = args->link_layer_obj;
DataLinkManager* obj = args->link_layer_obj;
// if (obj == nullptr){
// ESP_LOGE("thread", "bad pointer\n");
// vTaskDelete(NULL); //should never get here
// }
if (obj == nullptr){
ESP_LOGE("thread", "bad pointer\n");
vTaskDelete(NULL); //should never get here
}
// QueueHandle_t shared_queue = (QueueHandle_t)args->receive_queue;
QueueHandle_t shared_queue = (QueueHandle_t)args->receive_queue;
// uint8_t curr_channel = args-> task_id;
uint8_t curr_channel = args-> task_id;
// printf("RX JOB for task %d starting...\n", curr_channel);
// esp_err_t res;
printf("RX JOB for task %d starting...\n", curr_channel);
esp_err_t res;
// uint8_t recv_buf[DATA_SIZE_TEST];
// memset(recv_buf, 0, DATA_SIZE_TEST);
uint8_t recv_buf[DATA_SIZE_TEST];
memset(recv_buf, 0, DATA_SIZE_TEST);
// ReceviedFrame recv_frame = {};
ReceviedFrame recv_frame = {};
// FrameHeader header = {};
FrameHeader header = {};
// while(true){
// res = obj->async_receive(recv_buf, sizeof(recv_buf), &header, curr_channel);
// vTaskDelay(pdMS_TO_TICKS(10));
// if (res != ESP_OK){
// // ESP_LOGE("thread", "Failed to receive message on thread %d", curr_channel);
// if (res != ESP_ERR_NOT_FOUND) {
// recv_frame.len = 0;
// if (xQueueSendToBack(shared_queue, (void*)&recv_frame, (TickType_t) 10) != pdPASS){
// ESP_LOGE("RX Job", "Failed to push received frame onto shared queue for channel %d", curr_channel);
// }
// }
// continue;
// } else {
// // printf("Successfully receive message\n");
// }
while(true){
res = obj->async_receive(recv_buf, sizeof(recv_buf), &header, curr_channel);
vTaskDelay(pdMS_TO_TICKS(10));
if (res != ESP_OK){
// ESP_LOGE("thread", "Failed to receive message on thread %d", curr_channel);
if (res != ESP_ERR_NOT_FOUND) {
recv_frame.len = 0;
if (xQueueSendToBack(shared_queue, (void*)&recv_frame, (TickType_t) 10) != pdPASS){
ESP_LOGE("RX Job", "Failed to push received frame onto shared queue for channel %d", curr_channel);
}
}
continue;
} else {
// printf("Successfully receive message\n");
}
// if (header.data_len == 0){
// continue;
// }
if (header.data_len == 0){
continue;
}
// recv_frame.len = header.data_len;
// memcpy((void*)recv_frame.buf, (void*)recv_buf, header.data_len);
// recv_frame.header = header;
recv_frame.len = header.data_len;
memcpy((void*)recv_frame.buf, (void*)recv_buf, header.data_len);
recv_frame.header = header;
// if (xQueueSendToBack(shared_queue, (void*)&recv_frame, (TickType_t) 10) != pdPASS){
// ESP_LOGE("RX Job", "Failed to push received frame onto shared queue for channel %d", curr_channel);
// }
if (xQueueSendToBack(shared_queue, (void*)&recv_frame, (TickType_t) 10) != pdPASS){
ESP_LOGE("RX Job", "Failed to push received frame onto shared queue for channel %d", curr_channel);
}
// }
}
// }
}
// void multi_transceiver(void* arg) {
// TaskArgs* args = (TaskArgs*)arg;
void multi_transceiver(void* arg) {
TaskArgs* args = (TaskArgs*)arg;
// DataLinkManager* obj = args->link_layer_obj;
DataLinkManager* obj = args->link_layer_obj;
// if (obj == nullptr){
// ESP_LOGE("thread", "bad pointer\n");
// vTaskDelete(NULL); //should never get here
// }
if (obj == nullptr){
ESP_LOGE("thread", "bad pointer\n");
vTaskDelete(NULL); //should never get here
}
// xTaskCreate(receive_frames, "receive_frame_job", 4096, arg, 5, NULL);
xTaskCreate(receive_frames, "receive_frame_job", 4096, arg, 5, NULL);
// uint8_t dest_board_id = args->receiver_id; //using a dummy number for now - there is no board with id 2 right now
uint8_t dest_board_id = args->receiver_id; //using a dummy number for now - there is no board with id 2 right now
// const char* message = "this is some other data that should not be corrupted.";
const char* message = "this is some other data that should not be corrupted.";
const char* generic_frame_additional_message = "This is some other extra data that can be sent that also shouldn't be corrupted while transmitting.";
const char* generic_frame_second_additional_message = "At this point we have reached 241 bytes. This is some other data that we can send using generic frames but this will be fragmented. however, this data shouldn't be corrupted and be sent as if it was sent all at once. total message size right here is 469 bytes:)";
// uint8_t curr_channel = args->task_id;
// QueueHandle_t shared_queue = (QueueHandle_t)args->receive_queue;
uint8_t curr_channel = args->task_id;
QueueHandle_t shared_queue = (QueueHandle_t)args->receive_queue;
// uint8_t send_buf[DATA_SIZE_TEST];
// uint8_t recv_buf[DATA_SIZE_TEST];
// memset(recv_buf, 0, DATA_SIZE_TEST);
// memset(send_buf, 0, DATA_SIZE_TEST);
uint8_t send_buf[DATA_SIZE_TEST];
uint8_t recv_buf[DATA_SIZE_TEST];
memset(recv_buf, 0, DATA_SIZE_TEST);
memset(send_buf, 0, DATA_SIZE_TEST);
// size_t recv_len = 0;
// uint8_t iteration = 0;
// esp_err_t res = ESP_OK;
size_t recv_len = 0;
uint8_t iteration = 0;
esp_err_t res = ESP_OK;
// gptimer_handle_t gptimer = NULL;
// gptimer_config_t timer_config = {
// .clk_src = GPTIMER_CLK_SRC_DEFAULT,
// .direction = GPTIMER_COUNT_UP,
// .resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us
// };
// ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
// ESP_ERROR_CHECK(gptimer_enable(gptimer));
// ESP_ERROR_CHECK(gptimer_start(gptimer));
// uint64_t start_count = 0, end_count = 0;
gptimer_handle_t gptimer = NULL;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
ESP_ERROR_CHECK(gptimer_enable(gptimer));
ESP_ERROR_CHECK(gptimer_start(gptimer));
uint64_t start_count = 0, end_count = 0;
// uint32_t num_incorrect = 0;
// uint32_t total_transactions = 0;
uint32_t num_incorrect = 0;
uint32_t total_transactions = 0;
// RIPRow_public_matrix matrix[RIP_MAX_ROUTES];
// size_t matrix_size = RIP_MAX_ROUTES;
RIPRow_public_matrix matrix[RIP_MAX_ROUTES];
size_t matrix_size = RIP_MAX_ROUTES;
// for (int i = 0; i < RIP_MAX_ROUTES; i++){
// RIPRow_public* table = (RIPRow_public*)pvPortMalloc(sizeof(RIPRow_public)*RIP_MAX_ROUTES);
// matrix[i] = {
// .table = table,
// .size = RIP_MAX_ROUTES
// };
// }
for (int i = 0; i < RIP_MAX_ROUTES; i++){
RIPRow_public* table = (RIPRow_public*)pvPortMalloc(sizeof(RIPRow_public)*RIP_MAX_ROUTES);
matrix[i] = {
.table = table,
.size = RIP_MAX_ROUTES
};
}
// ReceviedFrame recv_frame = {};
// printf("task %d starting...\n", curr_channel);
// vTaskDelay(3000 / portTICK_PERIOD_MS);
ReceviedFrame recv_frame = {};
printf("task %d starting...\n", curr_channel);
vTaskDelay(3000 / portTICK_PERIOD_MS);
// bool receive_only = false;
bool receive_only = false;
#if defined(RECEIVE_ONLY) && RECEIVE_ONLY
receive_only = true;
#else
receive_only = false;
#endif
// while(1){
// if(!receive_only){
// vTaskDelay(1000 / portTICK_PERIOD_MS); // wait 1 second before trying to send again
while(1){
if(!receive_only){
printf("waiting for 3 seconds...\n");
vTaskDelay(pdMS_TO_TICKS(3000)); // wait 3 second before trying to send again
// snprintf(reinterpret_cast<char*>(send_buf), sizeof(send_buf), "This is a message from board %d sending on channel %d. %s", BOARD_ID, curr_channel, message);
snprintf(reinterpret_cast<char*>(send_buf), sizeof(send_buf), "This is a message from board %d sending on channel %d. %s %s %s", BOARD_ID, curr_channel, message, generic_frame_additional_message, generic_frame_second_additional_message);
// snprintf(reinterpret_cast<char*>(send_buf), sizeof(send_buf), "This is a message from board %d sending on channel %d. %s %s", BOARD_ID, curr_channel, message, generic_frame_additional_message);
// snprintf(reinterpret_cast<char*>(send_buf), sizeof(send_buf), "This is a message from board %d sending on channel %d. %s", BOARD_ID, curr_channel, message);
// ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &start_count));
// res = obj->send(dest_board_id, send_buf, strlen(reinterpret_cast<char*>(send_buf)), FrameType::DEBUG_CONTROL_TYPE, 0x0);
// ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &end_count));
ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &start_count));
res = obj->send(dest_board_id, send_buf, strlen(reinterpret_cast<char*>(send_buf)), FrameType::MISC_GENERIC_TYPE, 0x0);
ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &end_count));
// // snprintf(reinterpret_cast<char*>(send_buf), sizeof(send_buf), "%s RANDOM", mej.kssage); //modifying the data while it transmits shouldn't affect the actual transmission here
// snprintf(reinterpret_cast<char*>(send_buf), sizeof(send_buf), "%s RANDOM", mej.kssage); //modifying the data while it transmits shouldn't affect the actual transmission here
// if (res != ESP_OK){
// ESP_LOGE("thread", "Failed to send message on thread %d. Error: 0x%x", curr_channel, res);
// continue;
// } else {
// // printf("Successfully sent message %s\n", send_buf);
// printf("Sent %zu B sized in %" PRIu64 " us from channel %d\n", strlen(reinterpret_cast<char*>(send_buf)) + CONTROL_FRAME_OVERHEAD, end_count-start_count, curr_channel);
// }
// }
if (res != ESP_OK){
ESP_LOGE("thread", "Failed to send message on thread %d. Error: 0x%x", curr_channel, res);
continue;
} else {
// printf("Successfully sent message %s\n", send_buf);
printf("Sent %zu B sized in %" PRIu64 " us from channel %d\n", strlen(reinterpret_cast<char*>(send_buf)) + CONTROL_FRAME_OVERHEAD, end_count-start_count, curr_channel);
}
}
// //wait on a queue for a few ms (if there's nothing, just send another frame. otherwise pop from queue and read it)
// if (xQueueReceive(shared_queue, (void*)&recv_frame, (TickType_t) 50) != pdPASS){
// memset(send_buf, 0, 256);
// continue; //nothing or failed to pop from queue
// }
// total_transactions++;
// if (recv_frame.len == 0){
// //receive fail
// num_incorrect++;
// } else {
// // res = obj->print_frame_info(recv_frame.buf, recv_frame.len, recv_buf, DATA_SIZE_TEST);
//wait on a queue for a few ms (if there's nothing, just send another frame. otherwise pop from queue and read it)
printf("waiting for rx\n");
if (xQueueReceive(shared_queue, (void*)&recv_frame, pdMS_TO_TICKS(36000)) != pdPASS){
memset(send_buf, 0, DATA_SIZE_TEST);
printf("didn't receive anything in time\n");
continue; //nothing or failed to pop from queue
}
total_transactions++;
if (recv_frame.len == 0){
//receive fail
num_incorrect++;
} else {
// res = obj->print_frame_info(recv_frame.buf, recv_frame.len, recv_buf, DATA_SIZE_TEST);
// if (res != ESP_OK){
// num_incorrect++;
// // printf("Received %ld bad frames on tx/rx round %ld for thread %d\n", num_incorrect, total_transactions, curr_channel);
// } else {
// // printf("Header information:\n");
// // printf("Preamble\tTX ID\tRX ID\tSeq Num\tType/Flag\tFrag Info\tData Len\tCRC\n");
// // printf("%X\t%d\t%d\t%d\t%X\t%ld\t%d\t%d\n",recv_frame.header.preamble, recv_frame.header.sender_id, recv_frame.header.receiver_id, recv_frame.header.seq_num,
// // recv_frame.header.type_flag, recv_frame.header.frag_info, recv_frame.header.data_len, recv_frame.header.crc_16);
// // printf("Received message '%.*s' on channel %d\n", recv_frame.len, recv_frame.buf, curr_channel);
// }
// }
if (res != ESP_OK){
num_incorrect++;
// printf("Received %ld bad frames on tx/rx round %ld for thread %d\n", num_incorrect, total_transactions, curr_channel);
} else {
// printf("Header information:\n");
// printf("Preamble\tTX ID\tRX ID\tSeq Num\tFrag Info\tType/Flag\tData Len\tCRC\n");
// printf("0x%02X\t\t%-12d %-13d\t%-15d\t0x%02lX\t%d\t%-10d\t0x%04X\n",recv_frame.header.preamble, recv_frame.header.sender_id, recv_frame.header.receiver_id, recv_frame.header.seq_num,
// recv_frame.header.frag_info, recv_frame.header.type_flag, recv_frame.header.data_len, recv_frame.header.crc_16);
printf("Received message '%.*s' on channel %d from board %d seq num %d\n", recv_frame.len, recv_frame.buf, curr_channel, recv_frame.header.sender_id, recv_frame.header.seq_num);
}
}
// printf("Total received packets: %ld\tTotal packets corrupted: %ld\n", total_transactions, num_incorrect);
// printf("Total received packets: %ld\tTotal packets corrupted: %ld\n", total_transactions, num_incorrect);
// // vTaskDelay(1000 / portTICK_PERIOD_MS); // wait 1 second before trying to send again
// //reset temp buffers
// memset(recv_buf, 0, DATA_SIZE_TEST);
// memset(send_buf, 0, DATA_SIZE_TEST);
// vTaskDelay(1000 / portTICK_PERIOD_MS); // wait 1 second before trying to send again
//reset temp buffers
memset(recv_buf, 0, DATA_SIZE_TEST);
memset(send_buf, 0, DATA_SIZE_TEST);
// }
}
// while(true){
// vTaskDelay(2000 / portTICK_PERIOD_MS);
// }
while(true){
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
// }
}
// void print_binary(unsigned char c) {
// for (int i = 7; i >= 0; i--) {
// printf("%d", (c >> i) & 1);
// }
// }
void print_binary(unsigned char c) {
for (int i = 7; i >= 0; i--) {
printf("%d", (c >> i) & 1);
}
}
// void print_string_binary(const char *str) {
// while (*str) {
// print_binary((unsigned char)*str);
// printf(" "); // space between bytes for readability
// str++;
// }
// printf("\n");
// }
void print_string_binary(const char *str) {
while (*str) {
print_binary((unsigned char)*str);
printf(" "); // space between bytes for readability
str++;
}
printf("\n");
}
// extern "C" [[noreturn]] void app_main(void) {
// esp_err_t ret = nvs_flash_init();
// if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// ESP_ERROR_CHECK(nvs_flash_erase());
// ret = nvs_flash_init();
// }
// ESP_ERROR_CHECK(ret);
extern "C" [[noreturn]] void app_main(void) {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// esp_netif_init();
// esp_event_loop_create_default();
esp_netif_init();
esp_event_loop_create_default();
// printf("finished esp init\n");
printf("finished esp init\n");
// printf("Hello world!\n");
printf("Hello world!\n");
// // uint8_t iteration = 0;
// // const char* message = "THIS IS A TEXT MESSAGE";
// uint8_t num_channels = 4;
// std::unique_ptr<DataLinkManager> obj = std::make_unique<DataLinkManager>(BOARD_ID, num_channels);
// uint8_t iteration = 0;
// const char* message = "THIS IS A TEXT MESSAGE";
uint8_t num_channels = 4;
std::unique_ptr<DataLinkManager> obj = std::make_unique<DataLinkManager>(BOARD_ID, num_channels);
if (obj->ready() != ESP_OK){
for (int i = 5; i >= 0; i--) {
printf("Restarting in %d seconds...\n", i);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
printf("Restarting now.\n");
fflush(stdout);
esp_restart();
}
// // uint8_t dest_board_id = 2; //using a dummy number for now - there is no board with id 2 right now
// uint8_t dest_board_id = 2; //using a dummy number for now - there is no board with id 2 right now
// // esp_err_t res;
// esp_err_t res;
// // uint8_t send_buf[256];
// // uint8_t recv_buf[256];
// // size_t recv_len = 0;
// uint8_t send_buf[256];
// uint8_t recv_buf[256];
// size_t recv_len = 0;
// // uint8_t curr_channel = 0;
// uint8_t curr_channel = 0;
// DataLinkManager* obj_to_send = obj.release();
DataLinkManager* obj_to_send = obj.release();
// TaskArgs args[4] = {};
TaskArgs args[4] = {};
// for (uint8_t i = 0; i < 1; i++){
// args[i].link_layer_obj = obj_to_send;
// args[i].task_id = i;
// args[i].receiver_id = RECEIVER_BOARD_ID;
// args[i].receive_queue = xQueueCreate(10, sizeof(ReceviedFrame)); //queue storing up to 10 control frames
// xTaskCreate(multi_transceiver, "multi_transceiver", 4096, static_cast<void*>(&args[i]), 5, NULL);
// vTaskDelay(500 / portTICK_PERIOD_MS);
// }
for (uint8_t i = 0; i < 1; i++){
args[i].link_layer_obj = obj_to_send;
args[i].task_id = i;
args[i].receiver_id = RECEIVER_BOARD_ID;
args[i].receive_queue = xQueueCreate(10, sizeof(ReceviedFrame)); //queue storing up to 10 control frames
xTaskCreate(multi_transceiver, "multi_transceiver", 8192, static_cast<void*>(&args[i]), 5, NULL);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
// printf("Tasks have been created\n");
printf("Tasks have been created\n");
// while(true){
// //do nothing
// vTaskDelay(1000 / portTICK_PERIOD_MS);
// }
// for (int i = 5; i >= 0; i--) {
// printf("Restarting in %d seconds...\n", i);
// vTaskDelay(1000 / portTICK_PERIOD_MS);
// }
// printf("Restarting now.\n");
// fflush(stdout);
// esp_restart();
// while(true){
// //dummy wait
// vTaskDelay(2000 / portTICK_PERIOD_MS);
// }
// }
while(true){
//do nothing
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
#endif //RMT_TEST