mirror of
https://github.com/BotChain-Robots/firmware.git
synced 2026-07-08 17:47:21 +02:00
decrease freq resolution for rmt to hopefully make it more reliable
This commit is contained in:
@@ -176,12 +176,18 @@ esp_err_t DataLinkManager::send(uint8_t dest_board, uint8_t* data, uint16_t data
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ESP_LOGI(DEBUG_LINK_TAG, "Sending %d bytes", offset);
|
// ESP_LOGI(DEBUG_LINK_TAG, "Sending %d bytes", offset);
|
||||||
// print_buffer_binary(send_data, frame_size);
|
// printf("Sending Frame Information:\n");
|
||||||
|
// printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n",
|
||||||
|
// "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC");
|
||||||
|
|
||||||
|
// printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n",
|
||||||
|
// new_frame.preamble, new_frame.sender_id, new_frame.receiver_id, new_frame.seq_num, new_frame.type_flag, new_frame.data_len, new_frame.crc_16);
|
||||||
|
|
||||||
uint8_t channel_to_route = MAX_CHANNELS;
|
uint8_t channel_to_route = MAX_CHANNELS;
|
||||||
if (new_frame.receiver_id == BROADCAST_ADDR){
|
if (new_frame.receiver_id == BROADCAST_ADDR){
|
||||||
for (uint8_t i = 0; i < num_channels; i++){
|
for (uint8_t i = 0; i < num_channels; i++){
|
||||||
|
// printf("Sending on channel %d\n", i);
|
||||||
phys_comms->send(send_data, offset, &config, i);
|
phys_comms->send(send_data, offset, &config, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,16 +195,12 @@ esp_err_t DataLinkManager::send(uint8_t dest_board, uint8_t* data, uint16_t data
|
|||||||
res = route_frame(new_frame.receiver_id, &channel_to_route);
|
res = route_frame(new_frame.receiver_id, &channel_to_route);
|
||||||
|
|
||||||
if (res != ESP_OK){
|
if (res != ESP_OK){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Failed to find entry for %d", new_frame.receiver_id);
|
// ESP_LOGE(DEBUG_LINK_TAG, "Failed to find entry for %d", new_frame.receiver_id);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
ESP_LOGI(DEBUG_LINK_TAG, "Sending message to %d", new_frame.receiver_id);
|
// ESP_LOGI(DEBUG_LINK_TAG, "Sending message to %d", new_frame.receiver_id);
|
||||||
phys_comms->send(send_data, offset, &config, channel_to_route);
|
phys_comms->send(send_data, offset, &config, channel_to_route);
|
||||||
}
|
}
|
||||||
|
|
||||||
//can wait for the rmt to finish
|
|
||||||
// esp_err_t res = phys_comms->wait_until_send_complete(curr_channel); //this cannot be here in deployment but until the RMT manager can hold this copy of data this will have to be here
|
|
||||||
|
|
||||||
// if (res != ESP_OK){
|
// if (res != ESP_OK){
|
||||||
// ESP_LOGE(DEBUG_LINK_TAG, "Failed to send message");
|
// ESP_LOGE(DEBUG_LINK_TAG, "Failed to send message");
|
||||||
// return ESP_FAIL;
|
// return ESP_FAIL;
|
||||||
@@ -209,6 +211,7 @@ esp_err_t DataLinkManager::send(uint8_t dest_board, uint8_t* data, uint16_t data
|
|||||||
} else {
|
} else {
|
||||||
//generic frame
|
//generic frame
|
||||||
printf("not implemented yet\n");
|
printf("not implemented yet\n");
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -241,20 +244,29 @@ esp_err_t DataLinkManager::start_receive_frames(uint8_t curr_channel){
|
|||||||
return phys_comms->start_receiving(curr_channel);
|
return phys_comms->start_receiving(curr_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @param data_len
|
||||||
|
* @param recv_len
|
||||||
|
* @param curr_channel
|
||||||
|
* @return esp_err_t
|
||||||
|
*/
|
||||||
esp_err_t DataLinkManager::receive(uint8_t* data, size_t data_len, size_t* recv_len, uint8_t curr_channel){
|
esp_err_t DataLinkManager::receive(uint8_t* data, size_t data_len, size_t* recv_len, uint8_t curr_channel){
|
||||||
if (data == NULL){
|
if (data == NULL){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid data array");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid data array");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr_channel >= num_channels){
|
if (curr_channel >= num_channels){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid channel");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid channel");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_len < MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD){
|
if (data_len < MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Receive data buffer len is too small");
|
ESP_LOGE(DEBUG_LINK_TAG, "Receive data buffer len is too small");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint8_t recv_buf[256];
|
// uint8_t recv_buf[256];
|
||||||
@@ -263,38 +275,39 @@ esp_err_t DataLinkManager::receive(uint8_t* data, size_t data_len, size_t* recv_
|
|||||||
|
|
||||||
if (res != ESP_OK){
|
if (res != ESP_OK){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "RMT Failed to receive");
|
ESP_LOGE(DEBUG_LINK_TAG, "RMT Failed to receive");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*recv_len > MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD){
|
if (*recv_len > MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid control frame");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid control frame");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*recv_len < CONTROL_FRAME_OVERHEAD) {
|
if (*recv_len < CONTROL_FRAME_OVERHEAD) {
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* message = (uint8_t*)pvPortMalloc(CONTROL_FRAME_OVERHEAD + MAX_CONTROL_DATA_LEN);
|
uint8_t* message = (uint8_t*)pvPortMalloc(CONTROL_FRAME_OVERHEAD + MAX_CONTROL_DATA_LEN);
|
||||||
if (message == nullptr){
|
if (message == nullptr){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Failed to malloc for receive");
|
ESP_LOGE(DEBUG_LINK_TAG, "Failed to malloc for receive");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
memset(message, 0, sizeof(message));
|
memset(message, 0, sizeof(message));
|
||||||
size_t message_size = 0;
|
size_t message_size = 0;
|
||||||
frame_header header;
|
frame_header header;
|
||||||
res = get_data_from_frame(data, *recv_len, message, &message_size, &header);
|
res = get_data_from_frame(data, *recv_len, message, &message_size, &header);
|
||||||
if (res != ESP_OK){
|
if (res != ESP_OK){
|
||||||
|
// print_buffer_binary(message, message_size);
|
||||||
vPortFree((void*)message);
|
vPortFree((void*)message);
|
||||||
return ESP_FAIL;
|
return res;
|
||||||
}
|
}
|
||||||
*recv_len = message_size;
|
*recv_len = message_size;
|
||||||
memcpy(data, message, message_size);
|
memcpy(data, message, message_size);
|
||||||
ESP_LOGI(DEBUG_LINK_TAG, "Received frame of type 0x%X destined for board %d", GET_TYPE(header.type_flag), header.receiver_id);
|
// ESP_LOGI(DEBUG_LINK_TAG, "Received frame of type 0x%X destined for board %d", GET_TYPE(header.type_flag), header.receiver_id);
|
||||||
|
|
||||||
//check for a rip frame
|
//check for a rip frame
|
||||||
if (static_cast<FrameType>(GET_TYPE(header.type_flag)) == FrameType::RIP_TABLE_CONTROL){
|
if (static_cast<FrameType>(GET_TYPE(header.type_flag)) == FrameType::RIP_TABLE_CONTROL){
|
||||||
printf("Got a RIP frame\n");
|
// printf("Got a RIP frame\n");
|
||||||
|
|
||||||
for (size_t i = 0; i < message_size-1; i+=2){
|
for (size_t i = 0; i < message_size-1; i+=2){
|
||||||
uint8_t board_id = message[i];
|
uint8_t board_id = message[i];
|
||||||
@@ -361,19 +374,19 @@ esp_err_t DataLinkManager::receive(uint8_t* data, size_t data_len, size_t* recv_
|
|||||||
esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, frame_header* header){
|
esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, uint8_t* message, size_t* message_size, frame_header* header){
|
||||||
if (data == nullptr){
|
if (data == nullptr){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid data array");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid data array");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (message == nullptr){
|
if (message == nullptr){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid message array");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid message array");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (message_size == nullptr){
|
if (message_size == nullptr){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid message size ptr");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid message size ptr");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (header == nullptr){
|
if (header == nullptr){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Invalid header ptr");
|
ESP_LOGE(DEBUG_LINK_TAG, "Invalid header ptr");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_CONTROL_FRAME(data[5])){
|
if (IS_CONTROL_FRAME(data[5])){
|
||||||
@@ -386,12 +399,12 @@ esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, u
|
|||||||
|
|
||||||
if (header->data_len > data_len){
|
if (header->data_len > data_len){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Mismatch data length in control frame");
|
ESP_LOGE(DEBUG_LINK_TAG, "Mismatch data length in control frame");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->data_len == 0){
|
if (header->data_len == 0){
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "Data len 0");
|
ESP_LOGE(DEBUG_LINK_TAG, "Data len 0");
|
||||||
return ESP_FAIL;
|
return ESP_ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*message_size = header->data_len;
|
*message_size = header->data_len;
|
||||||
@@ -400,18 +413,21 @@ esp_err_t DataLinkManager::get_data_from_frame(uint8_t* data, size_t data_len, u
|
|||||||
|
|
||||||
geneate_crc_16(data, 8*sizeof(uint8_t) + header->data_len, &header->crc_16);
|
geneate_crc_16(data, 8*sizeof(uint8_t) + header->data_len, &header->crc_16);
|
||||||
|
|
||||||
if (((uint16_t)data[8 + header->data_len] | ((uint16_t)data[9 + header->data_len] << 8)) != header->crc_16){
|
uint16_t crc_calc = ((uint16_t)data[8 + header->data_len] | ((uint16_t)data[9 + header->data_len] << 8));
|
||||||
|
|
||||||
|
if (crc_calc != header->crc_16){
|
||||||
//CRC mismatch
|
//CRC mismatch
|
||||||
ESP_LOGE(DEBUG_LINK_TAG, "CRC Mismatch");
|
ESP_LOGE(DEBUG_LINK_TAG, "CRC Mismatch");
|
||||||
return ESP_FAIL;
|
ESP_LOGE(DEBUG_LINK_TAG, "Got 0x%04X but calculated 0x%04X\n", crc_calc, header->crc_16);
|
||||||
|
return ESP_ERR_INVALID_CRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Frame Information:\n");
|
// printf("Received Frame Information:\n");
|
||||||
printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n",
|
// printf("%-10s %-12s %-13s %-15s %-12s %-10s %-6s\n",
|
||||||
"Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC");
|
// "Preamble", "Sender ID", "Receiver ID", "Sequence Num", "Type+Flag", "Data Len", "CRC");
|
||||||
|
|
||||||
printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n",
|
// printf("0x%02X %-12d %-13d %-15d 0x%02X %-10d 0x%04X\n",
|
||||||
header->preamble, header->sender_id, header->receiver_id, header->seq_num, header->type_flag, header->data_len, header->crc_16);
|
// header->preamble, header->sender_id, header->receiver_id, header->seq_num, header->type_flag, header->data_len, header->crc_16);
|
||||||
} else {
|
} else {
|
||||||
//not implemented yet
|
//not implemented yet
|
||||||
}
|
}
|
||||||
@@ -448,7 +464,7 @@ esp_err_t DataLinkManager::geneate_crc_16(uint8_t* data, size_t data_len, uint16
|
|||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t DataLinkManager::print_frame_info(uint8_t* data, size_t data_len, uint8_t* message){
|
esp_err_t DataLinkManager::print_frame_info(uint8_t* data, size_t data_len, uint8_t* message){
|
||||||
printf("Received frame of size %d:\n", data_len);
|
// printf("Received frame of size %d:\n", data_len);
|
||||||
|
|
||||||
size_t message_size;
|
size_t message_size;
|
||||||
|
|
||||||
|
|||||||
25
components/dataLink/test_scripts/parse_bit_frame.py
Normal file
25
components/dataLink/test_scripts/parse_bit_frame.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
def parse(byte_message: list[str]):
|
||||||
|
print("got", len(byte_message), "bytes")
|
||||||
|
preamble = byte_message[0]
|
||||||
|
sender_id = int(byte_message[1], 2)
|
||||||
|
receiver_id = int(byte_message[2], 2)
|
||||||
|
seq_num = int(byte_message[4]+byte_message[3], 2)
|
||||||
|
type_flag = hex(int(byte_message[5], 2)).upper()
|
||||||
|
data_len = int(byte_message[7]+byte_message[6], 2)
|
||||||
|
message = ''
|
||||||
|
for x in range(8, 8+data_len):
|
||||||
|
message += chr(int(byte_message[x], 2))
|
||||||
|
crc_16 = int(byte_message[8+data_len+1]+byte_message[8+data_len], 2)
|
||||||
|
|
||||||
|
print("Preamble", preamble, "Sender ID", sender_id, "Receiver ID", receiver_id, \
|
||||||
|
"Sequence Number", seq_num, "Type + Flag", type_flag, "Message length (B)", data_len, \
|
||||||
|
"Message:\n", message, "\nCRC-16", crc_16)
|
||||||
|
if __name__ == "__main__":
|
||||||
|
message = "10101011 01000101 00000001 00010010 00000000 11000000 01101011 00000000 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01101101 01100101 01110011 01110011 01100001 01100111 01100101 00100000 01100110 01110010 01101111 01101101 00100000 01100010 01101111 01100001 01110010 01100100 00100000 00110110 00111001 00100000 01110011 01100101 01101110 01100100 01101001 01101110 01100111 00100000 01101111 01101110 00100000 01100011 01101000 01100001 01101110 01101110 01100101 01101100 00100000 00110000 00101110 00100000 01110100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01110011 01101111 01101101 01100101 00100000 01101111 01110100 01101000 01100101 01110010 00100000 01100100 01100001 01110100 01100001 00100000 01110100 01101000 01100001 01110100 00100000 01110011 01101000 01101111 01110101 01101100 01100100 00100000 01101110 01101111 01110100 00100000 01100010 01100101 00100000 01100011 01101111 01110010 01110010 01110101 01110000 01110100 01100101 01100100 00101110 01000100 11001010"
|
||||||
|
parse(byte_message=message.split(" "))
|
||||||
|
message = "10101011 01000101 00000001 00010011 00000000 11000000 01101011 00000000 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01101101 01100101 01110011 01110011 01100001 01100111 01100101 00100000 01100110 01110010 01101111 01101101 00100000 01100010 01101111 01100001 01110010 01100100 00100000 00110110 00111001 00100000 01110011 01100101 01101110 01100100 01101001 01101110 01100111 00100000 01101111 01101110 00100000 01100011 01101000 01100001 01101110 01101110 01100101 01101100 00100000 00110000 00101110 00100000 01110100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01110011 01101111 01101101 01100101 00100000 01101111 01110100 01101000 01100101 01110010 00100000 01100100 01100001 01110100 01100001 00100000 01110100 01101000 01100001 01110100 00100000 01110011 01101000 01101111 01110101 01101100 01100100 00100000 01101110 01101111 01110100 00100000 01100010 01100101 00100000 01100011 01101111 01110010 01110010 01110101 01110000 01110100 01100101 01100100 00101110 01100011 01100111"
|
||||||
|
parse(byte_message=message.split(" "))
|
||||||
|
message = "10101011 01000101 00000001 00010100 00000000 11000000 01101011 00000000 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01101101 01100101 01110011 01110011 01100001 01100111 01100101 00100000 01100110 01110010 01101111 01101101 00100000 01100010 01101111 01100001 01110010 01100100 00100000 00110110 00111001 00100000 01110011 01100101 01101110 01100100 01101001 01101110 01100111 00100000 01101111 01101110 00100000 01100011 01101000 01100001 01101110 01101110 01101101 01001011 00001000 00001010 11111010 00111011 11110001 01110010 11110010 11010001 10011011 11110010 11010001 10011011 11110001 10010010 00010010 01010011 01011011 11110010 00010001 01110010 11110011 01010001 10111011 11110011 01110011 11010001 01110011 11011011 11110001 01110010 11110011 11010001 01111011 11110001 10010010 11110010 00010001 01010010 01110011 01111011 11110010 00110010 00010001 01111011 11110011 10110011 01011011 11110011 10010010 00010001 10110001 10110001 01010001 11110001 01110011 01010011 01111010 00100001 01011101"
|
||||||
|
parse(byte_message=message.split(" "))
|
||||||
|
message = "10101011 01000101 00000001 00010111 00000000 11000000 01101011 00000000 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01101101 01100101 01110011 01110011 01100001 01100111 01100101 00100000 01100110 01110010 01101111 01101101 00100000 01100010 01101111 01100001 01110010 01100100 00100000 00110110 00111001 00100000 01110011 01100101 01101110 01100100 01101001 01101110 01100111 00100000 01101111 01101110 00100000 01100011 01101000 01100001 01101110 01101110 01100101 01101100 00100000 00110000 00101110 00100000 01110100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01110011 01101111 01101101 01100101 00100000 01101111 01110100 01101000 01100101 01110010 00100000 01100100 01100001 01110100 01100001 00100000 01110100 01101000 01100001 01110100 00100000 01110011 01101000 01101111 01110101 01101100 01100100 00100000 01101110 01101111 01110100 00100000 01100010 01100101 00100000 01100011 01101111 01110010 01110010 01110101 01110000 01110100 01100101 01100100 00101110 10111101 11110011"
|
||||||
|
parse(byte_message=message.split(" "))
|
||||||
@@ -29,6 +29,9 @@ RMTManager::RMTManager(uint8_t num_channels = MAX_CHANNELS){
|
|||||||
|
|
||||||
esp_err_t RMTManager::init_tx_channel(){
|
esp_err_t RMTManager::init_tx_channel(){
|
||||||
esp_err_t res_tx = ESP_FAIL;
|
esp_err_t res_tx = ESP_FAIL;
|
||||||
|
memory_to_free = xQueueCreate(15, sizeof(uint8_t*));
|
||||||
|
|
||||||
|
xTaskCreate(RMTManager::freeMemory, "RIPFreeMem", 4096, static_cast<void*>(memory_to_free), 5, NULL);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < num_channels; i++){
|
for (uint8_t i = 0; i < num_channels; i++){
|
||||||
//setup encoder config
|
//setup encoder config
|
||||||
@@ -98,10 +101,11 @@ esp_err_t RMTManager::init_tx_channel(){
|
|||||||
|
|
||||||
channels[i].tx_done_semaphore = xSemaphoreCreateBinary(); //create a binary sem
|
channels[i].tx_done_semaphore = xSemaphoreCreateBinary(); //create a binary sem
|
||||||
|
|
||||||
TxCallbackContext* tx_callback_ctx = new TxCallbackContext {
|
channels[i].tx_context = {
|
||||||
.tx_done_sem = channels[i].tx_done_semaphore,
|
.tx_done_sem = channels[i].tx_done_semaphore,
|
||||||
.transmit_queue = channels[i].tx_queue,
|
.transmit_queue = channels[i].tx_queue,
|
||||||
.tx_context = &channels[i].encoder_context
|
.tx_context = &channels[i].encoder_context,
|
||||||
|
.free_mem_queue = memory_to_free
|
||||||
};
|
};
|
||||||
|
|
||||||
if (channels[i].tx_done_semaphore == NULL){
|
if (channels[i].tx_done_semaphore == NULL){
|
||||||
@@ -110,7 +114,7 @@ esp_err_t RMTManager::init_tx_channel(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// res_tx = rmt_tx_register_event_callbacks(channels[i].tx_rmt_handle, &tx_cbs, channels[i].tx_done_semaphore);
|
// res_tx = rmt_tx_register_event_callbacks(channels[i].tx_rmt_handle, &tx_cbs, channels[i].tx_done_semaphore);
|
||||||
res_tx = rmt_tx_register_event_callbacks(channels[i].tx_rmt_handle, &tx_cbs, static_cast<void*>(tx_callback_ctx));
|
res_tx = rmt_tx_register_event_callbacks(channels[i].tx_rmt_handle, &tx_cbs, static_cast<void*>(&channels[i].tx_context));
|
||||||
|
|
||||||
if (res_tx != ESP_OK) {
|
if (res_tx != ESP_OK) {
|
||||||
// printf("Failed to register TX callback\n");
|
// printf("Failed to register TX callback\n");
|
||||||
@@ -144,13 +148,14 @@ bool RMTManager::rmt_tx_done_callback(rmt_channel_handle_t channel, const rmt_tx
|
|||||||
QueueHandle_t queue = args->transmit_queue;
|
QueueHandle_t queue = args->transmit_queue;
|
||||||
rmt_encoder_context_t* encoder_context = args->tx_context;
|
rmt_encoder_context_t* encoder_context = args->tx_context;
|
||||||
|
|
||||||
|
QueueHandle_t free_queue = args->free_mem_queue;
|
||||||
|
|
||||||
TxBuffer buf = {};
|
TxBuffer buf = {};
|
||||||
BaseType_t xTaskWokenByReceive = pdFALSE;
|
BaseType_t xTaskWokenByReceive = pdFALSE;
|
||||||
xQueueReceiveFromISR(queue, static_cast<TxBuffer*>(&buf), &xTaskWokenByReceive); //remove from the queue
|
xQueueReceiveFromISR(queue, static_cast<TxBuffer*>(&buf), &xTaskWokenByReceive); //remove from the queue
|
||||||
|
|
||||||
if (buf.data != nullptr){
|
if (buf.data != nullptr){
|
||||||
vPortFree((void*)buf.data);
|
xQueueSendFromISR(free_queue, &buf.data, &xTaskWokenByReceive);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoder_context != nullptr){
|
if (encoder_context != nullptr){
|
||||||
@@ -186,10 +191,10 @@ bool RMTManager::rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx
|
|||||||
QueueHandle_t receive_queue = (QueueHandle_t)user_data;
|
QueueHandle_t receive_queue = (QueueHandle_t)user_data;
|
||||||
// send the received RMT symbols to the parser task
|
// send the received RMT symbols to the parser task
|
||||||
BaseType_t res = xQueueSendFromISR(receive_queue, edata, &high_task_wakeup);
|
BaseType_t res = xQueueSendFromISR(receive_queue, edata, &high_task_wakeup);
|
||||||
if (res != pdTRUE){
|
// if (res != pdTRUE){
|
||||||
// printf("RX Callback: Failed to enqueue received data\n");
|
// // printf("RX Callback: Failed to enqueue received data\n");
|
||||||
ESP_LOGE(DEBUG_TAG, "RX Callback: Failed to enqueue received data");
|
// // ESP_LOGE(DEBUG_TAG, "RX Callback: Failed to enqueue received data");
|
||||||
}
|
// }
|
||||||
// return whether any task is woken up
|
// return whether any task is woken up
|
||||||
return high_task_wakeup == pdTRUE;
|
return high_task_wakeup == pdTRUE;
|
||||||
}
|
}
|
||||||
@@ -274,6 +279,21 @@ esp_err_t RMTManager::init(){
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void RMTManager::freeMemory(void* args){
|
||||||
|
QueueHandle_t queue = (QueueHandle_t)(args);
|
||||||
|
|
||||||
|
uint8_t* dummy;
|
||||||
|
|
||||||
|
while (true){
|
||||||
|
if (xQueueReceive(queue, &dummy, pdMS_TO_TICKS(10)) == pdTRUE){
|
||||||
|
if (dummy != nullptr){
|
||||||
|
vPortFree((void*)dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is a callback function called by RMT when transmitting. This function will encode the user data `data` with rising and falling edges based on the bit.a64l
|
* @brief This is a callback function called by RMT when transmitting. This function will encode the user data `data` with rising and falling edges based on the bit.a64l
|
||||||
* The symbols are defined in `RMTManager.h`, where a bit 1 is transmitted as a `RMT_SYMBOL_ONE` and a bit 0 is transmitted as a `RMT_SYMBOL_ZERO`
|
* The symbols are defined in `RMTManager.h`, where a bit 1 is transmitted as a `RMT_SYMBOL_ONE` and a bit 0 is transmitted as a `RMT_SYMBOL_ZERO`
|
||||||
@@ -300,59 +320,10 @@ size_t RMTManager::encoder_callback(const void* data, size_t data_size, size_t s
|
|||||||
uint8_t byte = bytes[ctx->byte_index]; //get the byte from the data
|
uint8_t byte = bytes[ctx->byte_index]; //get the byte from the data
|
||||||
uint8_t bit = (byte >> (7 - ctx->bit_index)) & 0x01; //get the current bit, as determined from the bit index (MSB first)
|
uint8_t bit = (byte >> (7 - ctx->bit_index)) & 0x01; //get the current bit, as determined from the bit index (MSB first)
|
||||||
|
|
||||||
#ifndef NRZ_INVERTED
|
//Manchester (Ethernet Standard) Encoding
|
||||||
//Manchester (Ethernet Standard) Encoding
|
symbols[symbols_used++] = bit ? RMT_SYMBOL_ONE : RMT_SYMBOL_ZERO; //if the bit is a 1, transmit a 1 symbol; otherwise, transmit 0 symbol
|
||||||
symbols[symbols_used++] = bit ? RMT_SYMBOL_ONE : RMT_SYMBOL_ZERO; //if the bit is a 1, transmit a 1 symbol; otherwise, transmit 0 symbol
|
ctx->num_symbols++;
|
||||||
ctx->num_symbols++;
|
|
||||||
#else
|
|
||||||
//NRZ-I encoding. Must change the voltage level whenever a bit 1 is detected
|
|
||||||
if (ctx->byte_index == 0 && ctx->bit_index == 0){
|
|
||||||
//MSB of the first byte - send a rising edge 1 to allow any succeeding 0s to be detected by the receiver
|
|
||||||
symbols[symbols_used++] = RMT_SYMBOL_ONE_RISING;
|
|
||||||
ctx->current_level = !ctx->current_level; //current level is high
|
|
||||||
ctx->num_symbols++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->zero_count == CONSEC_ZERO_THRESHOLD){
|
|
||||||
ctx->current_level = !ctx->current_level;
|
|
||||||
symbols[symbols_used++] = ctx->current_level ? RMT_SYMBOL_ONE_RISING : RMT_SYMBOL_ONE_FALLING;
|
|
||||||
ctx->num_symbols++;
|
|
||||||
ctx->zero_count = 0;
|
|
||||||
|
|
||||||
// Don't advance to next bit – reprocess the current bit
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bit == 1){
|
|
||||||
ctx->current_level = !ctx->current_level; //invert current level
|
|
||||||
symbols[symbols_used++] = ctx->current_level ? RMT_SYMBOL_ONE_RISING : RMT_SYMBOL_ONE_FALLING; //if current level is 0 (low), it must be a falling edge. otherwise, it is a rising edge
|
|
||||||
ctx->num_symbols++;
|
|
||||||
ctx->zero_count = 0;
|
|
||||||
} else {
|
|
||||||
//bit 0s, maintain current level
|
|
||||||
if (ctx->current_level){
|
|
||||||
//check if the previous symbol was RMT_SYMBOL_ZERO_HIGH. if it is, simply add another RMT_DURATION_MAX on duration1 (this is a slight optimization to send less symbols)
|
|
||||||
if (symbols[symbols_used-1].level0 == 1 && symbols[symbols_used-1].level1 == 1){
|
|
||||||
symbols[symbols_used-1].duration1 += RMT_DURATION_MAX;
|
|
||||||
} else {
|
|
||||||
//previous symbol was not RMT_SYMBOL_ZERO_HIGH
|
|
||||||
symbols[symbols_used++] = RMT_SYMBOL_ZERO_HIGH;
|
|
||||||
ctx->num_symbols++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (symbols[symbols_used-1].level0 == 0 && symbols[symbols_used-1].level1 == 0){
|
|
||||||
symbols[symbols_used-1].duration1 += RMT_DURATION_MAX;
|
|
||||||
} else {
|
|
||||||
symbols[symbols_used++] = ctx->current_level ? RMT_SYMBOL_ZERO_HIGH : RMT_SYMBOL_ZERO_LOW;
|
|
||||||
ctx->num_symbols++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->zero_count++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
ctx->bit_index++;
|
ctx->bit_index++;
|
||||||
if (ctx->bit_index >= 8) {
|
if (ctx->bit_index >= 8) {
|
||||||
//reached the end of the byte; go to the next byte
|
//reached the end of the byte; go to the next byte
|
||||||
@@ -370,9 +341,6 @@ void RMTManager::reset_encoder_context(rmt_encoder_context_t* ctx){
|
|||||||
ctx->bit_index = 0;
|
ctx->bit_index = 0;
|
||||||
ctx->byte_index = 0;
|
ctx->byte_index = 0;
|
||||||
ctx->num_symbols = 0;
|
ctx->num_symbols = 0;
|
||||||
#ifdef NRZ_INVERTED
|
|
||||||
ctx->current_level = false;
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -396,7 +364,12 @@ esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* co
|
|||||||
|
|
||||||
if (this->channels[channel_num].tx_rmt_handle == nullptr) {
|
if (this->channels[channel_num].tx_rmt_handle == nullptr) {
|
||||||
// printf("send() error: tx_chan is NULL\n");
|
// printf("send() error: tx_chan is NULL\n");
|
||||||
ESP_LOGE(DEBUG_TAG, "send() error: tx_chan is NULL");
|
ESP_LOGE(DEBUG_TAG, "send() error: tx_rmt_handle is NULL");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
if (this->channels[channel_num].tx_queue == nullptr) {
|
||||||
|
// printf("send() error: tx_chan is NULL\n");
|
||||||
|
ESP_LOGE(DEBUG_TAG, "send() error: tx_queue is NULL");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
if (this->channels[channel_num].encoder == nullptr) {
|
if (this->channels[channel_num].encoder == nullptr) {
|
||||||
@@ -427,7 +400,7 @@ esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* co
|
|||||||
|
|
||||||
memcpy((void*)(new_data_to_send_buf.data), data, size);
|
memcpy((void*)(new_data_to_send_buf.data), data, size);
|
||||||
|
|
||||||
if (xQueueSendToBack(channels[channel_num].tx_queue, (void*)&new_data_to_send_buf, (TickType_t) 10) != pdPASS){ //note this may not work very well since im not checking the return value; this function can fail if the queue is full
|
if (xQueueSendToBack(channels[channel_num].tx_queue, (void*)&new_data_to_send_buf, (TickType_t) 10) != pdPASS){
|
||||||
vPortFree((void*)new_data_to_send_buf.data);
|
vPortFree((void*)new_data_to_send_buf.data);
|
||||||
ESP_LOGE(DEBUG_TAG, "Failed to queue data");
|
ESP_LOGE(DEBUG_TAG, "Failed to queue data");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
@@ -463,126 +436,39 @@ int RMTManager::decode_symbols(rmt_symbol_word_t* symbols, size_t num, rmt_symbo
|
|||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
bool curr_high_low = true; //flag to maintain where we are (either high or low)
|
bool curr_high_low = true; //flag to maintain where we are (either high or low)
|
||||||
|
|
||||||
#ifdef NRZ_INVERTED
|
|
||||||
uint32_t num_0_symbols_duration = 0, num_0_symbols = 0;
|
|
||||||
uint8_t consecutive_zeros = 0;
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
while (output_index < output_num && i < num){
|
while (output_index < output_num && i < num){
|
||||||
// printf("duration0 %d level0 %d duration1 %d level1 %d\n", symbols[i].duration0, symbols[i].level0, symbols[i].duration1, symbols[i].level1); //dummy print receive
|
// printf("duration0 %d level0 %d duration1 %d level1 %d\n", symbols[i].duration0, symbols[i].level0, symbols[i].duration1, symbols[i].level1); //dummy print receive
|
||||||
#ifndef NRZ_INVERTED
|
//manchester encoding
|
||||||
//manchester encoding
|
/*there are two cases in the beginning:
|
||||||
/*there are two cases in the beginning:
|
1. if duration0 = 20, then we are in between two symbols (low to high and high to low).
|
||||||
1. if duration0 = 20, then we are in between two symbols (low to high and high to low).
|
in this case, we need to insert a low in the beginning and "split" the current symbol into 2
|
||||||
in this case, we need to insert a low in the beginning and "split" the current symbol into 2
|
2. if duration0 = 10, then the first symbol should be high to low
|
||||||
2. if duration0 = 10, then the first symbol should be high to low
|
*/
|
||||||
*/
|
if (symbols[i].duration0 != RMT_DURATION_SYMBOL){
|
||||||
if (symbols[i].duration0 != RMT_DURATION_SYMBOL){
|
if (i != 0){
|
||||||
if (i != 0){
|
if (curr_high_low){
|
||||||
if (curr_high_low){
|
decoded[output_index++] = RMT_SYMBOL_ONE;
|
||||||
decoded[output_index++] = RMT_SYMBOL_ONE;
|
|
||||||
} else {
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ZERO;
|
|
||||||
}
|
|
||||||
curr_high_low = !curr_high_low;
|
|
||||||
} else {
|
} else {
|
||||||
//need to insert a 0 before received symbols
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ZERO;
|
decoded[output_index++] = RMT_SYMBOL_ZERO;
|
||||||
}
|
}
|
||||||
|
curr_high_low = !curr_high_low;
|
||||||
}
|
|
||||||
|
|
||||||
if (curr_high_low){
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ONE;
|
|
||||||
} else {
|
} else {
|
||||||
|
//need to insert a 0 before received symbols
|
||||||
decoded[output_index++] = RMT_SYMBOL_ZERO;
|
decoded[output_index++] = RMT_SYMBOL_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if duration1 = 20, then we are starting low
|
}
|
||||||
if (symbols[i].duration1 != RMT_DURATION_SYMBOL){
|
|
||||||
curr_high_low = !curr_high_low;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
//nrz-i encoding - bit stuffing doesn't work
|
|
||||||
//there is always a rising edge (period of RMT_DURATION_SYMBOL on high as the first half isn't captured)
|
|
||||||
// if (i == 0){
|
|
||||||
// curr_high_low = true;
|
|
||||||
// if (symbols[i].duration0 == RMT_DURATION_MAX){
|
|
||||||
// //next symbol is a 1 - can continue (first RMT_DURATION is from the first symbol (init rising edge). second RMT_DURATION is second symbol)
|
|
||||||
// i++;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//need to "split"
|
if (curr_high_low){
|
||||||
if (symbols[i].duration0 % (RMT_DURATION_SYMBOL * 2) != 0){
|
decoded[output_index++] = RMT_SYMBOL_ONE;
|
||||||
num_0_symbols_duration = symbols[i].duration0 - RMT_DURATION_SYMBOL; //last waveform has duration0 with some duration that's only a multiple of RMT_DURATION_SYMBOL
|
} else {
|
||||||
}else {
|
decoded[output_index++] = RMT_SYMBOL_ZERO;
|
||||||
num_0_symbols_duration = symbols[i].duration0 - RMT_DURATION_SYMBOL * 2; //one from the rising edge, one from the falling edge
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
num_0_symbols = num_0_symbols_duration / RMT_DURATION_MAX; //should be the number of 0 symbols
|
|
||||||
for (int j = 0; j < num_0_symbols && output_index < output_num; j++){
|
|
||||||
decoded[output_index++] = curr_high_low ? RMT_SYMBOL_ZERO_HIGH : RMT_SYMBOL_ZERO_LOW;
|
|
||||||
consecutive_zeros++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//if duration1 = 20, then we are starting low
|
||||||
|
if (symbols[i].duration1 != RMT_DURATION_SYMBOL){
|
||||||
curr_high_low = !curr_high_low;
|
curr_high_low = !curr_high_low;
|
||||||
if (output_index >= output_num){
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!curr_high_low){
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ONE_FALLING;
|
|
||||||
} else {
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ONE_RISING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (consecutive_zeros == MAX_ZER){
|
|
||||||
// consecutive_zeros = 0;
|
|
||||||
// } else {
|
|
||||||
// if (!curr_high_low) {
|
|
||||||
// decoded[output_index++] = RMT_SYMBOL_ONE_FALLING;
|
|
||||||
// } else {
|
|
||||||
// decoded[output_index++] = RMT_SYMBOL_ONE_RISING;
|
|
||||||
// }
|
|
||||||
// consecutive_zeros = 0; // reset zero count after a real 1 bit
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (symbols[i].duration1 == 0){
|
|
||||||
break; //last waveform has duration1 = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
num_0_symbols_duration = symbols[i].duration1 - RMT_DURATION_SYMBOL * 2; //one from the falling edge, one from the rising edge
|
|
||||||
num_0_symbols = num_0_symbols_duration / RMT_DURATION_MAX; //should be the number of 0 symbols
|
|
||||||
|
|
||||||
for (int j = 0; j < num_0_symbols && output_index < output_num; j++){
|
|
||||||
decoded[output_index++] = curr_high_low ? RMT_SYMBOL_ZERO_HIGH : RMT_SYMBOL_ZERO_LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr_high_low = !curr_high_low;
|
|
||||||
if (output_index >= output_num){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!curr_high_low){
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ONE_FALLING;
|
|
||||||
} else {
|
|
||||||
decoded[output_index++] = RMT_SYMBOL_ONE_RISING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (consecutive_zeros == 5){
|
|
||||||
// consecutive_zeros = 0;
|
|
||||||
// } else {
|
|
||||||
// if (!curr_high_low) {
|
|
||||||
// decoded[output_index++] = RMT_SYMBOL_ONE_FALLING;
|
|
||||||
// } else {
|
|
||||||
// decoded[output_index++] = RMT_SYMBOL_ONE_RISING;
|
|
||||||
// }
|
|
||||||
// consecutive_zeros = 0; // reset zero count after a real 1 bit
|
|
||||||
// }
|
|
||||||
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -609,28 +495,14 @@ int RMTManager::convert_symbols_to_char(rmt_symbol_word_t* symbols, size_t num,
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (i < num && output_index < output_num){
|
while (i < num && output_index < output_num){
|
||||||
#ifndef NRZ_INVERTED
|
if (symbols[i].level0 == 0 && symbols[i].level1 == 1){
|
||||||
if (symbols[i].level0 == 0 && symbols[i].level1 == 1){
|
//zero
|
||||||
//zero
|
byte = byte << 1;
|
||||||
byte = byte << 1;
|
}else if (symbols[i].level0 == 1 && symbols[i].level1 == 0) {
|
||||||
}else if (symbols[i].level0 == 1 && symbols[i].level1 == 0) {
|
byte = (byte << 1) + 1;
|
||||||
byte = (byte << 1) + 1;
|
} else {
|
||||||
} else {
|
return ESP_FAIL;
|
||||||
return ESP_FAIL;
|
}
|
||||||
}
|
|
||||||
#else
|
|
||||||
//nrz-i
|
|
||||||
|
|
||||||
if (symbols[i].level0 != symbols[i].level1){
|
|
||||||
//bit 1
|
|
||||||
byte = (byte << 1) + 1;
|
|
||||||
} else if (symbols[i].level0 == symbols[i].level1){
|
|
||||||
//bit 0
|
|
||||||
byte = byte << 1;
|
|
||||||
} else {
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
|
|
||||||
bit_count++;
|
bit_count++;
|
||||||
if (bit_count == 8){
|
if (bit_count == 8){
|
||||||
@@ -717,16 +589,21 @@ esp_err_t RMTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_siz
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("\n\nparsed symbols:\n");
|
|
||||||
// for (int i = 0; i < num; i++){
|
|
||||||
// printf("duration0 %d level0 %d duration1 %d level1 %d\n", decoded_recv_symbols[i].duration0, decoded_recv_symbols[i].level0, decoded_recv_symbols[i].duration1, decoded_recv_symbols[i].level1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
*output_size = this->convert_symbols_to_char(channels[channel_num].decoded_recv_symbols, num, recv_buf, size);
|
*output_size = this->convert_symbols_to_char(channels[channel_num].decoded_recv_symbols, num, recv_buf, size);
|
||||||
if (*output_size < 0){
|
if (*output_size < 0){
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//UNCOMMENT HERE TO GET RAW BITS TO USE IN `components/dataLink/test_scripts/parse_bit_frame.py`
|
||||||
|
// printf("\n\nparsed characters:\n");
|
||||||
|
// for (int i = 0; i < *output_size; i++) {
|
||||||
|
// for (int bit = 7; bit >= 0; bit--) {
|
||||||
|
// printf("%d", (recv_buf[i] >> bit) & 1);
|
||||||
|
// }
|
||||||
|
// printf(" ");
|
||||||
|
// }
|
||||||
|
// printf("\nDone\n");
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,21 @@ typedef struct {
|
|||||||
size_t byte_index; //which byte is currently being encoded when transmitting
|
size_t byte_index; //which byte is currently being encoded when transmitting
|
||||||
uint8_t bit_index; //which bit in the `byte_index` is currently being encoded (into high/low waveforms)
|
uint8_t bit_index; //which bit in the `byte_index` is currently being encoded (into high/low waveforms)
|
||||||
size_t num_symbols; //temp
|
size_t num_symbols; //temp
|
||||||
#ifdef NRZ_INVERTED
|
|
||||||
bool current_level;
|
|
||||||
uint8_t zero_count;
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
} rmt_encoder_context_t;
|
} rmt_encoder_context_t;
|
||||||
|
|
||||||
|
//will need to keep the data alive until it has been transmitted (not working or being used atm)
|
||||||
|
struct TxCallbackContext{
|
||||||
|
SemaphoreHandle_t tx_done_sem;
|
||||||
|
QueueHandle_t transmit_queue;
|
||||||
|
rmt_encoder_context_t* tx_context;
|
||||||
|
QueueHandle_t free_mem_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* data;
|
||||||
|
size_t length;
|
||||||
|
} TxBuffer;
|
||||||
|
|
||||||
typedef struct _rmt_channel{
|
typedef struct _rmt_channel{
|
||||||
//TX
|
//TX
|
||||||
uint8_t tx_gpio;
|
uint8_t tx_gpio;
|
||||||
@@ -47,6 +56,7 @@ typedef struct _rmt_channel{
|
|||||||
QueueHandle_t tx_queue;
|
QueueHandle_t tx_queue;
|
||||||
rmt_encoder_handle_t encoder; //encoder config
|
rmt_encoder_handle_t encoder; //encoder config
|
||||||
rmt_encoder_context_t encoder_context;
|
rmt_encoder_context_t encoder_context;
|
||||||
|
TxCallbackContext tx_context;
|
||||||
|
|
||||||
//RX
|
//RX
|
||||||
uint8_t rx_gpio;
|
uint8_t rx_gpio;
|
||||||
@@ -86,6 +96,8 @@ class RMTManager{
|
|||||||
int decode_symbols(rmt_symbol_word_t* symbols, size_t num, rmt_symbol_word_t* decoded, size_t output_num);
|
int decode_symbols(rmt_symbol_word_t* symbols, size_t num, rmt_symbol_word_t* decoded, size_t output_num);
|
||||||
int convert_symbols_to_char(rmt_symbol_word_t* symbols, size_t num, uint8_t* string, size_t output_num);
|
int convert_symbols_to_char(rmt_symbol_word_t* symbols, size_t num, uint8_t* string, size_t output_num);
|
||||||
|
|
||||||
|
[[noreturn]] static void freeMemory(void* args);
|
||||||
|
|
||||||
rmt_channel channels[MAX_CHANNELS] = {0};
|
rmt_channel channels[MAX_CHANNELS] = {0};
|
||||||
//=====================TX=====================
|
//=====================TX=====================
|
||||||
|
|
||||||
@@ -102,7 +114,7 @@ class RMTManager{
|
|||||||
//will be used to temporarily hold the bits that are being wait to be sent -- not working
|
//will be used to temporarily hold the bits that are being wait to be sent -- not working
|
||||||
// QueueHandle_t transmit_queue = NULL;
|
// QueueHandle_t transmit_queue = NULL;
|
||||||
|
|
||||||
// TxCallbackContext tx_context;
|
QueueHandle_t memory_to_free;
|
||||||
|
|
||||||
//=====================RX=====================
|
//=====================RX=====================
|
||||||
rmt_channel_handle_t rx_chan;
|
rmt_channel_handle_t rx_chan;
|
||||||
@@ -124,19 +136,6 @@ class RMTManager{
|
|||||||
// bool ready_to_receive = false;
|
// bool ready_to_receive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
//will need to keep the data alive until it has been transmitted (not working or being used atm)
|
|
||||||
|
|
||||||
struct TxCallbackContext{
|
|
||||||
SemaphoreHandle_t tx_done_sem;
|
|
||||||
QueueHandle_t transmit_queue;
|
|
||||||
rmt_encoder_context_t* tx_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const uint8_t* data;
|
|
||||||
size_t length;
|
|
||||||
} TxBuffer;
|
|
||||||
|
|
||||||
typedef struct _gpio_channel_pair {
|
typedef struct _gpio_channel_pair {
|
||||||
gpio_num_t tx_pin;
|
gpio_num_t tx_pin;
|
||||||
gpio_num_t rx_pin;
|
gpio_num_t rx_pin;
|
||||||
|
|||||||
@@ -2,43 +2,11 @@
|
|||||||
|
|
||||||
#include "driver/rmt_tx.h"
|
#include "driver/rmt_tx.h"
|
||||||
|
|
||||||
// #ifdef MANCHESTER_40
|
#define RMT_RESOLUTION_HZ 3 * 1000 * 1000 // 3MHz resolution
|
||||||
// #define RMT_RESOLUTION_HZ 40 * 1000 * 1000 // 40MHz resolution
|
#define RMT_DURATION_SYMBOL 1 //0.667us
|
||||||
// #define RMT_DURATION_SYMBOL 10 //0.25 us bit duration
|
|
||||||
// #elif NRZ_INVERTED
|
|
||||||
// #ifdef NRZ_INVERTED_40_HZ
|
|
||||||
// #define RMT_RESOLUTION_HZ 40 * 1000 * 1000 // 40MHz resolution
|
|
||||||
// #else
|
|
||||||
// #define RMT_RESOLUTION_HZ 20 * 1000 * 1000 // 20MHz resolution
|
|
||||||
// #endif //NRZ_INVERTED_40_HZ
|
|
||||||
// #ifdef NRZ_INVERTED_10
|
|
||||||
// #define RMT_DURATION_SYMBOL 10 //0.5us bit duration
|
|
||||||
// #elif NRZ_INVERTED_20
|
|
||||||
// #define RMT_DURATION_SYMBOL 5 //0.25 us bit duration
|
|
||||||
// #elif NRZ_INVERTED_2
|
|
||||||
// #define RMT_DURATION_SYMBOL 2 //0.1 us bit duration
|
|
||||||
// #else
|
|
||||||
// #define RMT_DURATION_SYMBOL 20 //1us bit duration
|
|
||||||
// #endif //NRZ_INVERTED_10
|
|
||||||
// #else
|
|
||||||
// #define RMT_RESOLUTION_HZ 1 * 1000 * 1000 // 1MHz resolution
|
|
||||||
// #define RMT_DURATION_SYMBOL 10
|
|
||||||
// #endif //MANCHESTER_40
|
|
||||||
|
|
||||||
// #define NRZ_INVERTED //using NRZ_I
|
|
||||||
#define RMT_RESOLUTION_HZ 40 * 1000 * 1000 // 40MHz resolution
|
|
||||||
#define RMT_DURATION_SYMBOL 12 //0.6us
|
|
||||||
|
|
||||||
|
|
||||||
// #define RMT_DURATION_SYMBOL ((RMT_RESOLUTION_HZ * 3) / 1000000) // duration time for a symbol - this is 3us
|
|
||||||
|
|
||||||
#define RMT_DURATION_MAX (2 * RMT_DURATION_SYMBOL)
|
#define RMT_DURATION_MAX (2 * RMT_DURATION_SYMBOL)
|
||||||
|
|
||||||
// #define RMT_TX_GPIO GPIO_NUM_1 //RMT will use GPIO pin 1 to transmit (on one channel)
|
|
||||||
|
|
||||||
// #define RMT_RX_GPIO GPIO_NUM_12 // RMT will use GPIO pin 12 to receive (on one channel)
|
|
||||||
|
|
||||||
#ifndef NRZ_INVERTED
|
|
||||||
//MANCHESTER ENCODING (ETHERNET STANDARD)
|
//MANCHESTER ENCODING (ETHERNET STANDARD)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,60 +30,6 @@ static const rmt_symbol_word_t RMT_SYMBOL_ZERO = {
|
|||||||
.duration1 = RMT_DURATION_SYMBOL,
|
.duration1 = RMT_DURATION_SYMBOL,
|
||||||
.level1 = 1,
|
.level1 = 1,
|
||||||
};
|
};
|
||||||
#else
|
|
||||||
|
|
||||||
//Non-Return-to-Zero Inverted (NRZ-I)
|
|
||||||
|
|
||||||
#define CONSEC_ZERO_THRESHOLD 3 //max number of consecutive zeros before adding a bit 1
|
|
||||||
|
|
||||||
// Logic 1 inverts the current voltage state
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct represents a 1 symbol being transmitted over RMT. This will create a falling edge (low for `RMT_DURATION_SYMBOL` and high for `RMT_DURATION_SYMBOL`)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static const rmt_symbol_word_t RMT_SYMBOL_ONE_FALLING = {
|
|
||||||
.duration0 = RMT_DURATION_SYMBOL,
|
|
||||||
.level0 = 1,
|
|
||||||
.duration1 = RMT_DURATION_SYMBOL,
|
|
||||||
.level1 = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct represents a 1 symbol being transmitted over RMT. This will create a rising edge (low for `RMT_DURATION_SYMBOL` and high for `RMT_DURATION_SYMBOL`)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static const rmt_symbol_word_t RMT_SYMBOL_ONE_RISING = {
|
|
||||||
.duration0 = RMT_DURATION_SYMBOL,
|
|
||||||
.level0 = 0,
|
|
||||||
.duration1 = RMT_DURATION_SYMBOL,
|
|
||||||
.level1 = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct will represent a bit 0. In NRZ-I, this represents a no change in the voltage
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static const rmt_symbol_word_t RMT_SYMBOL_ZERO_HIGH = {
|
|
||||||
.duration0 = RMT_DURATION_SYMBOL,
|
|
||||||
.level0 = 1,
|
|
||||||
.duration1 = RMT_DURATION_SYMBOL,
|
|
||||||
.level1 = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct will represent a bit 0. In NRZ-I, this represents a no change in the voltage
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static const rmt_symbol_word_t RMT_SYMBOL_ZERO_LOW = {
|
|
||||||
.duration0 = RMT_DURATION_SYMBOL,
|
|
||||||
.level0 = 0,
|
|
||||||
.duration1 = RMT_DURATION_SYMBOL,
|
|
||||||
.level1 = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //NRZ_INVERTED
|
|
||||||
|
|
||||||
//not used at the moment
|
//not used at the moment
|
||||||
|
|
||||||
|
|||||||
310
main/main_rmt_test.cpp
Normal file
310
main/main_rmt_test.cpp
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
// //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 "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"
|
||||||
|
|
||||||
|
// #define DATA_SIZE_TEST 270
|
||||||
|
// #define BOARD_ID 1
|
||||||
|
|
||||||
|
// struct TaskArgs{
|
||||||
|
// DataLinkManager* link_layer_obj;
|
||||||
|
// uint8_t task_id;
|
||||||
|
// uint8_t receiver_id;
|
||||||
|
// QueueHandle_t receive_queue;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// struct ReceviedFrame{
|
||||||
|
// uint8_t buf[MAX_CONTROL_DATA_LEN + CONTROL_FRAME_OVERHEAD]; //max 41B
|
||||||
|
// size_t len;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// void receive_frames(void* arg){
|
||||||
|
// TaskArgs* args = (TaskArgs*)arg;
|
||||||
|
|
||||||
|
// DataLinkManager* obj = args->link_layer_obj;
|
||||||
|
|
||||||
|
// if (obj == nullptr){
|
||||||
|
// ESP_LOGE("thread", "bad pointer\n");
|
||||||
|
// vTaskDelete(NULL); //should never get here
|
||||||
|
// }
|
||||||
|
|
||||||
|
// QueueHandle_t shared_queue = (QueueHandle_t)args->receive_queue;
|
||||||
|
|
||||||
|
// uint8_t curr_channel = args-> task_id;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// size_t recv_len = 0;
|
||||||
|
|
||||||
|
// ReceviedFrame recv_frame = {};
|
||||||
|
|
||||||
|
// while(true){
|
||||||
|
// res = obj->start_receive_frames(curr_channel); // this will be moved to a separate thread with a shared queue
|
||||||
|
// if (res != ESP_OK){
|
||||||
|
// ESP_LOGE("thread", "Failed to start rx async job on thread %d", curr_channel);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// res = obj->receive(recv_buf, sizeof(recv_buf), &recv_len, curr_channel);
|
||||||
|
// if (res != ESP_OK){
|
||||||
|
// // ESP_LOGE("thread", "Failed to receive message on thread %d", curr_channel);
|
||||||
|
// if (res != ESP_FAIL) {
|
||||||
|
// 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 (recv_len == 0){
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// recv_frame.len = recv_len;
|
||||||
|
// memcpy((void*)recv_frame.buf, (void*)recv_buf, recv_len);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// DataLinkManager* obj = args->link_layer_obj;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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.";
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// size_t recv_len = 0;
|
||||||
|
// uint8_t iteration = 0;
|
||||||
|
// esp_err_t res;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ReceviedFrame recv_frame = {};
|
||||||
|
// printf("task %d starting...\n", curr_channel);
|
||||||
|
// vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
// bool receive_only = false;
|
||||||
|
|
||||||
|
// while(1){
|
||||||
|
// if(!receive_only){
|
||||||
|
// vTaskDelay(1000 / portTICK_PERIOD_MS); // wait 1 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);
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
// // 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", curr_channel);
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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("Received message %s on channel %d on round %ld. Total bad frames %ld\n", recv_buf, curr_channel, total_transactions, num_incorrect);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// printf("Total received packets: %ld\tTotal packets corrupted: %ld\n", total_transactions, num_incorrect);
|
||||||
|
|
||||||
|
// // iteration++;
|
||||||
|
// // if (iteration == 10){
|
||||||
|
// // iteration = 0;
|
||||||
|
// // // if (!receive_only){
|
||||||
|
// // // matrix_size = RIP_MAX_ROUTES;
|
||||||
|
// // // res = obj->get_network_toplogy(matrix, &matrix_size);
|
||||||
|
// // // if (res != ESP_OK){
|
||||||
|
// // // ESP_LOGE("multi", "Failed to get topology");
|
||||||
|
// // // } else {
|
||||||
|
// // // for (int i = 0; i < matrix_size; i++){
|
||||||
|
// // // printf("Table for board %d:\n", matrix[i].board_id);
|
||||||
|
// // // printf("board_id\t\tHops\t\tChannel\n");
|
||||||
|
// // // for (int j = 0; j < matrix[i].size; j++){
|
||||||
|
// // // printf("%d\t\t%d\t\t%d\n", matrix[i].table[j].info.board_id, matrix[i].table[j].info.hops, matrix[i].table[j].channel);
|
||||||
|
// // // }
|
||||||
|
// // // printf("=====\n");
|
||||||
|
|
||||||
|
// // // //reset matrix
|
||||||
|
// // // matrix[i].size = RIP_MAX_ROUTES;
|
||||||
|
// // // }
|
||||||
|
// // // }
|
||||||
|
// // // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // 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);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// printf("finished esp init\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 dest_board_id = 2; //using a dummy number for now - there is no board with id 2 right now
|
||||||
|
|
||||||
|
// // esp_err_t res;
|
||||||
|
|
||||||
|
// // uint8_t send_buf[256];
|
||||||
|
// // uint8_t recv_buf[256];
|
||||||
|
// // size_t recv_len = 0;
|
||||||
|
|
||||||
|
// // uint8_t curr_channel = 0;
|
||||||
|
|
||||||
|
// DataLinkManager* obj_to_send = obj.release();
|
||||||
|
|
||||||
|
// 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 = 69;
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
Reference in New Issue
Block a user