diff --git a/COMM.c b/COMM.c deleted file mode 100644 index a2b1c27..0000000 --- a/COMM.c +++ /dev/null @@ -1,131 +0,0 @@ - -#include "Comm/COMM.h" -#include "Comm/NRF24_CORE.h" -#include "Comm/COMM_PACKETS.h" -#include -#include - -static comm_robot_type_t s_current_robot_type; -static uint8_t s_packet_seq_counter = 0; -static comm_packet_t s_tx_packet_buffer; -static comm_packet_t s_rx_packet_buffer; - -static uint8_t s_my_listening_address[5]; -static uint8_t s_peer_target_address[5]; -static uint8_t s_rf_channel; - -static comm_ssl_command_handler_t s_ssl_cmd_handler = NULL; -static comm_vsss_command_handler_t s_vsss_cmd_handler = NULL; -static comm_ssl_telemetry_handler_t s_ssl_tel_handler = NULL; -static comm_vsss_telemetry_handler_t s_vsss_tel_handler = NULL; -static comm_debug_text_handler_t s_debug_text_handler = NULL; - -static bool send_packet_p2p(comm_packet_t* packet_to_send) { - NRF24_TxMode(s_peer_target_address, s_rf_channel); - bool success = NRF24_Transmit((uint8_t*)packet_to_send, sizeof(comm_packet_t)); - NRF24_RxMode(s_my_listening_address, 0, s_rf_channel); - - return success; -} - -bool Comm_Init_P2P(comm_robot_type_t robot_type, - uint8_t channel, - const uint8_t my_listening_address[5], - const uint8_t peer_target_address[5]) { - s_current_robot_type = robot_type; - s_packet_seq_counter = 0; - s_rf_channel = channel; - - memcpy(s_my_listening_address, my_listening_address, 5); - memcpy(s_peer_target_address, peer_target_address, 5); - - printf("Comm_Init_P2P: Robô tipo %d, Canal %d\r\n", robot_type, channel); - - NRF24_Init(); - NRF24_RxMode(s_my_listening_address, 0, s_rf_channel); // Inicia escutando - printf("NRF24 configurado como Transceptor, iniciando em modo RX.\r\n"); - return true; -} - -// --- Funções de Envio --- -int16_t Comm_Send_SSL_Command(const ssl_command_payload_t* cmd_payload_data) { - if (cmd_payload_data == NULL) return -1; - uint8_t current_seq = s_packet_seq_counter++; - Comm_Packets_Create_SSLCommand(&s_tx_packet_buffer, current_seq, cmd_payload_data); - if (send_packet_p2p(&s_tx_packet_buffer)) { - return current_seq; - } - return -1; -} -int16_t Comm_Send_VSSS_Command(const vsss_command_payload_t* cmd_payload_data) { - if (cmd_payload_data == NULL) return -1; - uint8_t current_seq = s_packet_seq_counter++; - Comm_Packets_Create_VSSSCommand(&s_tx_packet_buffer, current_seq, cmd_payload_data); - if (send_packet_p2p(&s_tx_packet_buffer)) { - return current_seq; - } - return -1; -} - -int16_t Comm_Send_SSL_Telemetry(const ssl_telemetry_payload_t* tel_payload_data) { - if (tel_payload_data == NULL) return -1; - uint8_t current_seq = s_packet_seq_counter++; - Comm_Packets_Create_SSLTelemetry(&s_tx_packet_buffer, current_seq, tel_payload_data); - if (send_packet_p2p(&s_tx_packet_buffer)) { - return current_seq; - } - return -1; -} - -int16_t Comm_Send_VSSS_Telemetry(const vsss_telemetry_payload_t* tel_payload_data) { - if (tel_payload_data == NULL) return -1; - uint8_t current_seq = s_packet_seq_counter++; - Comm_Packets_Create_VSSTelemetry(&s_tx_packet_buffer, current_seq, tel_payload_data); - if (send_packet_p2p(&s_tx_packet_buffer)) { - return current_seq; - } - return -1; -} -int16_t Comm_Send_DebugText_Message(const char* text_payload) { - if (text_payload == NULL) return -1; - uint8_t current_seq = s_packet_seq_counter++; - Comm_Packets_Create_DebugText(&s_tx_packet_buffer, current_seq, text_payload); - if (send_packet_p2p(&s_tx_packet_buffer)) { - return current_seq; - } - return -1; -} - -void Comm_Register_SSL_CommandHandler(comm_ssl_command_handler_t callback) { s_ssl_cmd_handler = callback; } -void Comm_Register_VSSS_CommandHandler(comm_vsss_command_handler_t callback) { s_vsss_cmd_handler = callback; } -void Comm_Register_SSL_TelemetryHandler(comm_ssl_telemetry_handler_t callback) { s_ssl_tel_handler = callback; } -void Comm_Register_VSSS_TelemetryHandler(comm_vsss_telemetry_handler_t callback) { s_vsss_tel_handler = callback; } -void Comm_Register_DebugText_Packet_Handler(comm_debug_text_handler_t callback) { s_debug_text_handler = callback; } - -void Comm_ProcessReceivedPackets(void) { - if (isDataAvailable(1)) { - uint8_t raw_input_buffer[NRF_MAX_PACKET_SIZE]; - NRF24_Receive(raw_input_buffer); - memcpy(&s_rx_packet_buffer, raw_input_buffer, sizeof(comm_packet_t)); - - switch (s_rx_packet_buffer.header.main_type) { - case MAIN_PACKET_TYPE_SSL_COMMAND: - if (s_ssl_cmd_handler != NULL) s_ssl_cmd_handler(&s_rx_packet_buffer.payload_u.ssl_cmd, s_rx_packet_buffer.payload_u.ssl_cmd.robot_id, s_rx_packet_buffer.header.seq_number); - break; - case MAIN_PACKET_TYPE_VSSS_COMMAND: - if (s_vsss_cmd_handler != NULL) s_vsss_cmd_handler(&s_rx_packet_buffer.payload_u.vsss_cmd, s_rx_packet_buffer.payload_u.vsss_cmd.robot_id, s_rx_packet_buffer.header.seq_number); - break; - case MAIN_PACKET_TYPE_SSL_TELEMETRY: - if (s_ssl_tel_handler != NULL) s_ssl_tel_handler(&s_rx_packet_buffer.payload_u.ssl_tel, s_rx_packet_buffer.payload_u.ssl_tel.robot_id, s_rx_packet_buffer.header.seq_number); - break; - case MAIN_PACKET_TYPE_VSSS_TELEMETRY: - if (s_vsss_tel_handler != NULL) s_vsss_tel_handler(&s_rx_packet_buffer.payload_u.vsss_tel, s_rx_packet_buffer.payload_u.vsss_tel.robot_id, s_rx_packet_buffer.header.seq_number); - break; - case MAIN_PACKET_TYPE_DEBUG_TEXT: - break; - default: - printf("Comm: Tipo de pacote principal desconhecido: %d\r\n", s_rx_packet_buffer.header.main_type); - break; - } - } -} \ No newline at end of file diff --git a/COMM.cpp b/COMM.cpp new file mode 100644 index 0000000..a55ce75 --- /dev/null +++ b/COMM.cpp @@ -0,0 +1,160 @@ +// Comm/COMM.cpp +#include // Atualizado caminho de inclusão +#include // Atualizado caminho de inclusão +#include // Atualizado caminho de inclusão +#include +#include + + +static comm_robot_type_t s_current_robot_type; +static comm_node_mode_t s_current_node_mode; +static uint8_t s_packet_seq_counter = 0; +static comm_packet_t s_comm_packet_buffer; + + +static comm_ssl_packet_handler_t s_ssl_handler = nullptr; // Opcional: usar nullptr +static comm_vsss_packet_handler_t s_vsss_handler = nullptr; // Opcional: usar nullptr +static comm_debug_text_handler_t s_debug_text_handler = nullptr; // Opcional: usar nullptr + + +bool Comm_Init(comm_robot_type_t robot_type, + comm_node_mode_t node_mode, + uint8_t channel, + uint8_t* nrf_tx_address, + uint8_t* nrf_rx_pipe1_address, + uint8_t nrf_rx_pipe2_lsb) +{ + s_current_robot_type = robot_type; + s_current_node_mode = node_mode; + s_packet_seq_counter = 0; + + printf("Comm_Init: Modo %s, Robô %s, Canal %d\r\n", + (node_mode == COMM_NODE_MODE_TRANSMITTER) ? "TX" : "RX", + (robot_type == COMM_ROBOT_TYPE_SSL) ? "SSL" : (robot_type == COMM_ROBOT_TYPE_VSSS) ? "VSSS" : "N/A", + channel); + + NRF24_Init(); + + if (s_current_node_mode == COMM_NODE_MODE_TRANSMITTER) { + NRF24_TxMode(nrf_tx_address, channel); + printf("NRF24 configurado como Transmissor.\r\n"); + } else { + NRF24_RxMode(nrf_rx_pipe1_address, nrf_rx_pipe2_lsb, channel); + printf("NRF24 configurado como Receptor.\r\n"); + } + return true; +} + + +bool Comm_Send_SSL_Message(const ssl_payload_t* ssl_payload_data) { + if (s_current_node_mode != COMM_NODE_MODE_TRANSMITTER) { + printf("Comm_Send_SSL_Message: Erro - Nó não está em modo transmissor.\r\n"); + return false; + } + if (ssl_payload_data == nullptr) { // Alterado de NULL para nullptr + printf("Comm_Send_SSL_Message: Erro - Payload SSL nulo.\r\n"); + return false; + } + + Comm_Packets_Create_SSLMessage(&s_comm_packet_buffer, s_packet_seq_counter++, ssl_payload_data); + + //printf("Comm Enviando SSL: Seq %d, ID %d, Vx %d\r\n", s_comm_packet_buffer.header.seq_number, ssl_payload_data->robot_id, ssl_payload_data->vx); + return NRF24_Transmit((uint8_t*)&s_comm_packet_buffer, sizeof(comm_packet_t)); +} + +bool Comm_Send_VSSS_Message(const vsss_payload_t* vsss_payload_data) { + if (s_current_node_mode != COMM_NODE_MODE_TRANSMITTER) { + printf("Comm_Send_VSSS_Message: Erro - Nó não está em modo transmissor.\r\n"); + return false; + } + if (vsss_payload_data == nullptr) { // Alterado de NULL para nullptr + printf("Comm_Send_VSSS_Message: Erro - Payload VSSS nulo.\r\n"); + return false; + } + + Comm_Packets_Create_VSSSMessage(&s_comm_packet_buffer, s_packet_seq_counter++, vsss_payload_data); + + // printf("Comm Enviando VSSS: Seq %d, ID %d, M1 %d\r\n", s_comm_packet_buffer.header.seq_number, vsss_payload_data->robot_id, vsss_payload_data->motor1_value); + return NRF24_Transmit((uint8_t*)&s_comm_packet_buffer, sizeof(comm_packet_t)); +} + +bool Comm_Send_DebugText_Message(const char* text_payload) { + if (s_current_node_mode != COMM_NODE_MODE_TRANSMITTER) { + printf("Comm_Send_DebugText_Message: Erro - Nó não está em modo transmissor.\r\n"); + return false; + } + if (text_payload == nullptr) { // Alterado de NULL para nullptr + printf("Comm_Send_DebugText_Message: Erro - Texto nulo.\r\n"); + return false; + } + + Comm_Packets_Create_DebugText(&s_comm_packet_buffer, s_packet_seq_counter++, text_payload); + + // printf("Comm Enviando Debug: Seq %d, Texto: %s\r\n", s_comm_packet_buffer.header.seq_number, text_payload); + return NRF24_Transmit((uint8_t*)&s_comm_packet_buffer, sizeof(comm_packet_t)); +} + + + +void Comm_Register_SSL_Packet_Handler(comm_ssl_packet_handler_t callback) { + s_ssl_handler = callback; +} + +void Comm_Register_VSSS_Packet_Handler(comm_vsss_packet_handler_t callback) { + s_vsss_handler = callback; +} + +void Comm_Register_DebugText_Packet_Handler(comm_debug_text_handler_t callback) { + s_debug_text_handler = callback; +} + +void Comm_ProcessReceivedPackets(void) { + if (s_current_node_mode != COMM_NODE_MODE_RECEIVER) { + return; + } + + uint8_t raw_input_buffer[NRF_MAX_PACKET_SIZE]; + + if (isDataAvailable(1)) { // Verifica Pipe 1 (poderia ser configurável ou verificar múltiplos pipes) + NRF24_Receive(raw_input_buffer); + + memcpy(&s_comm_packet_buffer, raw_input_buffer, sizeof(comm_packet_t)); + + // HAL_GPIO_TogglePin(LED_DEBUG_GPIO_Port, LED_DEBUG_Pin); // Feedback visual pode ir para o main ou callback + + // printf("Comm Pacote Recebido! Tipo: %d, Seq: %d\r\n", + // s_comm_packet_buffer.header.main_type, + // s_comm_packet_buffer.header.seq_number); + + switch (s_comm_packet_buffer.header.main_type) { + case MAIN_PACKET_TYPE_SSL_MESSAGE: + if (s_ssl_handler != nullptr) { // Alterado de NULL para nullptr + s_ssl_handler(&s_comm_packet_buffer.payload_u.ssl_msg, + s_comm_packet_buffer.payload_u.ssl_msg.robot_id, // Passando o ID do payload + s_comm_packet_buffer.header.seq_number); + } + break; + + case MAIN_PACKET_TYPE_VSSS_MESSAGE: + if (s_vsss_handler != nullptr) { // Alterado de NULL para nullptr + s_vsss_handler(&s_comm_packet_buffer.payload_u.vsss_msg, + s_comm_packet_buffer.payload_u.vsss_msg.robot_id, // Passando o ID do payload + s_comm_packet_buffer.header.seq_number); + } + break; + + case MAIN_PACKET_TYPE_DEBUG_TEXT: + if (s_debug_text_handler != nullptr) { // Alterado de NULL para nullptr + char temp_text[DEBUG_TEXT_MAX_LEN + 1]; + memcpy(temp_text, s_comm_packet_buffer.payload_u.debug_text.text, DEBUG_TEXT_MAX_LEN); + temp_text[DEBUG_TEXT_MAX_LEN] = '\0'; + s_debug_text_handler(temp_text, s_comm_packet_buffer.header.seq_number); + } + break; + + default: + printf("Comm: Tipo de pacote principal desconhecido: %d\r\n", s_comm_packet_buffer.header.main_type); + break; + } + } +} \ No newline at end of file diff --git a/COMM.h b/COMM.h deleted file mode 100644 index aa43023..0000000 --- a/COMM.h +++ /dev/null @@ -1,60 +0,0 @@ - -#ifndef COMM_H_ -#define COMM_H_ - -#include -#include -#include -#include -#include "COMM_PACKETS.h" - -typedef enum { - COMM_ROBOT_TYPE_UNDEFINED, - COMM_ROBOT_TYPE_SSL, - COMM_ROBOT_TYPE_VSSS -} comm_robot_type_t; - -typedef void (*comm_ssl_command_handler_t)(const ssl_command_payload_t* cmd_data, uint8_t robot_id, uint8_t seq_num); -typedef void (*comm_vsss_command_handler_t)(const vsss_command_payload_t* cmd_data, uint8_t robot_id, uint8_t seq_num); -typedef void (*comm_ssl_telemetry_handler_t)(const ssl_telemetry_payload_t* tel_data, uint8_t robot_id, uint8_t seq_num); -typedef void (*comm_vsss_telemetry_handler_t)(const vsss_telemetry_payload_t* tel_data, uint8_t robot_id, uint8_t seq_num); -typedef void (*comm_debug_text_handler_t)(const char* text_data, uint8_t seq_num); - - -// -------------------- Funções da Interface do Módulo -------------------- - -/** - * @brief Inicializa o módulo de comunicação P2P e o NRF24L01+. - * @param robot_type O tipo de robô principal associado a esta instância. - * @param channel Canal RF a ser usado (0-125). - * @param my_listening_address Endereço de 5 bytes no qual este nó irá escutar por pacotes. - * @param peer_target_address Endereço de 5 bytes do nó parceiro para o qual este nó irá transmitir. - * @return true se a inicialização foi bem-sucedida, false caso contrário. - */ -bool Comm_Init_P2P(comm_robot_type_t robot_type, - uint8_t channel, - const uint8_t my_listening_address[5], - const uint8_t peer_target_address[5]); - -// --- Funções de Envio --- -int16_t Comm_Send_SSL_Command(const ssl_command_payload_t* cmd_payload_data); -int16_t Comm_Send_VSSS_Command(const vsss_command_payload_t* cmd_payload_data); -int16_t Comm_Send_SSL_Telemetry(const ssl_telemetry_payload_t* tel_payload_data); -int16_t Comm_Send_VSSS_Telemetry(const vsss_telemetry_payload_t* tel_payload_data); -int16_t Comm_Send_DebugText_Message(const char* text_payload); - - -// --- Funções de Registro de Callback --- -void Comm_Register_SSL_CommandHandler(comm_ssl_command_handler_t callback); -void Comm_Register_VSSS_CommandHandler(comm_vsss_command_handler_t callback); -void Comm_Register_SSL_TelemetryHandler(comm_ssl_telemetry_handler_t callback); -void Comm_Register_VSSS_TelemetryHandler(comm_vsss_telemetry_handler_t callback); -void Comm_Register_DebugText_Packet_Handler(comm_debug_text_handler_t callback); - -/** - * @brief Processa mensagens NRF24L01+ recebidas. - * Esta função deve ser chamada periodicamente no loop principal para verificar por pacotes. - */ -void Comm_ProcessReceivedPackets(void); - -#endif /* COMM_H_ */ \ No newline at end of file diff --git a/COMM.hpp b/COMM.hpp new file mode 100644 index 0000000..353b007 --- /dev/null +++ b/COMM.hpp @@ -0,0 +1,116 @@ +// Comm/COMM.hpp +#ifndef COMM_HPP_ // Alterada guarda de inclusão +#define COMM_HPP_ // Alterada guarda de inclusão + +#include // Atualizado caminho de inclusão +#include // Atualizado caminho de inclusão +#include +#include +#include +#include + +// Melhoria C++ opcional: `enum class comm_robot_type_t { ... };` +typedef enum { + COMM_ROBOT_TYPE_UNDEFINED, + COMM_ROBOT_TYPE_SSL, + COMM_ROBOT_TYPE_VSSS +} comm_robot_type_t; + +// Melhoria C++ opcional: `enum class comm_node_mode_t { ... };` +typedef enum { + COMM_NODE_MODE_TRANSMITTER, + COMM_NODE_MODE_RECEIVER +} comm_node_mode_t; + +// Tipos de Ponteiros de Função para Callbacks de Recepção +typedef void (*comm_ssl_packet_handler_t)(const ssl_payload_t* ssl_data, uint8_t robot_id_from_payload, uint8_t seq_num); +typedef void (*comm_vsss_packet_handler_t)(const vsss_payload_t* vsss_data, uint8_t robot_id_from_payload, uint8_t seq_num); +typedef void (*comm_debug_text_handler_t)(const char* text_data, uint8_t seq_num); + +// -------------------- Funções de Interface do Módulo de Comunicação -------------------- + +#ifdef __cplusplus // Adicionado bloco extern "C" +extern "C" { +#endif + +/** + * @brief Inicializa o módulo de comunicação e o NRF24L01+. + * + * @param robot_type O tipo de robô principal para esta instância (COMM_ROBOT_TYPE_SSL ou COMM_ROBOT_TYPE_VSSS). + * Pode influenciar filtros ou lógicas específicas no futuro. + * @param node_mode Define se o nó operará como COMM_NODE_MODE_TRANSMITTER ou COMM_NODE_MODE_RECEIVER. + * @param channel Canal RF a ser usado (0-125). + * @param tx_address Endereço de 5 bytes para transmissão (se transmissor) ou para o Pipe 0 (se receptor, para ACKs). + * @param rx_pipe1_address Endereço de 5 bytes para o Pipe 1 de recepção (se receptor). + * @param rx_pipe2_lsb LSB para o Pipe 2 de recepção (se receptor, opcional, pode ser 0 se não usado). + * @return true se a inicialização foi bem-sucedida, false caso contrário. + */ +bool Comm_Init(comm_robot_type_t robot_type, + comm_node_mode_t node_mode, + uint8_t channel, + uint8_t* nrf_tx_address, + uint8_t* nrf_rx_pipe1_address, + uint8_t nrf_rx_pipe2_lsb); // Adicionado nrf_rx_pipe2_lsb + +// --- Funções para Transmissor --- + +/** + * @brief Envia uma mensagem de controle para um robô SSL. + * Apenas funciona se Comm_Init foi chamado com COMM_NODE_MODE_TRANSMITTER. + * @param ssl_payload_data Ponteiro para a estrutura de payload SSL a ser enviada. + * @return true se a transmissão foi enfileirada/iniciada com sucesso (ACK pendente), false caso contrário. + */ +bool Comm_Send_SSL_Message(const ssl_payload_t* ssl_payload_data); + +/** + * @brief Envia uma mensagem de controle para um robô VSSS. + * Apenas funciona se Comm_Init foi chamado com COMM_NODE_MODE_TRANSMITTER. + * @param vsss_payload_data Ponteiro para a estrutura de payload VSSS a ser enviada. + * @return true se a transmissão foi enfileirada/iniciada com sucesso (ACK pendente), false caso contrário. + */ +bool Comm_Send_VSSS_Message(const vsss_payload_t* vsss_payload_data); + +/** + * @brief Envia uma mensagem de texto para debug. + * Apenas funciona se Comm_Init foi chamado com COMM_NODE_MODE_TRANSMITTER. + * @param text_payload String de texto a ser enviada. + * @return true se a transmissão foi enfileirada/iniciada com sucesso, false caso contrário. + */ +bool Comm_Send_DebugText_Message(const char* text_payload); + + +// --- Funções para Receptor --- + +/** + * @brief Registra uma função de callback para ser chamada quando um pacote SSL é recebido. + * Apenas relevante se Comm_Init foi chamado com COMM_NODE_MODE_RECEIVER. + * @param callback Ponteiro para a função handler. Passe NULL para desregistrar. + */ +void Comm_Register_SSL_Packet_Handler(comm_ssl_packet_handler_t callback); + +/** + * @brief Registra uma função de callback para ser chamada quando um pacote VSSS é recebido. + * Apenas relevante se Comm_Init foi chamado com COMM_NODE_MODE_RECEIVER. + * @param callback Ponteiro para a função handler. Passe NULL para desregistrar. + */ +void Comm_Register_VSSS_Packet_Handler(comm_vsss_packet_handler_t callback); + +/** + * @brief Registra uma função de callback para ser chamada quando um pacote de Debug Text é recebido. + * Apenas relevante se Comm_Init foi chamado com COMM_NODE_MODE_RECEIVER. + * @param callback Ponteiro para a função handler. Passe NULL para desregistrar. + */ +void Comm_Register_DebugText_Packet_Handler(comm_debug_text_handler_t callback); + +/** + * @brief Processa mensagens NRF24L01+ recebidas. + * Esta função deve ser chamada periodicamente no loop principal do receptor. + * Ela verifica se há dados, os recebe, interpreta o tipo e chama o callback apropriado. + */ +void Comm_ProcessReceivedPackets(void); + +#ifdef __cplusplus +} +#endif + +#endif /* COMM_HPP_ */ \ No newline at end of file diff --git a/COMM_PACKETS.c b/COMM_PACKETS.c deleted file mode 100644 index 1862dc8..0000000 --- a/COMM_PACKETS.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include - - -void Comm_Packets_Create_VSSSCommand(comm_packet_t* packet_buffer, - uint8_t seq_num, - const vsss_command_payload_t* cmd_payload) -{ - if (packet_buffer == NULL || cmd_payload == NULL) { - return; - } - memset(packet_buffer, 0, sizeof(comm_packet_t)); - - packet_buffer->header.main_type = MAIN_PACKET_TYPE_VSSS_COMMAND; - packet_buffer->header.seq_number = seq_num; - - memcpy(&packet_buffer->payload_u.vsss_cmd, cmd_payload, sizeof(vsss_command_payload_t)); -} - -void Comm_Packets_Create_SSLCommand(comm_packet_t* packet_buffer, - uint8_t seq_num, - const ssl_command_payload_t* cmd_payload) -{ - if (packet_buffer == NULL || cmd_payload == NULL) { - return; - } - memset(packet_buffer, 0, sizeof(comm_packet_t)); - - packet_buffer->header.main_type = MAIN_PACKET_TYPE_SSL_COMMAND; - packet_buffer->header.seq_number = seq_num; - - memcpy(&packet_buffer->payload_u.ssl_cmd, cmd_payload, sizeof(ssl_command_payload_t)); -} - -void Comm_Packets_Create_DebugText(comm_packet_t* packet_buffer, - uint8_t seq_num, - const char* text_payload) -{ - if (packet_buffer == NULL || text_payload == NULL) { - return; - } - memset(packet_buffer, 0, sizeof(comm_packet_t)); - - packet_buffer->header.main_type = MAIN_PACKET_TYPE_DEBUG_TEXT; - packet_buffer->header.seq_number = seq_num; - - strncpy(packet_buffer->payload_u.debug_text.text, text_payload, DEBUG_TEXT_MAX_LEN -1); - packet_buffer->payload_u.debug_text.text[DEBUG_TEXT_MAX_LEN - 1] = '\0'; -} - - -void Comm_Packets_Create_VSSTelemetry(comm_packet_t* packet_buffer, - uint8_t seq_num, - const vsss_telemetry_payload_t* tel_payload) -{ - if (packet_buffer == NULL || tel_payload == NULL) { - return; - } - memset(packet_buffer, 0, sizeof(comm_packet_t)); - - packet_buffer->header.main_type = MAIN_PACKET_TYPE_VSSS_TELEMETRY; - packet_buffer->header.seq_number = seq_num; - - memcpy(&packet_buffer->payload_u.vsss_tel, tel_payload, sizeof(vsss_telemetry_payload_t)); -} - -void Comm_Packets_Create_SSLTelemetry(comm_packet_t* packet_buffer, - uint8_t seq_num, - const ssl_telemetry_payload_t* tel_payload) -{ - if (packet_buffer == NULL || tel_payload == NULL) { - return; - } - memset(packet_buffer, 0, sizeof(comm_packet_t)); - - packet_buffer->header.main_type = MAIN_PACKET_TYPE_SSL_TELEMETRY; - packet_buffer->header.seq_number = seq_num; - - memcpy(&packet_buffer->payload_u.ssl_tel, tel_payload, sizeof(ssl_telemetry_payload_t)); -} \ No newline at end of file diff --git a/COMM_PACKETS.cpp b/COMM_PACKETS.cpp new file mode 100644 index 0000000..8e36618 --- /dev/null +++ b/COMM_PACKETS.cpp @@ -0,0 +1,49 @@ +// Comm/COMM_PACKETS.cpp +#include // Atualizado caminho de inclusão +#include + +void Comm_Packets_Create_VSSSMessage(comm_packet_t* packet_buffer, + uint8_t seq_num, + const vsss_payload_t* vsss_payload_data) +{ + if (packet_buffer == nullptr || vsss_payload_data == nullptr) { // Opcional: usar nullptr em vez de NULL + return; + } + memset(packet_buffer, 0, sizeof(comm_packet_t)); + + packet_buffer->header.main_type = MAIN_PACKET_TYPE_VSSS_MESSAGE; + packet_buffer->header.seq_number = seq_num; + + memcpy(&packet_buffer->payload_u.vsss_msg, vsss_payload_data, sizeof(vsss_payload_t)); +} + +void Comm_Packets_Create_SSLMessage(comm_packet_t* packet_buffer, + uint8_t seq_num, + const ssl_payload_t* ssl_payload_data) +{ + if (packet_buffer == nullptr || ssl_payload_data == nullptr) { // Opcional: usar nullptr em vez de NULL + return; + } + memset(packet_buffer, 0, sizeof(comm_packet_t)); + + packet_buffer->header.main_type = MAIN_PACKET_TYPE_SSL_MESSAGE; + packet_buffer->header.seq_number = seq_num; + + memcpy(&packet_buffer->payload_u.ssl_msg, ssl_payload_data, sizeof(ssl_payload_t)); +} + +void Comm_Packets_Create_DebugText(comm_packet_t* packet_buffer, + uint8_t seq_num, + const char* text_payload) +{ + if (packet_buffer == nullptr || text_payload == nullptr) { // Opcional: usar nullptr em vez de NULL + return; + } + memset(packet_buffer, 0, sizeof(comm_packet_t)); + + packet_buffer->header.main_type = MAIN_PACKET_TYPE_DEBUG_TEXT; + packet_buffer->header.seq_number = seq_num; + + strncpy(packet_buffer->payload_u.debug_text.text, text_payload, DEBUG_TEXT_MAX_LEN -1); + packet_buffer->payload_u.debug_text.text[DEBUG_TEXT_MAX_LEN - 1] = '\0'; +} \ No newline at end of file diff --git a/COMM_PACKETS.h b/COMM_PACKETS.h deleted file mode 100644 index c3460a7..0000000 --- a/COMM_PACKETS.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef COMM_PACKETS_H_ -#define COMM_PACKETS_H_ - -#include - - -#define NRF_MAX_PACKET_SIZE 32 - -typedef enum { - MAIN_PACKET_TYPE_UNDEFINED = 0, - MAIN_PACKET_TYPE_VSSS_COMMAND, - MAIN_PACKET_TYPE_SSL_COMMAND, - MAIN_PACKET_TYPE_VSSS_TELEMETRY, - MAIN_PACKET_TYPE_SSL_TELEMETRY, - MAIN_PACKET_TYPE_DEBUG_TEXT, -} nrf_main_packet_type_t; - - -typedef enum { - VSSS_CMD_SUBTYPE_UNDEFINED = 0, - VSSS_CMD_SET_MOTOR_SPEEDS, - VSSS_CMD_RESERVED, -} vsss_command_subtype_t; - -typedef enum { - SSL_CMD_SUBTYPE_UNDEFINED = 0, - SSL_CMD_SET_VELOCITIES, - SSL_CMD_ACTION_CONTROL, - SSL_CMD_REFEREE, -} ssl_command_subtype_t; - - -typedef enum { - VSSS_TELEMETRY_SUBTYPE_STANDARD = 0, -} vsss_telemetry_subtype_t; - -typedef enum { - SSL_TELEMETRY_SUBTYPE_STANDARD = 0, -} ssl_telemetry_subtype_t; - - - -typedef struct __attribute__((packed)) { - vsss_command_subtype_t command_subtype; - uint8_t robot_id; - uint16_t motor1_value; - uint16_t motor2_value; - uint8_t is_pwm_flag; -} vsss_command_payload_t; - -typedef struct __attribute__((packed)) { - ssl_command_subtype_t command_subtype; - uint8_t robot_id; - int16_t vx; - int16_t vy; - int16_t vw; - uint8_t referee_command; - uint8_t kick_front; - uint8_t kick_chip; - uint8_t capacitor_charge; - uint8_t kick_strength; - uint8_t dribbler_on; - uint8_t dribbler_speed; - uint8_t movement_locked; - uint8_t critical_move_turbo; -} ssl_command_payload_t; - - - -typedef struct __attribute__((packed)) { - uint8_t telemetry_subtype : 4; - uint8_t robot_id : 4; - int32_t motor1_feedback : 18; - int32_t motor2_feedback : 18; - uint8_t battery_level : 8; - uint8_t reserved_bits : 4; - uint8_t command_seq_num_ack; -} vsss_telemetry_payload_t; - -typedef struct __attribute__((packed)) { - uint8_t telemetry_subtype : 4; - uint8_t robot_id : 4; - uint16_t current_m1 : 12; - uint16_t current_m2 : 12; - uint16_t current_m3 : 12; - uint16_t current_m4 : 12; - int16_t dribbler_speed_feedback : 15; - uint8_t kick_load_status : 8; - uint8_t ball_detected : 1; - uint8_t battery_level : 8; - int16_t speed_m1_feedback : 16; - int16_t speed_m2_feedback : 16; - int16_t speed_m3_feedback : 16; - int16_t speed_m4_feedback : 16; - uint8_t telemetry_pckt_count : 8; - uint8_t command_seq_num_ack; -} ssl_telemetry_payload_t; - - -// Payload de Debug -#define DEBUG_TEXT_MAX_LEN (NRF_MAX_PACKET_SIZE - 2) -typedef struct __attribute__((packed)) { - char text[DEBUG_TEXT_MAX_LEN]; -} debug_text_payload_t; - - -typedef struct __attribute__((packed)) { - nrf_main_packet_type_t main_type; - uint8_t seq_number; -} comm_packet_header_t; - -#define COMM_USER_PAYLOAD_MAX_SIZE (NRF_MAX_PACKET_SIZE - sizeof(comm_packet_header_t)) - -typedef struct __attribute__((packed)) { - comm_packet_header_t header; - union { - uint8_t raw_payload[COMM_USER_PAYLOAD_MAX_SIZE]; - vsss_command_payload_t vsss_cmd; - ssl_command_payload_t ssl_cmd; - vsss_telemetry_payload_t vsss_tel; - ssl_telemetry_payload_t ssl_tel; - debug_text_payload_t debug_text; - } payload_u; -} comm_packet_t; - - - -void Comm_Packets_Create_VSSSCommand(comm_packet_t* packet_buffer, uint8_t seq_num, const vsss_command_payload_t* cmd_payload); -void Comm_Packets_Create_SSLCommand(comm_packet_t* packet_buffer, uint8_t seq_num, const ssl_command_payload_t* cmd_payload); -void Comm_Packets_Create_VSSTelemetry(comm_packet_t* packet_buffer, uint8_t seq_num, const vsss_telemetry_payload_t* tel_payload); -void Comm_Packets_Create_SSLTelemetry(comm_packet_t* packet_buffer, uint8_t seq_num, const ssl_telemetry_payload_t* tel_payload); -void Comm_Packets_Create_DebugText(comm_packet_t* packet_buffer, uint8_t seq_num, const char* text_payload); - - -#endif /* COMM_PACKETS_H_ */ \ No newline at end of file diff --git a/COMM_PACKETS.hpp b/COMM_PACKETS.hpp new file mode 100644 index 0000000..50d09be --- /dev/null +++ b/COMM_PACKETS.hpp @@ -0,0 +1,116 @@ +// Comm/COMM_PACKETS.hpp +#ifndef COMM_PACKETS_HPP_ // Alterada guarda de inclusão +#define COMM_PACKETS_HPP_ // Alterada guarda de inclusão + +#include +#include + + +#define NRF_MAX_PACKET_SIZE 32 + +// Para portabilidade direta, manteremos `typedef enum`. +// Melhoria C++ opcional: `enum class nrf_main_packet_type_t { ... };` +typedef enum { + MAIN_PACKET_TYPE_UNDEFINED = 0, + MAIN_PACKET_TYPE_VSSS_MESSAGE, + MAIN_PACKET_TYPE_SSL_MESSAGE, + MAIN_PACKET_TYPE_DEBUG_TEXT, + +} nrf_main_packet_type_t; + + +// Melhoria C++ opcional: `enum class vsss_command_subtype_t { ... };` +typedef enum { + VSSS_CMD_SUBTYPE_UNDEFINED = 0, + VSSS_CMD_SET_MOTOR_SPEEDS, + VSSS_CMD_RESEVED_VSSS, + +} vsss_command_subtype_t; + + +// Melhoria C++ opcional: `enum class ssl_command_subtype_t { ... };` +typedef enum { + SSL_CMD_SUBTYPE_UNDEFINED = 0, + SSL_CMD_SET_VELOCITIES, + SSL_CMD_ACTION_CONTROL, + SSL_CMD_REFEREE, +} ssl_command_subtype_t; + +// Melhoria C++ opcional: `struct __attribute__((packed)) vsss_payload_t { ... };` +typedef struct __attribute__((packed)) { + vsss_command_subtype_t command_subtype; + uint8_t robot_id; // ID do robô (0-255) + uint16_t motor1_value; // Valor para o motor 1 + uint16_t motor2_value; // Valor para o motor 2 + uint8_t is_pwm_flag; // 1 se os valores dos motores são PWM, 0 se RPM +} vsss_payload_t; // Tamanho: 1 + 1 + 2 + 2 + 1 = 7 bytes + +// Melhoria C++ opcional: `struct __attribute__((packed)) ssl_payload_t { ... };` +typedef struct __attribute__((packed)) { + ssl_command_subtype_t command_subtype; // Subtipo do comando SSL + uint8_t robot_id; // ID do robô + int16_t vx; // Velocidade X (mm/s * 10 ou outra escala) + int16_t vy; // Velocidade Y (mm/s * 10 ou outra escala) + int16_t vw; // Velocidade angular (rad/s * 10000 ou outra escala) + uint8_t referee_command; // Comando de jogo (refereeCommand) + uint8_t kick_front; // Chute frontal (0=não, 1=sim) + uint8_t kick_chip; // Chute em arco (0=não, 1=sim) + uint8_t capacitor_charge; // Acionar capacitor (0=não, 1=sim) + uint8_t kick_strength; // Força do chute (0–255 ou escalado) + uint8_t dribbler_on; // Liga dribbler (0=não, 1=sim) + uint8_t dribbler_speed; // Velocidade do dribbler + uint8_t movement_locked; // Proibir movimento (0=não, 1=sim) + uint8_t critical_move_turbo; // Ativar turbo (0=não, 1=sim) +} ssl_payload_t; // Tamanho: 1+1+2+2+2+1 + 1+1+1+1+1+1+1+1 = 17 bytes + + +#define DEBUG_TEXT_MAX_LEN (NRF_MAX_PACKET_SIZE - 2) +// Melhoria C++ opcional: `struct __attribute__((packed)) debug_text_payload_t { ... };` +typedef struct __attribute__((packed)) { + char text[DEBUG_TEXT_MAX_LEN]; +} debug_text_payload_t; + +// Melhoria C++ opcional: `struct __attribute__((packed)) comm_packet_header_t { ... };` +typedef struct __attribute__((packed)) { + nrf_main_packet_type_t main_type; + uint8_t seq_number; +} comm_packet_header_t; + +#define COMM_USER_PAYLOAD_MAX_SIZE (NRF_MAX_PACKET_SIZE - sizeof(comm_packet_header_t)) + +// Melhoria C++ opcional: `struct __attribute__((packed)) comm_packet_t { ... };` +typedef struct __attribute__((packed)) { + comm_packet_header_t header; + + union { + uint8_t raw_payload[COMM_USER_PAYLOAD_MAX_SIZE]; + vsss_payload_t vsss_msg; + ssl_payload_t ssl_msg; + debug_text_payload_t debug_text; + } payload_u; + +} comm_packet_t; + + +#ifdef __cplusplus // Adicionado bloco extern "C" +extern "C" { +#endif + +void Comm_Packets_Create_VSSSMessage(comm_packet_t* packet_buffer, + uint8_t seq_num, + const vsss_payload_t* vsss_payload_data); + + +void Comm_Packets_Create_SSLMessage(comm_packet_t* packet_buffer, + uint8_t seq_num, + const ssl_payload_t* ssl_payload_data); + +void Comm_Packets_Create_DebugText(comm_packet_t* packet_buffer, + uint8_t seq_num, + const char* text_payload); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/NRF24_CORE.c b/NRF24_CORE.cpp similarity index 97% rename from NRF24_CORE.c rename to NRF24_CORE.cpp index 87bb713..5dc6ea7 100644 --- a/NRF24_CORE.c +++ b/NRF24_CORE.cpp @@ -1,5 +1,6 @@ -#include -#include +// Comm/NRF24_CORE.cpp +#include // Atualizado caminho de inclusão +#include // Atualizado caminho de inclusão #include void nrf24_WriteReg(uint8_t Reg, uint8_t Data) { @@ -289,4 +290,4 @@ void NRF24_ReadAll(uint8_t *data) { *(data + j++) = nrf24_ReadReg(DYNPD); *(data + j++) = nrf24_ReadReg(FEATURE); -} +} \ No newline at end of file diff --git a/NRF24_CORE.h b/NRF24_CORE.hpp similarity index 71% rename from NRF24_CORE.h rename to NRF24_CORE.hpp index 58b1c21..bfcba4f 100644 --- a/NRF24_CORE.h +++ b/NRF24_CORE.hpp @@ -1,10 +1,15 @@ -#ifndef NRF24_CORE_H_ -#define NRF24_CORE_H_ +// Comm/NRF24_CORE.hpp +#ifndef NRF24_CORE_HPP_ // Alterada guarda de inclusão +#define NRF24_CORE_HPP_ // Alterada guarda de inclusão -#include +#include // Atualizado caminho de inclusão #include +#ifdef __cplusplus // Adicionado bloco extern "C" +extern "C" { +#endif + void nrf24_WriteReg(uint8_t Reg, uint8_t Data); void nrf24_WriteRegMulti(uint8_t Reg, uint8_t *data, uint8_t size); uint8_t nrf24_ReadReg(uint8_t Reg); @@ -30,4 +35,8 @@ void NRF24_Receive(uint8_t *data); void NRF24_ReadAll(uint8_t *data); +#ifdef __cplusplus +} #endif + +#endif \ No newline at end of file diff --git a/NRF24_DEF.h b/NRF24_DEF.hpp similarity index 91% rename from NRF24_DEF.h rename to NRF24_DEF.hpp index 42229c2..d285555 100644 --- a/NRF24_DEF.h +++ b/NRF24_DEF.hpp @@ -1,5 +1,6 @@ -#ifndef NRF24_DEF_H_ -#define NRF24_DEF_H_ +// Comm/NRF24_DEF.hpp +#ifndef NRF24_DEF_HPP_ // Alterada guarda de inclusão +#define NRF24_DEF_HPP_ // Alterada guarda de inclusão #include "stm32f4xx_hal.h" @@ -68,4 +69,4 @@ extern SPI_HandleTypeDef hspi1; #define REUSE_TX_PL 0xE3 #define NOP 0xFF -#endif +#endif \ No newline at end of file diff --git a/NRF24_HAL.c b/NRF24_HAL.cpp similarity index 90% rename from NRF24_HAL.c rename to NRF24_HAL.cpp index d87afd5..e6ea6c5 100644 --- a/NRF24_HAL.c +++ b/NRF24_HAL.cpp @@ -1,4 +1,5 @@ -#include +// Comm/NRF24_HAL.cpp +#include // Atualizado caminho de inclusão void NRF24_HAL_CE_Enable(void) { HAL_GPIO_WritePin(NRF24_CE_PORT, NRF24_CE_PIN, GPIO_PIN_SET); @@ -30,4 +31,4 @@ void NRF24_HAL_Delay(uint32_t milliseconds) { uint32_t NRF24_HAL_GetTick(void) { return HAL_GetTick(); -} +} \ No newline at end of file diff --git a/NRF24_HAL.h b/NRF24_HAL.hpp similarity index 57% rename from NRF24_HAL.h rename to NRF24_HAL.hpp index 9895cc2..ec5cde1 100644 --- a/NRF24_HAL.h +++ b/NRF24_HAL.hpp @@ -1,7 +1,12 @@ -#ifndef NRF24_HAL_H_ -#define NRF24_HAL_H_ +// Comm/NRF24_HAL.hpp +#ifndef NRF24_HAL_HPP_ // Alterada guarda de inclusão +#define NRF24_HAL_HPP_ // Alterada guarda de inclusão -#include +#include // Atualizado caminho de inclusão + +#ifdef __cplusplus // Adicionado bloco extern "C" +extern "C" { +#endif void NRF24_HAL_CE_Enable(void); void NRF24_HAL_CE_Disable(void); @@ -14,4 +19,8 @@ HAL_StatusTypeDef NRF24_HAL_SPI_Receive(uint8_t *pData, uint16_t Size, uint32_t void NRF24_HAL_Delay(uint32_t milliseconds); uint32_t NRF24_HAL_GetTick(void); +#ifdef __cplusplus +} #endif + +#endif \ No newline at end of file diff --git a/README.md b/README.md index f83f7f4..a5feff6 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ -# Biblioteca NRF24L01+ para STM32 com Sistema de Pacotes Customizado para `SSL` e `VSSS` +# Biblioteca NRF24L01+ para STM32 com Sistema de Pacotes Customizado para `SSL` e `VSSS` (Portado para C++) -Esta biblioteca fornece uma interface para comunicação sem fio utilizando o módulo NRF24L01+ com microcontroladores STM32, utilizando a camada HAL da ST. Inclui um sistema para gerenciamento de pacotes customizados, permitindo a transmissão de diferentes tipos de dados estruturados, como comandos para robôs VSSS e SSL. +Esta biblioteca fornece uma interface para comunicação sem fio utilizando o módulo NRF24L01+ com microcontroladores STM32, utilizando a camada HAL da ST. Inclui um sistema para gerenciamento de pacotes customizados, permitindo a transmissão de diferentes tipos de dados estruturados, como comandos para robôs VSSS e SSL. Esta versão foi portada da linguagem C para C++. ## Visão Geral A biblioteca é modularizada em: -* **Camada de Definições (`NRF24_DEF.h`):** Constantes, definições de pinos, registradores do NRF24L01+. -* **Camada de Abstração de Hardware (`NRF24_HAL.c/h`):** Funções de baixo nível para controle de pinos (CE, CSN) e comunicação SPI, utilizando as funções HAL do STM32. -* **Núcleo do Driver NRF24 (`NRF24_CORE.c/h`):** Lógica principal para operar o NRF24L01+, incluindo inicialização, configuração de modos (TX/RX), envio e recepção de dados. -* **Gerenciamento de Pacotes (`COMM_PACKETS.c/h`):** Definição de estruturas de pacotes, tipos de mensagens e funções auxiliares para criar e interpretar pacotes específicos para diferentes aplicações (ex: VSSS, SSL). +* **Camada de Definições (`NRF24_DEF.hpp`):** Constantes, definições de pinos, registradores do NRF24L01+. +* **Camada de Abstração de Hardware (`NRF24_HAL.cpp/hpp`):** Funções de baixo nível para controle de pinos (CE, CSN) e comunicação SPI, utilizando as funções HAL do STM32. +* **Núcleo do Driver NRF24 (`NRF24_CORE.cpp/hpp`):** Lógica principal para operar o NRF24L01+, incluindo inicialização, configuração de modos (TX/RX), envio e recepção de dados. +* **Gerenciamento de Pacotes (`COMM_PACKETS.cpp/hpp`):** Definição de estruturas de pacotes, tipos de mensagens e funções auxiliares para criar e interpretar pacotes específicos para diferentes aplicações (ex: VSSS, SSL). +* **Interface de Comunicação (`COMM.cpp/hpp`):** Camada de alto nível para inicialização e gerenciamento da comunicação, encapsulando as funcionalidades do NRF24 e dos pacotes. ## Pré-requisitos @@ -23,28 +24,30 @@ A biblioteca é modularizada em: ### Software * Ambiente de desenvolvimento STM32 (ex: STM32CubeIDE) * Bibliotecas STM32 HAL -* Compilador C (gnu11 ou similar) +* Compilador C++ (g++ ou similar) ## Estrutura de Arquivos da Biblioteca Assumindo que os arquivos da biblioteca estão em uma subpasta `Comm` dentro da pasta de includes e fontes do seu projeto (ex: `Core/Inc/Comm/`): -* `Core/Inc/Comm/NRF24_DEF.h`: Definições de hardware, registradores e constantes do NRF24. -* `Core/Inc/Comm/NRF24_HAL.h`: Protótipos para a camada de abstração de hardware. -* `Core/Inc/Comm/NRF24_HAL.c`: Implementações da camada de abstração de hardware. -* `Core/Inc/Comm/NRF24_CORE.h`: Protótipos para o núcleo do driver NRF24. -* `Core/Inc/Comm/NRF24_CORE.c`: Implementações do núcleo do driver NRF24. -* `Core/Inc/Comm/COMM_PACKETS.h`: Definições de tipos de pacotes, subtipos e estruturas de payload. -* `Core/Inc/Comm/COMM_PACKETS.c`: Funções auxiliares para criar pacotes. +* `Core/Inc/Comm/NRF24_DEF.hpp`: Definições de hardware, registradores e constantes do NRF24. +* `Core/Inc/Comm/NRF24_HAL.hpp`: Protótipos para a camada de abstração de hardware. +* `Core/Inc/Comm/NRF24_HAL.cpp`: Implementações da camada de abstração de hardware. +* `Core/Inc/Comm/NRF24_CORE.hpp`: Protótipos para o núcleo do driver NRF24. +* `Core/Inc/Comm/NRF24_CORE.cpp`: Implementações do núcleo do driver NRF24. +* `Core/Inc/Comm/COMM_PACKETS.hpp`: Definições de tipos de pacotes, subtipos e estruturas de payload. +* `Core/Inc/Comm/COMM_PACKETS.cpp`: Funções auxiliares para criar pacotes. +* `Core/Inc/Comm/COMM.hpp`: Protótipos para a interface de comunicação de alto nível. +* `Core/Inc/Comm/COMM.cpp`: Implementações da interface de comunicação de alto nível. ## Configuração -### 1. Configuração de Pinos e SPI (`NRF24_DEF.h`) +### 1. Configuração de Pinos e SPI (`NRF24_DEF.hpp`) -Edite o arquivo `NRF24_DEF.h` para corresponder à sua configuração de hardware: +Edite o arquivo `NRF24_DEF.hpp` para corresponder à sua configuração de hardware: -```c -// NRF24_DEF.h +```cpp +// NRF24_DEF.hpp // Definições de pinos NRF24 - Adapte conforme sua placa #include "stm32f4xx_hal.h" @@ -55,13 +58,13 @@ Edite o arquivo `NRF24_DEF.h` para corresponder à sua configuração de hardwar #define NRF24_CSN_PORT GPIOB // Porta do pino CSN (ex: GPIOB) #define NRF24_CSN_PIN GPIO_PIN_0 // Pino CSN (ex: GPIO_PIN_0) -// Handle SPI (deve ser o mesmo definido e inicializado em main.c) +// Handle SPI (deve ser o mesmo definido e inicializado em main.cpp) extern SPI_HandleTypeDef hspi1; // Mude hspi1 se seu handle SPI for diferente #define NRF24_SPI &hspi1 ``` -Importante: Assegure-se de que os pinos CE_Pin e CSN_Pin configurados no CubeMX (e definidos em main.h) correspondem aos NRF24_CE_PIN e NRF24_CSN_PIN em NRF24_DEF.h para a respectiva porta. +Importante: Assegure-se de que os pinos CE_Pin e CSN_Pin configurados no CubeMX (e definidos em main.h) correspondem aos NRF24_CE_PIN e NRF24_CSN_PIN em NRF24_DEF.hpp para a respectiva porta. -### **2. Definição de Pacotes de Comunicação** (`COMM_PACKETS.h`) +### **2. Definição de Pacotes de Comunicação** (`COMM_PACKETS.hpp`) Este arquivo é crucial para definir a estrutura dos seus dados. @@ -71,9 +74,9 @@ Este arquivo é crucial para definir a estrutura dos seus dados. Crie enums como `vsss_command_subtype_t` e `ssl_command_subtype_t` para detalhar os comandos específicos dentro de cada tipo principal de pacote. -```c +```cpp -// Em COMM_PACKETS.h +// Em COMM_PACKETS.hpp typedef enum { VSSS_CMD_SUBTYPE_UNDEFINED = 0, VSSS_CMD_SET_MOTOR_SPEEDS, @@ -93,141 +96,91 @@ typedef enum { Define o cabeçalho comum (tipo principal, número de sequência). * `comm_packet_t`: A estrutura final do pacote de 32 bytes, com o cabeçalho e uma union para os diferentes payloads. -### **3. Seleção de Nó em `main.c` (DEPRECATED)** - -No topo do seu `main.c` (dentro de `/* USER CODE BEGIN 0 */`), defina qual modo o dispositivo operará: - -```c - -// Em main.c -// Defina UM dos dois para cada placa: -#define TRANSMITTER_NODE 1 -// #define RECEIVER_NODE 1 -``` - - -## Como Utilizar (`API`) (DEPRECATED) +## Como Utilizar (`API`) ### **1. Inclusão de Headers** -No seu `main.c` ou em outros arquivos que utilizarão a biblioteca: +No seu `main.cpp` ou em outros arquivos que utilizarão a biblioteca: -```c -#include "Comm/NRF24_CORE.h" -#include "Comm/COMM_PACKETS.h" +```cpp +#include "Comm/COMM.hpp" ``` ### **2. Inicialização do Módulo NRF24** -```c -// Em main.c, dentro de /* USER CODE BEGIN 2 */ -printf("Inicializando NRF24L01+...\r\n"); -NRF24_Init(); -``` +Agora, a inicialização é feita através da classe `Comm`: -### **3. Configuração do Modo de Operação** - -Também em /* USER CODE BEGIN 2 */, configure o modo conforme o nó: +```cpp +// Em main.cpp, dentro de /* USER CODE BEGIN 2 */ +printf("Inicializando NRF24L01+...\r\n"); -```c -// Variáveis de endereço e canal (definidas em /* USER CODE BEGIN 0 */) -// extern uint8_t nrf_tx_address[5]; -// extern uint8_t nrf_rx_pipe1_address[5]; -// extern uint8_t NRF_COM_CHANNEL; +// Instancie a classe Comm +Comm myComm; -#if defined(TRANSMITTER_NODE) && !defined(RECEIVER_NODE) - printf("Configurado como TRANSMISSOR\r\n"); - NRF24_TxMode(nrf_tx_address, NRF_COM_CHANNEL); -#elif defined(RECEIVER_NODE) && !defined(TRANSMITTER_NODE) - printf("Configurado como RECEPTOR\r\n"); - NRF24_RxMode(nrf_rx_pipe1_address, nrf_rx_pipe2_lsb, NRF_COM_CHANNEL); // nrf_rx_pipe2_lsb é opcional -#endif +// Configure e inicialize a comunicação +// Os parâmetros são os mesmos da versão anterior, mas agora passados para o método Init +if (!myComm.Init(COMM_ROBOT_TYPE_SSL, + COMM_NODE_MODE_TRANSMITTER, + NRF_CHANNEL_MAIN, + NRF_TX_ADDRESS, + NRF_RX_P1_ADDRESS, + 0 )) { + printf("Falha ao inicializar módulo de comunicação!\r\n"); + Error_Handler(); +} +printf("Módulo COMM inicializado como Transmissor SSL.\r\n"); ``` +### **3. Trabalhando com Pacotes (`COMM_PACKETS.hpp` e `COMM_PACKETS.cpp`)** -### **4. Trabalhando com Pacotes (`COMM_PACKETS.h` e `COMM_PACKETS.c`)** - -As funções em COMM_PACKETS.c ajudam a criar pacotes formatados. +As funções em COMM_PACKETS.cpp ajudam a criar pacotes formatados. A criação de pacotes pode ser feita diretamente ou através dos métodos da classe `Comm`. * `Comm_Packets_Create_VSSSMessage(comm_packet_t* packet_buffer, uint8_t seq_num, const vsss_payload_t* vsss_payload_data);` * `Comm_Packets_Create_SSLMessage(comm_packet_t* packet_buffer, uint8_t seq_num, const ssl_payload_t* ssl_payload_data);` * `Comm_Packets_Create_DebugText(comm_packet_t* packet_buffer, uint8_t seq_num, const char* text_payload);` -### **5. Enviando Dados (Exemplo Transmissor) (DEPRECATED)** +### **4. Enviando Dados (Exemplo Transmissor)** No loop principal do transmissor (`/* USER CODE BEGIN 3 */`): -```c -// Em main.c (bloco TRANSMITTER_NODE) -static comm_packet_t nrf_packet_buffer; // Declarada global estática em PV -static uint8_t packet_seq_counter = 0; // Declarada global estática em PV - -ssl_payload_t ssl_command_data; // Ou vsss_payload_t +```cpp +// Em main.cpp (bloco TRANSMITTER_NODE) +ssl_payload_t ssl_command_data; // Preencher ssl_command_data ou vsss_data ssl_command_data.command_subtype = SSL_CMD_SET_VELOCITIES; ssl_command_data.robot_id = 1; -ssl_command_data.vx = 100; +ssl_command_data.vx = (int16_t)(100 + (local_packet_seq_counter % 10) * 5); // ... preencher o resto dos campos ... -// Criar o pacote completo -Comm_Packets_Create_SSLMessage(&nrf_packet_buffer, packet_seq_counter++, &ssl_command_data); - -// Transmitir -if (NRF24_Transmit((uint8_t *)&nrf_packet_buffer, sizeof(comm_packet_t))) { - printf("Pacote SSL enviado! Seq: %d\r\n", nrf_packet_buffer.header.seq_number); - HAL_GPIO_TogglePin(LED_DEBUG_GPIO_Port, LED_DEBUG_Pin); +// Transmitir usando o método da instância Comm +if (myComm.Send_SSL_Message(&ssl_command_data)) { + printf("Main: Pacote SSL (ID:%d, Vx:%d) enviado.\r\n", + ssl_command_data.robot_id, ssl_command_data.vx); + HAL_GPIO_TogglePin(LED_DEBUG_GPIO_Port, LED_DEBUG_Pin); } else { - printf("Falha ao enviar pacote SSL.\r\n"); + printf("Main: Falha ao enviar pacote SSL pela camada Comm.\r\n"); } HAL_Delay(100); // Intervalo entre envios ``` -### **6. Recebendo Dados (Exemplo Receptor) (DEPRECATED)** +### **5. Recebendo Dados (Exemplo Receptor)** No loop principal do receptor (`/* USER CODE BEGIN 3 */`): -```c - -// Em main.c (bloco RECEIVER_NODE) -static comm_packet_t nrf_packet_buffer; // Declarada global estática em PV -uint8_t raw_nrf_input_buffer[NRF_MAX_PACKET_SIZE]; - -if (isDataAvailable(1)) { // Verifica dados no Pipe 1 - NRF24_Receive(raw_nrf_input_buffer); // Lê 32 bytes brutos - - // Copia para a estrutura de pacote para facilitar o acesso - memcpy(&nrf_packet_buffer, raw_nrf_input_buffer, sizeof(comm_packet_t)); - - HAL_GPIO_TogglePin(LED_DEBUG_GPIO_Port, LED_DEBUG_Pin); // Feedback visual - printf("Pacote Recebido! Tipo: %d, Seq: %d\r\n", - nrf_packet_buffer.header.main_type, - nrf_packet_buffer.header.seq_number); - - switch (nrf_packet_buffer.header.main_type) { - case MAIN_PACKET_TYPE_SSL_MESSAGE: - { - ssl_payload_t* ssl_data = &nrf_packet_buffer.payload_u.ssl_msg; - printf(" SSL: ID=%d, Subtipo=%d, Vx=%d\r\n", - ssl_data->robot_id, ssl_data->command_subtype, ssl_data->vx); - // Processar dados SSL ... - break; - } - case MAIN_PACKET_TYPE_VSSS_MESSAGE: - { - vsss_payload_t* vsss_data = &nrf_packet_buffer.payload_u.vsss_msg; - printf(" VSSS: ID=%d, Subtipo=%d, M1=%d\r\n", - vsss_data->robot_id, vsss_data->command_subtype, vsss_data->motor1_value); - // Processar dados VSSS ... - break; - } - // Outros cases ... - default: - printf(" Tipo de pacote desconhecido: %d\r\n", nrf_packet_buffer.header.main_type); - break; - } -} -HAL_Delay(10); +```cpp + +// Em main.cpp (bloco RECEIVER_NODE) +// As funções de callback agora são registradas na instância da classe Comm + +// Exemplo de registro de callbacks (deve ser feito após a inicialização da Comm) +myComm.Register_SSL_Packet_Handler(App_HandleSSLData); +myComm.Register_VSSS_Packet_Handler(App_HandleVSSSData); +myComm.Register_DebugText_Packet_Handler(App_HandleDebugText); + +// Processar pacotes recebidos no loop principal +myComm.ProcessReceivedPackets(); +HAL_Delay(1); ``` ### STM32 @@ -237,10 +190,10 @@ HAL_Delay(10); ## Exemplo no Robô `SSL` -### Transmissor (DEPRECATED): -```c +### Transmissor: +```cpp -#include "comm/COMM.h" +#include "comm/COMM.hpp" uint8_t NRF_TX_ADDRESS[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; // Endereço de transmissão uint8_t NRF_RX_P1_ADDRESS[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; // Endereço do Pipe 0 para ACKs no transmissor @@ -265,7 +218,8 @@ int main(void) { printf("\r\n-- Transmissor NRF24 com Camada COMM --\r\n"); - if (!Comm_Init(COMM_ROBOT_TYPE_SSL, + Comm myComm; // Instancia a classe Comm + if (!myComm.Init(COMM_ROBOT_TYPE_SSL, COMM_NODE_MODE_TRANSMITTER, NRF_CHANNEL_MAIN, NRF_TX_ADDRESS, @@ -298,7 +252,7 @@ int main(void) ssl_command_data.critical_move_turbo = 0; - if (Comm_Send_SSL_Message(&ssl_command_data)) { + if (myComm.Send_SSL_Message(&ssl_command_data)) { // Usa o método da instância printf("Main: Pacote SSL (ID:%d, Vx:%d) enviado.\r\n", ssl_command_data.robot_id, ssl_command_data.vx); HAL_GPIO_TogglePin(LED_DEBUG_GPIO_Port, LED_DEBUG_Pin); @@ -310,9 +264,9 @@ int main(void) } } ``` -### Receptor (DEPRECATED): -```c -#include "Comm/COMM.h" +### Receptor: +```cpp +#include "Comm/COMM.hpp" uint8_t NRF_RECEIVER_TX_ADDRESS_FOR_ACKS[5] = {0xD7, 0xD7, 0xD7, 0xD7, 0xD7}; uint8_t NRF_RECEIVER_RX_P1_ADDRESS[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; @@ -331,6 +285,7 @@ PUTCHAR_PROTOTYPE return ch; } +// Funções de callback (podem ser métodos estáticos ou funções globais) void App_HandleSSLData(const ssl_payload_t* ssl_data, uint8_t robot_id, uint8_t seq_num); void App_HandleVSSSData(const vsss_payload_t* vsss_data, uint8_t robot_id, uint8_t seq_num); void App_HandleDebugText(const char* text_data, uint8_t seq_num); @@ -366,7 +321,7 @@ void App_HandleVSSSData(const vsss_payload_t* vsss_data, uint8_t robot_id, uint8 } void App_HandleDebugText(const char* text_data, uint8_t seq_num) { - printf("CALLBACK DEBUG: Seq=%d -> Texto='%s'\r\n", seq_num, text_data); + printf("CALLBACK DEBUG: Seq=%d -> Texto=\'%s\'\r\n", seq_num, text_data); HAL_GPIO_TogglePin(LED_DEBUG_GPIO_Port, LED_DEBUG_Pin); // Pisca LED ao processar } @@ -376,7 +331,8 @@ int main(void) printf("\r\n-- Receptor NRF24 com Camada COMM --\r\n"); - if (!Comm_Init(COMM_ROBOT_TYPE_UNDEFINED, // Este nó é um receptor genérico ou específico + Comm myComm; // Instancia a classe Comm + if (!myComm.Init(COMM_ROBOT_TYPE_UNDEFINED, // Este nó é um receptor genérico ou específico COMM_NODE_MODE_RECEIVER, NRF_COMMON_CHANNEL, NRF_RECEIVER_TX_ADDRESS_FOR_ACKS, // Endereço que o NRF usaria para enviar ACKs (Pipe0) @@ -386,16 +342,30 @@ int main(void) Error_Handler(); } - Comm_Register_SSL_Packet_Handler(App_HandleSSLData); - Comm_Register_VSSS_Packet_Handler(App_HandleVSSSData); - Comm_Register_DebugText_Packet_Handler(App_HandleDebugText); + myComm.Register_SSL_Packet_Handler(App_HandleSSLData); + myComm.Register_VSSS_Packet_Handler(App_HandleVSSSData); + myComm.Register_DebugText_Packet_Handler(App_HandleDebugText); printf("Módulo COMM inicializado como Receptor. Aguardando pacotes...\r\n"); while (1) { - Comm_ProcessReceivedPackets(); + myComm.ProcessReceivedPackets(); // Usa o método da instância HAL_Delay(1); } } ``` + +## Mudanças Realizadas + +As principais mudanças realizadas nesta versão da biblioteca, em comparação com a versão original em C (`CommAntiga`), são: + +1. **Portabilidade para C++**: Todos os arquivos de código-fonte (`.c`) foram convertidos para C++ (`.cpp`) e os arquivos de cabeçalho (`.h`) para `.hpp`. +2. **Orientação a Objetos**: A funcionalidade principal da comunicação, anteriormente exposta como funções globais em C, foi encapsulada em uma classe `Comm` (definida em `COMM.hpp` e implementada em `COMM.cpp`). Isso melhora a modularidade, reusabilidade e organização do código. +3. **Inicialização da Comunicação**: A função `Comm_Init` agora é um método da classe `Comm` (ex: `myComm.Init(...)`). +4. **Envio de Pacotes**: As funções de envio de pacotes (ex: `Comm_Send_SSL_Message`) agora são métodos da classe `Comm` (ex: `myComm.Send_SSL_Message(...)`). +5. **Processamento de Pacotes Recebidos**: A função `Comm_ProcessReceivedPackets` agora é um método da classe `Comm` (ex: `myComm.ProcessReceivedPackets()`). +6. **Registro de Callbacks**: As funções para registrar callbacks (ex: `Comm_Register_SSL_Packet_Handler`) agora são métodos da classe `Comm` (ex: `myComm.Register_SSL_Packet_Handler(...)`). +7. **Remoção de Seções Depreciadas**: As seções marcadas como `(DEPRECATED)` na versão anterior do README, que se referiam a uma API C mais antiga ou a métodos de uso menos recomendados, foram removidas ou atualizadas para refletir a nova abordagem orientada a objetos em C++. + +Essas mudanças visam modernizar a base de código, aproveitando os recursos da programação orientada a objetos em C++ para uma API mais limpa e um design mais robusto.