From 4f395df70f02fc99750dfcc7d365066592399609 Mon Sep 17 00:00:00 2001 From: Roberto Arellano Date: Wed, 21 Aug 2024 11:57:57 -0600 Subject: [PATCH 1/3] refactor: Code split into smaller files --- ModbusApp/Modbus.c | 1149 +---------------- ModbusApp/Modbus.h | 156 +++ ModbusApp/modbus_parser/modbus_parser.c | 185 +++ ModbusApp/modbus_parser/modbus_parser.h | 5 + .../modbus_ring_buffer/modbus_ring_buffer.c | 24 + .../modbus_ring_buffer/modbus_ring_buffer.h | 9 + ModbusApp/modbus_sender/modbus_sender.c | 18 + ModbusApp/modbus_sender/modbus_sender.h | 7 + ModbusApp/modbus_storage/modbus_storage.c | 62 + ModbusApp/modbus_storage/modbus_storage.h | 13 + ModbusApp/modbus_uart/modbus_uart.c | 127 ++ ModbusApp/modbus_uart/modbus_uart.h | 12 + ModbusApp/scenes/byte_input_scene.c | 58 + ModbusApp/scenes/main_scene.c | 70 + ModbusApp/scenes/manual_sender_scene.c | 203 +++ ModbusApp/scenes/msgs_buffer_scene.c | 51 + ModbusApp/scenes/sender_scene.c | 36 + ModbusApp/scenes/settings_scene.c | 117 ++ ModbusApp/scenes/sniffer_scene.c | 58 + ModbusApp/scenes_config/app_scene_config.h | 20 + ModbusApp/scenes_config/app_scene_functions.c | 49 + ModbusApp/scenes_config/app_scene_functions.h | 50 + 22 files changed, 1347 insertions(+), 1132 deletions(-) create mode 100644 ModbusApp/Modbus.h create mode 100644 ModbusApp/modbus_parser/modbus_parser.c create mode 100644 ModbusApp/modbus_parser/modbus_parser.h create mode 100644 ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c create mode 100644 ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h create mode 100644 ModbusApp/modbus_sender/modbus_sender.c create mode 100644 ModbusApp/modbus_sender/modbus_sender.h create mode 100644 ModbusApp/modbus_storage/modbus_storage.c create mode 100644 ModbusApp/modbus_storage/modbus_storage.h create mode 100644 ModbusApp/modbus_uart/modbus_uart.c create mode 100644 ModbusApp/modbus_uart/modbus_uart.h create mode 100644 ModbusApp/scenes/byte_input_scene.c create mode 100644 ModbusApp/scenes/main_scene.c create mode 100644 ModbusApp/scenes/manual_sender_scene.c create mode 100644 ModbusApp/scenes/msgs_buffer_scene.c create mode 100644 ModbusApp/scenes/sender_scene.c create mode 100644 ModbusApp/scenes/settings_scene.c create mode 100644 ModbusApp/scenes/sniffer_scene.c create mode 100644 ModbusApp/scenes_config/app_scene_config.h create mode 100644 ModbusApp/scenes_config/app_scene_functions.c create mode 100644 ModbusApp/scenes_config/app_scene_functions.h diff --git a/ModbusApp/Modbus.c b/ModbusApp/Modbus.c index c1d7cedea77..34bfcc2134e 100644 --- a/ModbusApp/Modbus.c +++ b/ModbusApp/Modbus.c @@ -1,226 +1,11 @@ -////////////////////////// Libraries ////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define PATHAPP "apps_data/modbus" -#define PATHAPPEXT EXT_PATH(PATHAPP) -#define PATHLOGS PATHAPPEXT "/logs" - -#define BR_VALUES 12 -#define DATAWIDTH_VALUES 3 -#define STOPBITS_VALUES 4 -#define PARITY_VALUES 3 -#define TIMEOUT_VALUES 255 -#define DIGITALFORMAT_VALUES 2 -#define ANALOGFORMAT_VALUES 2 -#define SAVE_LOG_VALUES 2 - -#define RX_BUF_SIZE 255 -#define UART_CH FuriHalSerialIdUsart -#define TEXT_BOX_LEN 4096 -#define FURI_HAL_SERIAL_USART_OVERSAMPLING 0x00000000U -#define TIMEOUT_SCALER 50 - -#define FixedModbusSize 4 -#define FixedPaket \ - ((!app->modbus->slave && FUNCTION <= 0x06) || (app->modbus->slave && FUNCTION >= 0x0F)) -#define SLAVE buf[0] -#define FUNCTION buf[1] -#define EXCEPTION buf[2] - 1 -#define STARTADDRESS (buf[2] << 8 | buf[3]) -#define QUANTITY (buf[4] << 8 | buf[5]) -#define BYTECOUNT buf[6] -#define CRCH buf[len - 2] -#define CRCL buf[len - 1] - -////////////////////////// Defining Structs ////////////////////////// -typedef enum { - Main_Scene, - Settings_Scene, - ConsoleOutput_Scene, - Sender_Scene, - ByteInput_Scene, - Manual_Sender_Scene, - MSGsBuffer_Scene, - Scene_Num -} Scenes; -typedef enum { - Submenu_View, - VarList_View, - TextBox_View, - ByteInput_View -} Views; -typedef enum { - Settings_Option, - Sniffer_Option, - Sender_Option, - Read_LOG_Option, - About_Option, - - Manual_Sender_Option, - Buffer_Sender_Option -} Main_options; - -typedef struct { - uint8_t baudrate; - uint8_t dataWidth; - uint8_t stopBits; - uint8_t parity; - uint8_t timeout; - bool hexOutput; - bool saveLOG; -} Config; - -typedef struct { - Config* cfg; - FuriThread* rxThread; - FuriStreamBuffer* rxStream; - FuriHalSerialHandle* serial_handle; - uint8_t rxBuff[RX_BUF_SIZE + 1]; -} Uart; -typedef struct { - bool slave; - FuriString* timeout; -} Modbus; -#define Ring_Buf_Size 255 -typedef struct { - uint8_t delimiters[32]; - uint8_t ringBuffer[Ring_Buf_Size]; - uint16_t writeIdx; - uint8_t delimiterIdx; - uint8_t readIdx; -} RingBuffer; - -typedef struct { - SceneManager* sceneManager; - ViewDispatcher* viewDispatcher; - Submenu* subMenu; - VariableItemList* varList; - ByteInput* byteInput; - Uart* uart; - Modbus* modbus; - DialogsApp* dialogs; - Storage* storage; - File* LOGfile; - char* logFilePath; - bool LOGfileReady; - - size_t rows; - size_t textLen; - - FuriTimer* timer; - TextBox* textBox; - FuriString* text; - - uint8_t msgBuf[RX_BUF_SIZE + 1]; - size_t msgLen; - RingBuffer* ringBuffer; -} App; - -typedef enum { - BaudRate_Option, - DataWidth_Option, - StopBits_Option, - Parity_Option, - TimeOut_Option, - OutputFormat_Option, - SaveLOG_Option -} Settings_Options; - -typedef enum { - Refresh = 0 -} UartEvents; - -void BuildSender(App* app, uint8_t* buf); - -/////////////////////////////// Storage -////////////////////////////////////////// - -char* sequential_file_resolve_path( - Storage* storage, - const char* dir, - const char* prefix, - const char* extension) { - if(storage == NULL || dir == NULL || prefix == NULL || extension == NULL) { - return NULL; - } - - char file_path[256]; - int file_index = 0; - - do { - if(snprintf( - file_path, sizeof(file_path), "%s/%s_%d.%s", dir, prefix, file_index, extension) < - 0) { - return NULL; - } - file_index++; - } while(storage_file_exists(storage, file_path)); - - return strdup(file_path); -} - -void makePaths(App* app) { - furi_assert(app); - if(!storage_simply_mkdir(app->storage, PATHAPPEXT)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); - } - if(!storage_simply_mkdir(app->storage, PATHLOGS)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\nlogs folder"); - } -} -bool OpenLogFile(App* app) { - // browse for files - FuriString* predefined_filepath = furi_string_alloc_set_str(PATHLOGS); - FuriString* selected_filepath = furi_string_alloc(); - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, ".log", NULL); - if(!dialog_file_browser_show( - app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { - return false; - } - if(storage_file_open( - app->LOGfile, furi_string_get_cstr(selected_filepath), FSAM_READ, FSOM_OPEN_EXISTING)) { - app->uart->cfg->saveLOG = false; - furi_string_reset(app->text); - char buf[storage_file_size(app->LOGfile)]; - storage_file_read(app->LOGfile, buf, sizeof(buf)); - buf[sizeof(buf)] = '\0'; - furi_string_cat_str(app->text, buf); - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot open File"); - return false; - } - storage_file_close(app->LOGfile); - furi_string_free(selected_filepath); - furi_string_free(predefined_filepath); - return true; -} -/////////////////////////////// UART /////////////////////////////////////// - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtRxDone = (1 << 1), - WorkerEvtTxStart = (1 << 2), - WorkerEvtCfgChange = (1 << 3), - -} WorkerEvtFlags; -#define WORKER_ALL_EVENTS (WorkerEvtStop | WorkerEvtRxDone | WorkerEvtTxStart | WorkerEvtCfgChange) - -static const char* baudrateValues[] = { +#include "Modbus.h" +#include "modbus_parser/modbus_parser.h" +#include "modbus_storage/modbus_storage.h" +#include "modbus_uart/modbus_uart.h" +#include "modbus_sender/modbus_sender.h" +#include "modbus_ring_buffer/modbus_ring_buffer.h" + +const char* baudrateValues[] = { "1200", "2400", "4800", @@ -234,12 +19,12 @@ static const char* baudrateValues[] = { "460800", "921600", }; -static const char* dataWidthValues[] = {"7", "8", "9"}; -static const char* stopBitsValues[] = {"0.5", "1", "1.5", "2"}; -static const char* parityValues[] = {"None", "Even", "Odd"}; -static const char* saveLOGValues[] = {"OFF", "ON"}; -static const char* outputFormatValues[] = {"Default", "HEX"}; -static const char* functionNames[] = { +const char* dataWidthValues[] = {"7", "8", "9"}; +const char* stopBitsValues[] = {"0.5", "1", "1.5", "2"}; +const char* parityValues[] = {"None", "Even", "Odd"}; +const char* saveLOGValues[] = {"OFF", "ON"}; +const char* outputFormatValues[] = {"Default", "HEX"}; +const char* functionNames[] = { "Read Coils(01)", "Read Discrete Inputs(02)", "Read Holding Registers(03)", @@ -248,7 +33,7 @@ static const char* functionNames[] = { "Write Single Register(06)", "Write Multiple Coils(0F)", "Write Multiple Registers(10)"}; -static const char* exceptionCodes[] = { +const char* exceptionCodes[] = { "ILLEGAL FUNCTION", "ILLEGAL DATA ADDRESS", "ILLEGAL DATA VALUE ", @@ -260,96 +45,6 @@ static const char* exceptionCodes[] = { "", "GATEWAY PATH\nUNAVAILABLE" "GATEWAY TARGET DEVICE\nFAILED TO RESPOND"}; -LL_USART_InitTypeDef buildUartSettings(Config* cfg) { - LL_USART_InitTypeDef USART_InitStruct; - USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; - - USART_InitStruct.BaudRate = atoi(baudrateValues[cfg->baudrate]); - USART_InitStruct.DataWidth = - (cfg->dataWidth == 0 ? LL_USART_DATAWIDTH_7B : - cfg->dataWidth == 2 ? LL_USART_DATAWIDTH_9B : - LL_USART_DATAWIDTH_8B); - - USART_InitStruct.StopBits = - (cfg->stopBits == 0 ? LL_USART_STOPBITS_0_5 : - cfg->stopBits == 2 ? LL_USART_STOPBITS_1_5 : - cfg->stopBits == 3 ? LL_USART_STOPBITS_2 : - LL_USART_STOPBITS_1); - - USART_InitStruct.Parity = - (cfg->parity == 1 ? LL_USART_PARITY_EVEN : - cfg->parity == 2 ? LL_USART_PARITY_ODD : - LL_USART_PARITY_NONE); - - USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; - USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; - USART_InitStruct.OverSampling = FURI_HAL_SERIAL_USART_OVERSAMPLING; - return USART_InitStruct; -} -void uart_set_config(void* context) { - furi_assert(context); - App* app = context; - UNUSED(app); - // furi_thread_flags_set(furi_thread_get_id(app->uart->rxThread), - // WorkerEvtCfgChange); -} -static void Serial_Begin(FuriHalSerialHandle* handle, LL_USART_InitTypeDef USART_InitStruct) { - furi_hal_bus_enable(FuriHalBusUSART1); - LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); - - furi_hal_gpio_init_ex( - &gpio_usart_tx, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn7USART1); - furi_hal_gpio_init_ex( - &gpio_usart_rx, - GpioModeAltFunctionPushPull, - GpioPullUp, - GpioSpeedVeryHigh, - GpioAltFn7USART1); - LL_USART_Init(USART1, &USART_InitStruct); - LL_USART_EnableFIFO(USART1); - LL_USART_ConfigAsyncMode(USART1); - - LL_USART_Enable(USART1); - - while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1)) - ; - - furi_hal_serial_set_br(handle, USART_InitStruct.BaudRate); - LL_USART_DisableIT_ERROR(USART1); -} -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// RING BUFFER -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -RingBuffer* ring_buffer_alloc() { - RingBuffer* buffer = malloc(sizeof(RingBuffer)); - buffer->writeIdx = 0; - buffer->delimiterIdx = 0; - for(uint8_t i = 0; i < 32; i++) - buffer->delimiters[i] = 255; - return buffer; -} -void ring_buffer_free(RingBuffer* buffer) { - free(buffer); -} -void writeRingBuffer(RingBuffer* rb, uint8_t* buf, size_t len) { - for(size_t i = 0; i < len; i++) { - rb->ringBuffer[rb->writeIdx] = buf[i]; - if(i == len - 1) rb->delimiters[rb->delimiterIdx] = rb->writeIdx; - if(++rb->writeIdx > 255) { - rb->delimiterIdx = 0; - rb->writeIdx = 0; - } - } - rb->delimiterIdx++; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// uint16_t getCRC(uint8_t* buf, uint8_t len) { uint16_t crc = 0xFFFF; @@ -367,815 +62,6 @@ uint16_t getCRC(uint8_t* buf, uint8_t len) { } return crc; } - -void discreteValuesParser(void* context, uint8_t* buff, size_t len, FuriString* data) { - App* app = context; - uint8_t value = 0; - uint8_t offset = 0; - while(len) { - memcpy(&value, buff + offset, 1); - offset++; - if(!app->uart->cfg->hexOutput) { - furi_string_cat_printf(data, "\n-Byte%d: \n->", offset); - for(int i = 0; i < 8; i++) - furi_string_cat_printf( - data, - "%s%s", - value >> i & 0x01 ? "ON" : "OFF", - i == 3 ? "\n->" : - i == 7 ? "" : - ","); - } else - furi_string_cat_printf(data, "\n->Byte%d: 0x%02X", offset, value); - len--; - } -} - -void analogValuesParser(void* context, uint8_t* buff, size_t len, FuriString* data) { - App* app = context; - uint16_t value = 0; - size_t offset = 0; - - while(offset < len) { - value = 0; - if(offset + 1 < len) { - memcpy(((uint8_t*)&value) + 1, buff + offset, sizeof(uint8_t)); - memcpy((uint8_t*)&value, buff + offset + 1, sizeof(uint8_t)); - } else if(offset < len) { - memcpy(((uint8_t*)&value) + 1, buff + offset, sizeof(uint8_t)); - } - - furi_string_cat_printf( - data, - app->uart->cfg->hexOutput ? "\n->Reg%d: 0x%04X" : "\n->Reg%d: %d", - offset / 2, - value); - - offset += 2; - } -} - -void pduParser(void* context, bool slave, uint8_t* buf, size_t len, FuriString* data) { - App* app = context; - size_t offset = 2; - uint16_t address = 0; - uint16_t qty = 0; - uint16_t bCount = 0; - uint16_t value = 0; - UNUSED(len); - furi_string_cat_printf( - data, "\n%s", functionNames[FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9]); - furi_string_cat_printf( - data, app->uart->cfg->hexOutput ? "\nPeripheral: 0x%02X" : "\nPeripheral: %d", SLAVE); - memcpy( - slave && FUNCTION <= 4 ? &bCount : &address, buf + offset, slave && FUNCTION <= 4 ? 1 : 2); - - offset += slave && FUNCTION <= 4 ? 1 : 2; - address = address >> 8 | address << 8; - if(app->uart->cfg->hexOutput) - furi_string_cat_printf( - data, - slave && FUNCTION <= 4 ? "\nbCount: 0x%02X" : "\nAddress: 0x%04X", - slave && FUNCTION <= 4 ? bCount : address); - else - furi_string_cat_printf( - data, - slave && FUNCTION <= 4 ? "\nbCount: %d" : "\nAddress: %d", - slave && FUNCTION <= 4 ? bCount : address); - - if(FUNCTION >= 0x0F || (!slave && FUNCTION <= 0x04)) { - memcpy(&qty, buf + offset, 2); - offset += 2; - qty = qty >> 8 | qty << 8; - furi_string_cat_printf( - data, app->uart->cfg->hexOutput ? "\nQty: 0x%04X" : "\nQty: %d", qty); - } else if(FUNCTION >= 0x05) { - memcpy(&value, buf + offset, 2); - offset += 2; - value = value >> 8 | value << 8; - if(FUNCTION == 0x05) - furi_string_cat_printf(data, "\nValue: %s", buf[4] ? "ON" : "OFF"); - else - furi_string_cat_printf( - data, app->uart->cfg->hexOutput ? "\nValue: 0x%04X" : "\nValue: %d", value); - } else if(FUNCTION <= 0x02) - discreteValuesParser(app, buf + offset, bCount, data); - else - analogValuesParser(app, buf + offset, bCount, data); - - if(FUNCTION >= 0x0F && !slave) { - memcpy(&bCount, buf + offset, 1); - offset++; - furi_string_cat_printf( - data, app->uart->cfg->hexOutput ? "\nbCount: 0x%02X" : "\nbCount: %d", bCount); - if(FUNCTION == 0x0F) - discreteValuesParser(app, buf + offset, bCount, data); - else - analogValuesParser(app, buf + offset, bCount, data); - } - furi_string_cat_printf(data, "\nCRC: 0x%02X", CRCL | CRCH << 8); -} -void ErrParser(uint8_t* buf, size_t len, FuriString* data) { - furi_string_cat_printf( - data, "\nException code (%02X):\n%s\n", FUNCTION, exceptionCodes[EXCEPTION]); - for(size_t i = 0; i < len; i++) - furi_string_cat_printf(data, "%02X", buf[i]); -} -void ModbusParser(uint8_t* buf, size_t len, App* app, FuriString* data) { - if(FUNCTION > 0x80) { - ErrParser(buf, len, data); - } else if((FUNCTION > 0x06 && FUNCTION < 0x0F) || FUNCTION > 0x10) { - furi_string_cat_printf(data, "\nUNSUPPORTED!!!\nFUNCTION(0x%02X)\n", FUNCTION); - for(size_t i = 0; i < len; i++) - furi_string_cat_printf(data, "%02X", buf[i]); - } else if(FixedPaket && len - 4 != FixedModbusSize) { - furi_string_cat_str(data, "\nLength-Type MissMatch!!!\n"); - for(size_t i = 0; i < len; i++) - furi_string_cat_printf(data, "%02X", buf[i]); - furi_string_cat_printf( - data, - "\nCheck Reponse TimeOut!!!\nCurrent: %dms", - app->uart->cfg->timeout * TIMEOUT_SCALER); - } else { - if(!app->modbus->slave) { - for(size_t i = 0; i < len; i++) - app->msgBuf[i] = buf[i]; - writeRingBuffer(app->ringBuffer, buf, len); - app->msgLen = len; - } - pduParser(app, app->modbus->slave, buf, len, data); - } -} -void handle_rx_data_cb(uint8_t* buf, size_t len, void* context) { - furi_assert(context); - App* app = context; - buf[len] = '\0'; - FuriString* data = furi_string_alloc(); - furi_string_reset(data); - ///* - furi_string_cat_printf( - data, "\n-----%s----", app->modbus->slave ? "PERIPHERAL-" : "---HUB----"); - if((CRCH | CRCL << 8) == getCRC(buf, len - 2)) { - ModbusParser(buf, len, app, data); - } else { - furi_string_cat_str(data, "\nCRC check Failed:\n"); - for(size_t i = 0; i < len; i++) - furi_string_cat_printf(data, "%02X", buf[i]); - furi_string_cat_str(data, "\nPlease check UART Settings!!!"); - } - //*/ - // for(size_t i = 0; i < len; i++) furi_string_cat_printf(data, "%02X", - // buf[i]); furi_string_cat_str(data, "\n"); - app->textLen += furi_string_size(data); - if(app->textLen >= 3500 - 1) { - furi_string_right(app->text, app->textLen / 2); - app->textLen = furi_string_size(app->text) + furi_string_size(data); - } - furi_string_cat_str(app->text, furi_string_get_cstr(data)); - - if(app->LOGfileReady) - storage_file_write(app->LOGfile, furi_string_get_cstr(data), furi_string_size(data)); - - furi_string_free(data); - - view_dispatcher_send_custom_event(app->viewDispatcher, Refresh); - - if(app->modbus->slave) { - app->modbus->slave = false; - furi_timer_stop(app->timer); - } else { - app->modbus->slave = true; - furi_timer_start(app->timer, app->uart->cfg->timeout * TIMEOUT_SCALER); - } -} -static void - on_rx_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent ev, size_t size, void* context) { - Uart* uart = context; - if(ev & (FuriHalSerialRxEventData | FuriHalSerialRxEventIdle)) { - uint8_t data[FURI_HAL_SERIAL_DMA_BUFFER_SIZE] = {0}; - while(size) { - size_t ret = furi_hal_serial_dma_rx( - handle, - data, - (size > FURI_HAL_SERIAL_DMA_BUFFER_SIZE) ? FURI_HAL_SERIAL_DMA_BUFFER_SIZE : size); - furi_stream_buffer_send(uart->rxStream, data, ret, 0); - size -= ret; - }; - furi_thread_flags_set(furi_thread_get_id(uart->rxThread), WorkerEvtRxDone); - } -} -static void serial_init(Uart* uart, uint8_t uart_ch) { - furi_assert(!uart->serial_handle); - uart->serial_handle = furi_hal_serial_control_acquire(uart_ch); - furi_assert(uart->serial_handle); - - Serial_Begin(uart->serial_handle, buildUartSettings(uart->cfg)); - furi_hal_serial_dma_rx_start(uart->serial_handle, on_rx_cb, uart, false); -} -static void serial_deinit(Uart* uart) { - furi_assert(uart->serial_handle); - - furi_hal_serial_dma_rx_stop(uart->serial_handle); - furi_hal_serial_deinit(uart->serial_handle); - furi_hal_serial_control_release(uart->serial_handle); - uart->serial_handle = NULL; -} -void timerDone(void* context) { - App* app = context; - app->modbus->slave = false; -} -void ModbusSender(void* context) { - App* app = context; - // 02 | 0F | 00 00 | 00 04 | 01 | 0C | 7E 86 - Uart* uart = app->uart; - uint16_t crc = getCRC(app->msgBuf, app->msgLen - 2); - app->msgBuf[app->msgLen - 2] = crc & 0x00FF; - app->msgBuf[app->msgLen - 1] = (crc & 0xFF00) >> 8; - furi_hal_gpio_write(&gpio_ext_pc0, true); - furi_hal_gpio_write(&gpio_ext_pc1, true); - furi_hal_serial_tx(uart->serial_handle, app->msgBuf, app->msgLen); - furi_hal_serial_tx_wait_complete(uart->serial_handle); - furi_hal_gpio_write(&gpio_ext_pc0, false); - furi_hal_gpio_write(&gpio_ext_pc1, false); - app->modbus->slave = true; - furi_timer_start(app->timer, app->uart->cfg->timeout * TIMEOUT_SCALER); -} -static int32_t uart_worker(void* context) { - App* app = context; - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - if(events & WorkerEvtStop) break; - if(events & WorkerEvtCfgChange) { - serial_deinit(app->uart); - serial_init(app->uart, UART_CH); - } - if(events & WorkerEvtRxDone) { - size_t len = - furi_stream_buffer_receive(app->uart->rxStream, app->uart->rxBuff, RX_BUF_SIZE, 0); - if(len > 0) { - handle_rx_data_cb(app->uart->rxBuff, len, app); - } - } - if(events & WorkerEvtTxStart) { - ModbusSender(app); - } - } - - return 0; -} - -////////////////////////// Main Scene ////////////////////////// -void mainOptionsCB(void* context, uint32_t index) { - App* app = context; - - switch(index) { - case Settings_Option: - scene_manager_set_scene_state(app->sceneManager, Main_Scene, Settings_Option); - scene_manager_next_scene(app->sceneManager, Settings_Scene); - break; - case Sniffer_Option: - scene_manager_set_scene_state(app->sceneManager, Main_Scene, Sniffer_Option); - scene_manager_set_scene_state(app->sceneManager, ConsoleOutput_Scene, Sniffer_Option); - scene_manager_next_scene(app->sceneManager, ConsoleOutput_Scene); - break; - case Sender_Option: - scene_manager_set_scene_state(app->sceneManager, Main_Scene, Sender_Option); - scene_manager_next_scene(app->sceneManager, Sender_Scene); - break; - case Read_LOG_Option: - scene_manager_set_scene_state(app->sceneManager, Main_Scene, Read_LOG_Option); - if(OpenLogFile(app)) { - scene_manager_set_scene_state(app->sceneManager, ConsoleOutput_Scene, Read_LOG_Option); - scene_manager_next_scene(app->sceneManager, ConsoleOutput_Scene); - } - break; - case About_Option: - scene_manager_set_scene_state(app->sceneManager, Main_Scene, About_Option); - scene_manager_set_scene_state(app->sceneManager, ConsoleOutput_Scene, About_Option); - scene_manager_next_scene(app->sceneManager, ConsoleOutput_Scene); - break; - default: - break; - } -} -void Main_Scene_OnEnter(void* context) { - App* app = context; - submenu_reset(app->subMenu); - submenu_set_header(app->subMenu, "Main"); - submenu_add_item(app->subMenu, "Settings", Settings_Option, mainOptionsCB, app); - submenu_add_item(app->subMenu, "Sniffer", Sniffer_Option, mainOptionsCB, app); - submenu_add_item(app->subMenu, "Sender", Sender_Option, mainOptionsCB, app); - submenu_add_item(app->subMenu, "Read LOG", Read_LOG_Option, mainOptionsCB, app); - submenu_add_item(app->subMenu, "About", About_Option, mainOptionsCB, app); - submenu_set_selected_item( - app->subMenu, scene_manager_get_scene_state(app->sceneManager, Main_Scene)); - view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); -} -bool Main_Scene_OnEvent(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void Main_Scene_OnExit(void* context) { - App* app = context; - submenu_reset(app->subMenu); -} - -////////////////////////// Settings Scene ////////////////////////// -void itemChangedCB(VariableItem* item) { - App* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - uint8_t selectedIndex = variable_item_list_get_selected_item_index(app->varList); - switch(selectedIndex) { - case BaudRate_Option: - variable_item_set_current_value_text(item, baudrateValues[index]); - app->uart->cfg->baudrate = index; - break; - case DataWidth_Option: - variable_item_set_current_value_text(item, dataWidthValues[index]); - app->uart->cfg->dataWidth = index; - break; - case StopBits_Option: - variable_item_set_current_value_text(item, stopBitsValues[index]); - app->uart->cfg->stopBits = index; - break; - case Parity_Option: - variable_item_set_current_value_text(item, parityValues[index]); - app->uart->cfg->timeout = index; - break; - case TimeOut_Option: - app->uart->cfg->timeout = index; - variable_item_set_current_value_index(item, index); - furi_string_printf(app->modbus->timeout, "%d", index * TIMEOUT_SCALER); - variable_item_set_current_value_text(item, furi_string_get_cstr(app->modbus->timeout)); - break; - case OutputFormat_Option: - variable_item_set_current_value_text(item, outputFormatValues[index]); - app->uart->cfg->hexOutput = index; - break; - case SaveLOG_Option: - variable_item_set_current_value_text(item, saveLOGValues[index]); - app->uart->cfg->saveLOG = index; - break; - default: - break; - } -} -void CFG_Scene_OnEnter(void* context) { - App* app = context; - VariableItem* item; - item = variable_item_list_add(app->varList, "Buadrate", BR_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->baudrate); - variable_item_set_current_value_text(item, baudrateValues[app->uart->cfg->baudrate]); - item = variable_item_list_add(app->varList, "Data size", DATAWIDTH_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->dataWidth); - variable_item_set_current_value_text(item, dataWidthValues[app->uart->cfg->dataWidth]); - item = variable_item_list_add(app->varList, "Stop bits", STOPBITS_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->stopBits); - variable_item_set_current_value_text(item, stopBitsValues[app->uart->cfg->stopBits]); - item = variable_item_list_add(app->varList, "Parity", PARITY_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->parity); - variable_item_set_current_value_text(item, parityValues[app->uart->cfg->parity]); - item = variable_item_list_add(app->varList, "TimeOut(ms)", TIMEOUT_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->timeout); - furi_string_printf(app->modbus->timeout, "%d", app->uart->cfg->timeout * TIMEOUT_SCALER); - variable_item_set_current_value_text(item, furi_string_get_cstr(app->modbus->timeout)); - item = variable_item_list_add( - app->varList, "Output Format", DIGITALFORMAT_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->hexOutput ? 1 : 0); - variable_item_set_current_value_text( - item, outputFormatValues[app->uart->cfg->hexOutput ? 1 : 0]); - item = variable_item_list_add(app->varList, "Save LOG?", SAVE_LOG_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->saveLOG ? 1 : 0); - variable_item_set_current_value_text(item, saveLOGValues[app->uart->cfg->saveLOG ? 1 : 0]); - - variable_item_list_set_selected_item(app->varList, 0); - view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); -} -bool CFG_Scene_OnEvent(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void CFG_Scene_OnExit(void* context) { - App* app = context; - if(app->uart->cfg->saveLOG) { - strcpy( - app->logFilePath, sequential_file_resolve_path(app->storage, PATHLOGS, "Log", "log")); - if(app->logFilePath != NULL) { - if(storage_file_open(app->LOGfile, app->logFilePath, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { - furi_string_reset(app->text); - app->LOGfileReady = true; - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); - } - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot resolve log path"); - } - } - uart_set_config(app); - variable_item_list_reset(app->varList); -} - -////////////////////////// Sniffer Scene ////////////////////////// -void Sniffer_Scene_OnEnter(void* context) { - App* app = context; - serial_init(app->uart, UART_CH); - if(scene_manager_get_scene_state(app->sceneManager, ConsoleOutput_Scene) == Sniffer_Option || - scene_manager_get_scene_state(app->sceneManager, ConsoleOutput_Scene) == Sender_Option) { - text_box_set_font(app->textBox, TextBoxFontText); - text_box_set_focus(app->textBox, TextBoxFocusEnd); - furi_string_cat_printf( - app->text, "Baudrate: %s", baudrateValues[app->uart->cfg->baudrate]); - furi_string_cat_printf( - app->text, "\nData Width: %s", dataWidthValues[app->uart->cfg->dataWidth]); - furi_string_cat_printf( - app->text, "\nStop bits: %s", stopBitsValues[app->uart->cfg->stopBits]); - furi_string_cat_printf(app->text, "\nParity: %s", parityValues[app->uart->cfg->parity]); - furi_string_cat_printf( - app->text, "\nResponse TimeOut: %dms", app->uart->cfg->timeout * TIMEOUT_SCALER); - } else if(scene_manager_get_scene_state(app->sceneManager, ConsoleOutput_Scene) == About_Option) { - text_box_set_font(app->textBox, TextBoxFontText); - text_box_set_focus(app->textBox, TextBoxFocusStart); - furi_string_cat_printf(app->text, "MODBUS APP\n"); - furi_string_cat_printf(app->text, "BY: ROBERTO ARELLANO\n"); - furi_string_cat_printf(app->text, "ELECTRONIC CATS\n"); - furi_string_cat_printf( - app->text, - "https://github.com/ElectronicCats/" - "flipper-rs485modbus/tree/main/ModbusApp/Test1"); - } - view_dispatcher_switch_to_view(app->viewDispatcher, TextBox_View); - text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); - if(scene_manager_get_scene_state(app->sceneManager, ConsoleOutput_Scene) == Sender_Option) { - furi_thread_flags_set(furi_thread_get_id(app->uart->rxThread), WorkerEvtTxStart); - } -} -bool Sniffer_Scene_OnEvent(void* context, SceneManagerEvent event) { - App* app = context; - UNUSED(app); - bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); - } - return consumed; -} -void Sniffer_Scene_OnExit(void* context) { - App* app = context; - text_box_reset(app->textBox); - furi_string_reset(app->text); - serial_deinit(app->uart); -} -////////////////////////// Sender Scene //////////////////////// -void SenderOptionsCB(void* context, uint32_t index) { - App* app = context; - if(index == Manual_Sender_Option) { - scene_manager_set_scene_state(app->sceneManager, Sender_Scene, Manual_Sender_Option); - scene_manager_next_scene(app->sceneManager, Manual_Sender_Scene); - } else if(index == Buffer_Sender_Option) { - scene_manager_set_scene_state(app->sceneManager, Sender_Scene, Buffer_Sender_Option); - scene_manager_next_scene(app->sceneManager, MSGsBuffer_Scene); - } -} -void Sender_Scene_OnEnter(void* context) { - App* app = context; - submenu_reset(app->subMenu); - submenu_set_header(app->subMenu, "Sender"); - submenu_add_item(app->subMenu, "Manual Sender", Manual_Sender_Option, SenderOptionsCB, app); - submenu_add_item(app->subMenu, "Buffer Sender", Buffer_Sender_Option, SenderOptionsCB, app); - submenu_set_selected_item( - app->subMenu, scene_manager_get_scene_state(app->sceneManager, Main_Scene)); - view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); -} -bool Sender_Scene_OnEvent(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void Sender_Scene_OnExit(void* context) { - App* app = context; - submenu_reset(app->subMenu); -} - -////////////////////////// ByteInput Scene //////////////////////// -void SetValue(void* context) { - App* app = context; - scene_manager_handle_back_event(app->sceneManager); -} -void ByteInput_Scene_OnEnter(void* context) { - App* app = context; - uint8_t* buf = app->msgBuf; - uint8_t offset = scene_manager_get_scene_state(app->sceneManager, ByteInput_Scene); - switch(scene_manager_get_scene_state(app->sceneManager, ByteInput_Scene)) { - case 0: - byte_input_set_header_text(app->byteInput, "Set Slave"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &SLAVE, 1); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; - case 1: - byte_input_set_header_text(app->byteInput, "Set Function"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &FUNCTION, 1); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; - case 2: - byte_input_set_header_text(app->byteInput, "Set Address"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &buf[2], 2); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; - case 3: - byte_input_set_header_text(app->byteInput, "Set value or quantity"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &buf[4], 2); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; - default: - if(FUNCTION == 0x0F) - offset += 2; - else - offset += offset - 3; - byte_input_set_header_text(app->byteInput, "Set x value"); - byte_input_set_result_callback( - app->byteInput, SetValue, NULL, app, &buf[offset], FUNCTION == 0x0F ? 1 : 2); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; - } -} -bool ByteInput_Scene_OnEvent(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void ByteInput_Scene_OnExit(void* context) { - App* app = context; - UNUSED(app); -} -////////////////////////// Manual Sender Scene ////////////////////////// -const char* fns[] = {"0x01", "0x02", "0x03", "0x04", "0x05", "0x06", "0x0F", "0x10"}; - -void itemChangeCB(VariableItem* item) { - App* app = variable_item_get_context(item); - uint8_t* buf = app->msgBuf; - uint8_t index = variable_item_get_current_value_index(item); - uint8_t selectedIndex = variable_item_list_get_selected_item_index(app->varList); - uint16_t Value; - char str[10]; - switch(selectedIndex) { - case 0: - snprintf(str, sizeof(str), "%d", index + 1); - variable_item_set_current_value_text(item, strdup(str)); - buf[0] = index + 1; - break; - case 1: - variable_item_set_current_value_text(item, fns[index]); - FUNCTION = index <= 0x05 ? index + 1 : index + 9; - buf[4] = 0; - buf[5] = 1; - BuildSender(app, buf); - break; - case 2: - snprintf(str, sizeof(str), "%d", index); - variable_item_set_current_value_text(item, strdup(str)); - buf[2] = index >> 8 & 0x00FF; - buf[3] = index & 0x00FF; - break; - case 3: - if(FUNCTION != 0x05 && FUNCTION != 0x06) { - index++; - snprintf(str, sizeof(str), "%d", index); - variable_item_set_current_value_text(item, strdup(str)); - buf[4] = index >> 8 & 0x00FF; - buf[5] = index & 0x00FF; - if(FUNCTION >= 0x0F) { - Value = (buf[4] << 8 | buf[5]); - if(FUNCTION == 0x0F) - Value = Value % 8 ? Value / 8 + 1 : Value / 8; - else - Value = Value * 2; - item = variable_item_list_get(app->varList, 4); - snprintf(str, sizeof(str), "[ %d ]", Value); - variable_item_set_current_value_text(item, strdup(str)); - if(BYTECOUNT != Value) { - BYTECOUNT = Value; - BuildSender(app, buf); - } - } - } else { - Value = FUNCTION == 5 ? index ? 0xFF00 : 0x0000 : index; - snprintf(str, sizeof(str), "0x%04X", Value); - variable_item_set_current_value_text( - item, FUNCTION == 0x05 ? index ? "ON" : "OFF" : str); - buf[4] = Value >> 8 & 0x00FF; - buf[5] = Value & 0x00FF; - } - break; - default: - Value = index; - snprintf(str, sizeof(str), FUNCTION == 0x10 ? "0x%04X" : "0x%02X", Value); - variable_item_set_current_value_text(item, str); - if(FUNCTION == 0x0F) { - selectedIndex += 2; - buf[selectedIndex] = Value; - } else { - selectedIndex += selectedIndex - 3; - - buf[selectedIndex] = Value >> 8 & 0x0FF; - buf[selectedIndex + 1] = Value & 0x00FF; - } - break; - } -} - -void itemEnterCB(void* context, uint32_t index) { - App* app = context; - uint8_t* buf = app->msgBuf; - uint8_t SendButton = FUNCTION >= 0x0F ? (FUNCTION == 0x0F ? BYTECOUNT : QUANTITY) + 5 : 4; - scene_manager_set_scene_state(app->sceneManager, Manual_Sender_Scene, index); - if(index == SendButton) { - scene_manager_set_scene_state(app->sceneManager, ConsoleOutput_Scene, Sender_Option); - scene_manager_next_scene(app->sceneManager, ConsoleOutput_Scene); - } - - else if(index == 1 || (FUNCTION >= 0x0F && index == 4)) { - } else { - if(!(FUNCTION == 0x05 && index == 3)) { - scene_manager_set_scene_state(app->sceneManager, ByteInput_Scene, index); - scene_manager_next_scene(app->sceneManager, ByteInput_Scene); - } - } -} -void BuildValues(App* app, uint16_t byteCount, uint8_t* buf, bool one) { - VariableItem* item; - char lbl[20]; - char val[10]; - for(uint16_t i = 0; i < byteCount; i += one ? 1 : 2) { - snprintf(lbl, sizeof(lbl), one ? "Byte %d" : "Register %d", one ? i + 1 : i / 2 + 1); - snprintf( - val, sizeof(val), one ? "0x%02X" : "0x%04X", one ? buf[i] : buf[i] << 8 | buf[i + 1]); - item = variable_item_list_add(app->varList, strdup(lbl), 255, itemChangeCB, app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index( - item, MIN(255, one ? buf[i] : buf[i] << 8 | buf[i + 1])); - } -} -void BuildSender(App* app, uint8_t* buf) { - variable_item_list_reset(app->varList); - VariableItem* item; - uint16_t Value = 0; - char val[10]; - SLAVE = MIN(SLAVE, 32); - snprintf(val, sizeof(val), "%d", SLAVE); - item = variable_item_list_add(app->varList, "Peripheral ID", 32, itemChangeCB, app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, SLAVE - 1); - item = variable_item_list_add(app->varList, "Function", 8, itemChangeCB, app); - variable_item_set_current_value_text(item, fns[FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9]); - variable_item_set_current_value_index(item, FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9); - Value = STARTADDRESS; - snprintf(val, sizeof(val), "%d", Value); - item = variable_item_list_add(app->varList, "Start Address", 255, itemChangeCB, app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, MIN(255, STARTADDRESS)); - if(FUNCTION != 0x05 && FUNCTION != 0x06) { - uint16_t max = FUNCTION == 0x10 ? 0x0A : - FUNCTION == 0x0F ? 0x50 : - FUNCTION <= 0x02 ? 0x7D0 : - 0x7D; - Value = MIN(buf[4] << 8 | buf[5], max); - snprintf(val, sizeof(val), "%d", Value); - item = variable_item_list_add(app->varList, "Quantity", max, itemChangeCB, app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, MIN(Value - 1, MIN(max, 255))); - buf[4] = Value >> 8 & 0x00FF; - buf[5] = Value & 0x00FF; - } else { - Value = buf[4] << 8 | buf[5]; - snprintf(val, sizeof(val), "0x%04X", Value); - item = variable_item_list_add( - app->varList, "Value", FUNCTION == 0x05 ? 2 : 255, itemChangeCB, app); - variable_item_set_current_value_text( - item, FUNCTION == 0x05 ? Value ? "ON" : "OFF" : strdup(val)); - variable_item_set_current_value_index( - item, FUNCTION == 0x05 ? Value ? 1 : 0 : MIN(Value, 255)); - Value = FUNCTION == 5 ? Value ? 0xFF00 : 0x0000 : Value; - buf[4] = Value >> 8 & 0x00FF; - buf[5] = Value & 0x00FF; - } - if(FUNCTION >= 0x0F) { - Value = (buf[4] << 8 | buf[5]); - if(FUNCTION == 0x0F) - Value = Value % 8 ? Value / 8 + 1 : Value / 8; - else - Value = Value * 2; - snprintf(val, sizeof(val), "[ %d ]", Value); - item = variable_item_list_add(app->varList, "ByteCount", 1, NULL, app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, 0); - BYTECOUNT = Value; - app->msgLen = Value + 9; - BuildValues(app, Value, buf + 7, FUNCTION == 0x0F ? true : false); - } - - item = variable_item_list_add(app->varList, "Send Packet", 1, NULL, app); - variable_item_list_set_enter_callback(app->varList, itemEnterCB, app); - variable_item_set_current_value_text(item, ""); - variable_item_set_current_value_index(item, 0); -} -void Manual_Sender_Scene_OnEnter(void* context) { - App* app = context; - BuildSender(app, app->msgBuf); - variable_item_list_set_selected_item( - app->varList, scene_manager_get_scene_state(app->sceneManager, Manual_Sender_Scene)); - view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); -} -bool Manual_Sender_Scene_OnEvent(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void Manual_Sender_Scene_OnExit(void* context) { - App* app = context; - variable_item_list_reset(app->varList); -} -////////////////////////// MSGsBuffer Scene //////////////////////// -void OnItemEnterCB(void* context, uint32_t index) { - App* app = context; - uint8_t start = index ? app->ringBuffer->delimiters[index - 1] + 1 : 0; - for(uint8_t i = start; i <= app->ringBuffer->delimiters[index]; i++) { - app->msgBuf[i - start] = app->ringBuffer->ringBuffer[i]; - if(i == app->ringBuffer->delimiters[index]) app->msgLen = i - start + 1; - } - scene_manager_next_scene(app->sceneManager, Manual_Sender_Scene); -} -void BuildCMDList(App* app) { - submenu_set_header(app->subMenu, " ID | FN |Adss"); - RingBuffer* rb = app->ringBuffer; - rb->readIdx = 0; - uint8_t buf[255]; - uint8_t i = 0; - uint8_t delimiterIdx = 0; - uint8_t len = 0; - char lbl[30]; - do { - len = 0; - do { - snprintf(lbl, sizeof(lbl), " %d | %d | %d |", SLAVE, FUNCTION, STARTADDRESS); - buf[len] = rb->ringBuffer[i]; - len++; - i++; - } while(i <= rb->delimiters[delimiterIdx] && i < 255); - delimiterIdx++; - if((CRCH | CRCL << 8) == getCRC(buf, len - 2)) - submenu_add_item(app->subMenu, lbl, delimiterIdx - 1, OnItemEnterCB, app); - } while(i < 255); -} -void MSGsBuffer_Scene_OnEnter(void* context) { - App* app = context; - submenu_reset(app->subMenu); - BuildCMDList(app); - view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); -} -bool MSGsBuffer_Scene_OnEvent(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} -void MSGsBuffer_Scene_OnExit(void* context) { - App* app = context; - submenu_reset(app->subMenu); -} -////////////////////////// Scene Handlers ////////////////////////// -void (*const OnEnterHandlers[])(void*) = { - Main_Scene_OnEnter, - CFG_Scene_OnEnter, - Sniffer_Scene_OnEnter, - Sender_Scene_OnEnter, - ByteInput_Scene_OnEnter, - Manual_Sender_Scene_OnEnter, - MSGsBuffer_Scene_OnEnter}; -bool (*const OnEventHandlers[])(void*, SceneManagerEvent) = { - Main_Scene_OnEvent, - CFG_Scene_OnEvent, - Sniffer_Scene_OnEvent, - Sender_Scene_OnEvent, - ByteInput_Scene_OnEvent, - Manual_Sender_Scene_OnEvent, - MSGsBuffer_Scene_OnEvent}; -void (*const OnExitHandlers[])(void*) = { - Main_Scene_OnExit, - CFG_Scene_OnExit, - Sniffer_Scene_OnExit, - Sender_Scene_OnExit, - ByteInput_Scene_OnExit, - Manual_Sender_Scene_OnExit, - MSGsBuffer_Scene_OnExit}; -static const SceneManagerHandlers SceneHandlers = { - .on_enter_handlers = OnEnterHandlers, - .on_event_handlers = OnEventHandlers, - .on_exit_handlers = OnExitHandlers, - .scene_num = Scene_Num}; - ////////////////////////// ViewDispatcher Callbacks ////////////////////////// static bool CustomEventCB(void* context, uint32_t event) { furi_assert(context); @@ -1242,9 +128,8 @@ static App* modbus_app_alloc() { app->dialogs = furi_record_open(RECORD_DIALOGS); app->storage = furi_record_open(RECORD_STORAGE); app->LOGfile = storage_file_alloc(app->storage); - app->sceneManager = scene_manager_alloc(&SceneHandlers, app); + app->sceneManager = scene_manager_alloc(&app_scene_handlers, app); app->viewDispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->viewDispatcher); view_dispatcher_set_event_callback_context(app->viewDispatcher, app); view_dispatcher_set_custom_event_callback(app->viewDispatcher, CustomEventCB); view_dispatcher_set_navigation_event_callback(app->viewDispatcher, BackEventCB); @@ -1324,7 +209,7 @@ int32_t Modbus_app(void* p) { App* app = modbus_app_alloc(); Gui* gui = furi_record_open(RECORD_GUI); view_dispatcher_attach_to_gui(app->viewDispatcher, gui, ViewDispatcherTypeFullscreen); - scene_manager_next_scene(app->sceneManager, Main_Scene); + scene_manager_next_scene(app->sceneManager, app_scene_main); view_dispatcher_run(app->viewDispatcher); furi_record_close(RECORD_GUI); modbus_app_free(app); diff --git a/ModbusApp/Modbus.h b/ModbusApp/Modbus.h new file mode 100644 index 00000000000..f060fb81854 --- /dev/null +++ b/ModbusApp/Modbus.h @@ -0,0 +1,156 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "scenes_config/app_scene_functions.h" + + +#define PATHAPP "apps_data/modbus" +#define PATHAPPEXT EXT_PATH(PATHAPP) +#define PATHLOGS PATHAPPEXT "/logs" + +#define BR_VALUES 12 +#define DATAWIDTH_VALUES 3 +#define STOPBITS_VALUES 4 +#define PARITY_VALUES 3 +#define TIMEOUT_VALUES 255 +#define DIGITALFORMAT_VALUES 2 +#define ANALOGFORMAT_VALUES 2 +#define SAVE_LOG_VALUES 2 + +#define RX_BUF_SIZE 255 +#define UART_CH FuriHalSerialIdUsart +#define TEXT_BOX_LEN 4096 +#define FURI_HAL_SERIAL_USART_OVERSAMPLING 0x00000000U +#define TIMEOUT_SCALER 50 + +#define FixedModbusSize 4 +#define FixedPaket \ + ((!app->modbus->slave && FUNCTION <= 0x06) || (app->modbus->slave && FUNCTION >= 0x0F)) +#define SLAVE buf[0] +#define FUNCTION buf[1] +#define EXCEPTION buf[2] - 1 +#define STARTADDRESS (buf[2] << 8 | buf[3]) +#define QUANTITY (buf[4] << 8 | buf[5]) +#define BYTECOUNT buf[6] +#define CRCH buf[len - 2] +#define CRCL buf[len - 1] + +////////////////////////// Defining Structs ////////////////////////// +typedef enum { + Submenu_View, + VarList_View, + TextBox_View, + ByteInput_View +} Views; +typedef enum { + Settings_Option, + Sniffer_Option, + Sender_Option, + Read_LOG_Option, + About_Option, + Manual_Sender_Option, + Buffer_Sender_Option +} Main_options; + +typedef struct { + uint8_t baudrate; + uint8_t dataWidth; + uint8_t stopBits; + uint8_t parity; + uint8_t timeout; + bool hexOutput; + bool saveLOG; +} Config; + +typedef struct { + Config* cfg; + FuriThread* rxThread; + FuriStreamBuffer* rxStream; + FuriHalSerialHandle* serial_handle; + uint8_t rxBuff[RX_BUF_SIZE + 1]; +} Uart; +typedef struct { + bool slave; + FuriString* timeout; +} Modbus; +#define Ring_Buf_Size 255 +typedef struct { + uint8_t delimiters[32]; + uint8_t ringBuffer[Ring_Buf_Size]; + uint16_t writeIdx; + uint8_t delimiterIdx; + uint8_t readIdx; +} RingBuffer; + +typedef struct { + SceneManager* sceneManager; + ViewDispatcher* viewDispatcher; + Submenu* subMenu; + VariableItemList* varList; + ByteInput* byteInput; + Uart* uart; + Modbus* modbus; + DialogsApp* dialogs; + Storage* storage; + File* LOGfile; + char* logFilePath; + bool LOGfileReady; + + size_t rows; + size_t textLen; + + FuriTimer* timer; + TextBox* textBox; + FuriString* text; + + uint8_t msgBuf[RX_BUF_SIZE + 1]; + size_t msgLen; + RingBuffer* ringBuffer; +} App; + +typedef enum { + BaudRate_Option, + DataWidth_Option, + StopBits_Option, + Parity_Option, + TimeOut_Option, + OutputFormat_Option, + SaveLOG_Option +} Settings_Options; + +typedef enum { + Refresh = 0 +} UartEvents; + +typedef enum { + WorkerEvtStop = (1 << 0), + WorkerEvtRxDone = (1 << 1), + WorkerEvtTxStart = (1 << 2), + WorkerEvtCfgChange = (1 << 3), + +} WorkerEvtFlags; +#define WORKER_ALL_EVENTS (WorkerEvtStop | WorkerEvtRxDone | WorkerEvtTxStart | WorkerEvtCfgChange) + +extern const char* baudrateValues[]; +extern const char* dataWidthValues[]; +extern const char* stopBitsValues[]; +extern const char* parityValues[]; +extern const char* saveLOGValues[]; +extern const char* outputFormatValues[]; +extern const char* functionNames[]; +extern const char* exceptionCodes[]; +uint16_t getCRC(uint8_t* buf, uint8_t len); \ No newline at end of file diff --git a/ModbusApp/modbus_parser/modbus_parser.c b/ModbusApp/modbus_parser/modbus_parser.c new file mode 100644 index 00000000000..448592fa38a --- /dev/null +++ b/ModbusApp/modbus_parser/modbus_parser.c @@ -0,0 +1,185 @@ +#include "modbus_parser.h" + +#include "../Modbus.h" +#include "../modbus_ring_buffer/modbus_ring_buffer.h" + +static void discreteValuesParser(void* context, uint8_t* buff, size_t len, FuriString* data) { + App* app = context; + uint8_t value = 0; + uint8_t offset = 0; + while(len) { + memcpy(&value, buff + offset, 1); + offset++; + if(!app->uart->cfg->hexOutput) { + furi_string_cat_printf(data, "\n-Byte%d: \n->", offset); + for(int i = 0; i < 8; i++) + furi_string_cat_printf( + data, + "%s%s", + value >> i & 0x01 ? "ON" : "OFF", + i == 3 ? "\n->" : + i == 7 ? "" : + ","); + } else + furi_string_cat_printf(data, "\n->Byte%d: 0x%02X", offset, value); + len--; + } +} + +static void analogValuesParser(void* context, uint8_t* buff, size_t len, FuriString* data) { + App* app = context; + uint16_t value = 0; + size_t offset = 0; + + while(offset < len) { + value = 0; + if(offset + 1 < len) { + memcpy(((uint8_t*)&value) + 1, buff + offset, sizeof(uint8_t)); + memcpy((uint8_t*)&value, buff + offset + 1, sizeof(uint8_t)); + } else if(offset < len) { + memcpy(((uint8_t*)&value) + 1, buff + offset, sizeof(uint8_t)); + } + + furi_string_cat_printf( + data, + app->uart->cfg->hexOutput ? "\n->Reg%d: 0x%04X" : "\n->Reg%d: %d", + offset / 2, + value); + + offset += 2; + } +} + +static void pduParser(void* context, bool slave, uint8_t* buf, size_t len, FuriString* data) { + App* app = context; + size_t offset = 2; + uint16_t address = 0; + uint16_t qty = 0; + uint16_t bCount = 0; + uint16_t value = 0; + UNUSED(len); + furi_string_cat_printf( + data, "\n%s", functionNames[FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9]); + furi_string_cat_printf( + data, app->uart->cfg->hexOutput ? "\nPeripheral: 0x%02X" : "\nPeripheral: %d", SLAVE); + memcpy( + slave && FUNCTION <= 4 ? &bCount : &address, buf + offset, slave && FUNCTION <= 4 ? 1 : 2); + + offset += slave && FUNCTION <= 4 ? 1 : 2; + address = address >> 8 | address << 8; + if(app->uart->cfg->hexOutput) + furi_string_cat_printf( + data, + slave && FUNCTION <= 4 ? "\nbCount: 0x%02X" : "\nAddress: 0x%04X", + slave && FUNCTION <= 4 ? bCount : address); + else + furi_string_cat_printf( + data, + slave && FUNCTION <= 4 ? "\nbCount: %d" : "\nAddress: %d", + slave && FUNCTION <= 4 ? bCount : address); + + if(FUNCTION >= 0x0F || (!slave && FUNCTION <= 0x04)) { + memcpy(&qty, buf + offset, 2); + offset += 2; + qty = qty >> 8 | qty << 8; + furi_string_cat_printf( + data, app->uart->cfg->hexOutput ? "\nQty: 0x%04X" : "\nQty: %d", qty); + } else if(FUNCTION >= 0x05) { + memcpy(&value, buf + offset, 2); + offset += 2; + value = value >> 8 | value << 8; + if(FUNCTION == 0x05) + furi_string_cat_printf(data, "\nValue: %s", buf[4] ? "ON" : "OFF"); + else + furi_string_cat_printf( + data, app->uart->cfg->hexOutput ? "\nValue: 0x%04X" : "\nValue: %d", value); + } else if(FUNCTION <= 0x02) + discreteValuesParser(app, buf + offset, bCount, data); + else + analogValuesParser(app, buf + offset, bCount, data); + + if(FUNCTION >= 0x0F && !slave) { + memcpy(&bCount, buf + offset, 1); + offset++; + furi_string_cat_printf( + data, app->uart->cfg->hexOutput ? "\nbCount: 0x%02X" : "\nbCount: %d", bCount); + if(FUNCTION == 0x0F) + discreteValuesParser(app, buf + offset, bCount, data); + else + analogValuesParser(app, buf + offset, bCount, data); + } + furi_string_cat_printf(data, "\nCRC: 0x%02X", CRCL | CRCH << 8); +} +static void ErrParser(uint8_t* buf, size_t len, FuriString* data) { + furi_string_cat_printf( + data, "\nException code (%02X):\n%s\n", FUNCTION, exceptionCodes[EXCEPTION]); + for(size_t i = 0; i < len; i++) + furi_string_cat_printf(data, "%02X", buf[i]); +} +static void ModbusParser(uint8_t* buf, size_t len, App* app, FuriString* data) { + if(FUNCTION > 0x80) { + ErrParser(buf, len, data); + } else if((FUNCTION > 0x06 && FUNCTION < 0x0F) || FUNCTION > 0x10) { + furi_string_cat_printf(data, "\nUNSUPPORTED!!!\nFUNCTION(0x%02X)\n", FUNCTION); + for(size_t i = 0; i < len; i++) + furi_string_cat_printf(data, "%02X", buf[i]); + } else if(FixedPaket && len - 4 != FixedModbusSize) { + furi_string_cat_str(data, "\nLength-Type MissMatch!!!\n"); + for(size_t i = 0; i < len; i++) + furi_string_cat_printf(data, "%02X", buf[i]); + furi_string_cat_printf( + data, + "\nCheck Reponse TimeOut!!!\nCurrent: %dms", + app->uart->cfg->timeout * TIMEOUT_SCALER); + } else { + if(!app->modbus->slave) { + for(size_t i = 0; i < len; i++) + app->msgBuf[i] = buf[i]; + writeRingBuffer(app->ringBuffer, buf, len); + app->msgLen = len; + } + pduParser(app, app->modbus->slave, buf, len, data); + } +} +void handle_rx_data_cb(uint8_t* buf, size_t len, void* context) { + furi_assert(context); + App* app = context; + buf[len] = '\0'; + FuriString* data = furi_string_alloc(); + furi_string_reset(data); + ///* + furi_string_cat_printf( + data, "\n-----%s----", app->modbus->slave ? "PERIPHERAL-" : "---HUB----"); + if((CRCH | CRCL << 8) == getCRC(buf, len - 2)) { + ModbusParser(buf, len, app, data); + } else { + furi_string_cat_str(data, "\nCRC check Failed:\n"); + for(size_t i = 0; i < len; i++) + furi_string_cat_printf(data, "%02X", buf[i]); + furi_string_cat_str(data, "\nPlease check UART Settings!!!"); + } + //*/ + // for(size_t i = 0; i < len; i++) furi_string_cat_printf(data, "%02X", + // buf[i]); furi_string_cat_str(data, "\n"); + app->textLen += furi_string_size(data); + if(app->textLen >= 3500 - 1) { + furi_string_right(app->text, app->textLen / 2); + app->textLen = furi_string_size(app->text) + furi_string_size(data); + } + furi_string_cat_str(app->text, furi_string_get_cstr(data)); + + if(app->LOGfileReady) + storage_file_write(app->LOGfile, furi_string_get_cstr(data), furi_string_size(data)); + + furi_string_free(data); + + view_dispatcher_send_custom_event(app->viewDispatcher, Refresh); + + if(app->modbus->slave) { + app->modbus->slave = false; + furi_timer_stop(app->timer); + } else { + app->modbus->slave = true; + furi_timer_start(app->timer, app->uart->cfg->timeout * TIMEOUT_SCALER); + } +} diff --git a/ModbusApp/modbus_parser/modbus_parser.h b/ModbusApp/modbus_parser/modbus_parser.h new file mode 100644 index 00000000000..e46d395a32d --- /dev/null +++ b/ModbusApp/modbus_parser/modbus_parser.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void handle_rx_data_cb(uint8_t* buf, size_t len, void* context); diff --git a/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c new file mode 100644 index 00000000000..1c4af91c20f --- /dev/null +++ b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c @@ -0,0 +1,24 @@ +#include "modbus_ring_buffer.h" + +RingBuffer* ring_buffer_alloc() { + RingBuffer* buffer = malloc(sizeof(RingBuffer)); + buffer->writeIdx = 0; + buffer->delimiterIdx = 0; + for(uint8_t i = 0; i < 32; i++) + buffer->delimiters[i] = 255; + return buffer; +} +void ring_buffer_free(RingBuffer* buffer) { + free(buffer); +} +void writeRingBuffer(RingBuffer* rb, uint8_t* buf, size_t len) { + for(size_t i = 0; i < len; i++) { + rb->ringBuffer[rb->writeIdx] = buf[i]; + if(i == len - 1) rb->delimiters[rb->delimiterIdx] = rb->writeIdx; + if(++rb->writeIdx > 255) { + rb->delimiterIdx = 0; + rb->writeIdx = 0; + } + } + rb->delimiterIdx++; +} \ No newline at end of file diff --git a/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h new file mode 100644 index 00000000000..683ffd4a50e --- /dev/null +++ b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#include "../Modbus.h" + +RingBuffer* ring_buffer_alloc(); +void ring_buffer_free(RingBuffer* buffer); +void writeRingBuffer(RingBuffer* rb, uint8_t* buf, size_t len); \ No newline at end of file diff --git a/ModbusApp/modbus_sender/modbus_sender.c b/ModbusApp/modbus_sender/modbus_sender.c new file mode 100644 index 00000000000..dbb41213f75 --- /dev/null +++ b/ModbusApp/modbus_sender/modbus_sender.c @@ -0,0 +1,18 @@ +#include "modbus_sender.h" + +void ModbusSender(void* context) { + App* app = context; + // 02 | 0F | 00 00 | 00 04 | 01 | 0C | 7E 86 + Uart* uart = app->uart; + uint16_t crc = getCRC(app->msgBuf, app->msgLen - 2); + app->msgBuf[app->msgLen - 2] = crc & 0x00FF; + app->msgBuf[app->msgLen - 1] = (crc & 0xFF00) >> 8; + furi_hal_gpio_write(&gpio_ext_pc0, true); + furi_hal_gpio_write(&gpio_ext_pc1, true); + furi_hal_serial_tx(uart->serial_handle, app->msgBuf, app->msgLen); + furi_hal_serial_tx_wait_complete(uart->serial_handle); + furi_hal_gpio_write(&gpio_ext_pc0, false); + furi_hal_gpio_write(&gpio_ext_pc1, false); + app->modbus->slave = true; + furi_timer_start(app->timer, app->uart->cfg->timeout * TIMEOUT_SCALER); +} \ No newline at end of file diff --git a/ModbusApp/modbus_sender/modbus_sender.h b/ModbusApp/modbus_sender/modbus_sender.h new file mode 100644 index 00000000000..a5242144438 --- /dev/null +++ b/ModbusApp/modbus_sender/modbus_sender.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "../Modbus.h" + +void ModbusSender(void* context); \ No newline at end of file diff --git a/ModbusApp/modbus_storage/modbus_storage.c b/ModbusApp/modbus_storage/modbus_storage.c new file mode 100644 index 00000000000..13308581a7f --- /dev/null +++ b/ModbusApp/modbus_storage/modbus_storage.c @@ -0,0 +1,62 @@ +#include "modbus_storage.h" + +char* sequential_file_resolve_path( + Storage* storage, + const char* dir, + const char* prefix, + const char* extension) { + if(storage == NULL || dir == NULL || prefix == NULL || extension == NULL) { + return NULL; + } + + char file_path[256]; + int file_index = 0; + + do { + if(snprintf( + file_path, sizeof(file_path), "%s/%s_%d.%s", dir, prefix, file_index, extension) < + 0) { + return NULL; + } + file_index++; + } while(storage_file_exists(storage, file_path)); + + return strdup(file_path); +} + +void makePaths(App* app) { + furi_assert(app); + if(!storage_simply_mkdir(app->storage, PATHAPPEXT)) { + dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); + } + if(!storage_simply_mkdir(app->storage, PATHLOGS)) { + dialog_message_show_storage_error(app->dialogs, "Cannot create\nlogs folder"); + } +} +bool OpenLogFile(App* app) { + // browse for files + FuriString* predefined_filepath = furi_string_alloc_set_str(PATHLOGS); + FuriString* selected_filepath = furi_string_alloc(); + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, ".log", NULL); + if(!dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + return false; + } + if(storage_file_open( + app->LOGfile, furi_string_get_cstr(selected_filepath), FSAM_READ, FSOM_OPEN_EXISTING)) { + app->uart->cfg->saveLOG = false; + furi_string_reset(app->text); + char buf[storage_file_size(app->LOGfile)]; + storage_file_read(app->LOGfile, buf, sizeof(buf)); + buf[sizeof(buf)] = '\0'; + furi_string_cat_str(app->text, buf); + } else { + dialog_message_show_storage_error(app->dialogs, "Cannot open File"); + return false; + } + storage_file_close(app->LOGfile); + furi_string_free(selected_filepath); + furi_string_free(predefined_filepath); + return true; +} \ No newline at end of file diff --git a/ModbusApp/modbus_storage/modbus_storage.h b/ModbusApp/modbus_storage/modbus_storage.h new file mode 100644 index 00000000000..087716f5678 --- /dev/null +++ b/ModbusApp/modbus_storage/modbus_storage.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "../Modbus.h" + +char* sequential_file_resolve_path( + Storage* storage, + const char* dir, + const char* prefix, + const char* extension); +bool OpenLogFile(App* app); +void makePaths(App* app); \ No newline at end of file diff --git a/ModbusApp/modbus_uart/modbus_uart.c b/ModbusApp/modbus_uart/modbus_uart.c new file mode 100644 index 00000000000..4b5484394df --- /dev/null +++ b/ModbusApp/modbus_uart/modbus_uart.c @@ -0,0 +1,127 @@ +#include "modbus_uart.h" +#include "../modbus_sender/modbus_sender.h" +#include "../modbus_parser/modbus_parser.h" + +LL_USART_InitTypeDef buildUartSettings(Config* cfg) { + LL_USART_InitTypeDef USART_InitStruct; + USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; + + USART_InitStruct.BaudRate = atoi(baudrateValues[cfg->baudrate]); + USART_InitStruct.DataWidth = + (cfg->dataWidth == 0 ? LL_USART_DATAWIDTH_7B : + cfg->dataWidth == 2 ? LL_USART_DATAWIDTH_9B : + LL_USART_DATAWIDTH_8B); + + USART_InitStruct.StopBits = + (cfg->stopBits == 0 ? LL_USART_STOPBITS_0_5 : + cfg->stopBits == 2 ? LL_USART_STOPBITS_1_5 : + cfg->stopBits == 3 ? LL_USART_STOPBITS_2 : + LL_USART_STOPBITS_1); + + USART_InitStruct.Parity = + (cfg->parity == 1 ? LL_USART_PARITY_EVEN : + cfg->parity == 2 ? LL_USART_PARITY_ODD : + LL_USART_PARITY_NONE); + + USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; + USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; + USART_InitStruct.OverSampling = FURI_HAL_SERIAL_USART_OVERSAMPLING; + return USART_InitStruct; +} +void uart_set_config(void* context) { + furi_assert(context); + App* app = context; + UNUSED(app); + // furi_thread_flags_set(furi_thread_get_id(app->uart->rxThread), + // WorkerEvtCfgChange); +} +void Serial_Begin(FuriHalSerialHandle* handle, LL_USART_InitTypeDef USART_InitStruct) { + furi_hal_bus_enable(FuriHalBusUSART1); + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + furi_hal_gpio_init_ex( + &gpio_usart_tx, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn7USART1); + furi_hal_gpio_init_ex( + &gpio_usart_rx, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedVeryHigh, + GpioAltFn7USART1); + LL_USART_Init(USART1, &USART_InitStruct); + LL_USART_EnableFIFO(USART1); + LL_USART_ConfigAsyncMode(USART1); + + LL_USART_Enable(USART1); + + while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1)) + ; + + furi_hal_serial_set_br(handle, USART_InitStruct.BaudRate); + LL_USART_DisableIT_ERROR(USART1); +} + +static void + on_rx_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent ev, size_t size, void* context) { + Uart* uart = context; + if(ev & (FuriHalSerialRxEventData | FuriHalSerialRxEventIdle)) { + uint8_t data[FURI_HAL_SERIAL_DMA_BUFFER_SIZE] = {0}; + while(size) { + size_t ret = furi_hal_serial_dma_rx( + handle, + data, + (size > FURI_HAL_SERIAL_DMA_BUFFER_SIZE) ? FURI_HAL_SERIAL_DMA_BUFFER_SIZE : size); + furi_stream_buffer_send(uart->rxStream, data, ret, 0); + size -= ret; + }; + furi_thread_flags_set(furi_thread_get_id(uart->rxThread), WorkerEvtRxDone); + } +} +void serial_init(Uart* uart, uint8_t uart_ch) { + furi_assert(!uart->serial_handle); + uart->serial_handle = furi_hal_serial_control_acquire(uart_ch); + furi_assert(uart->serial_handle); + + Serial_Begin(uart->serial_handle, buildUartSettings(uart->cfg)); + furi_hal_serial_dma_rx_start(uart->serial_handle, on_rx_cb, uart, false); +} +void serial_deinit(Uart* uart) { + furi_assert(uart->serial_handle); + + furi_hal_serial_dma_rx_stop(uart->serial_handle); + furi_hal_serial_deinit(uart->serial_handle); + furi_hal_serial_control_release(uart->serial_handle); + uart->serial_handle = NULL; +} +void timerDone(void* context) { + App* app = context; + app->modbus->slave = false; +} +int32_t uart_worker(void* context) { + App* app = context; + while(1) { + uint32_t events = + furi_thread_flags_wait(WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever); + furi_check((events & FuriFlagError) == 0); + if(events & WorkerEvtStop) break; + if(events & WorkerEvtCfgChange) { + serial_deinit(app->uart); + serial_init(app->uart, UART_CH); + } + if(events & WorkerEvtRxDone) { + size_t len = + furi_stream_buffer_receive(app->uart->rxStream, app->uart->rxBuff, RX_BUF_SIZE, 0); + if(len > 0) { + handle_rx_data_cb(app->uart->rxBuff, len, app); + } + } + if(events & WorkerEvtTxStart) { + ModbusSender(app); + } + } + + return 0; +} \ No newline at end of file diff --git a/ModbusApp/modbus_uart/modbus_uart.h b/ModbusApp/modbus_uart/modbus_uart.h new file mode 100644 index 00000000000..af8c9128236 --- /dev/null +++ b/ModbusApp/modbus_uart/modbus_uart.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include "../Modbus.h" + +LL_USART_InitTypeDef buildUartSettings(Config* cfg); +void uart_set_config(void* context); +void Serial_Begin(FuriHalSerialHandle* handle, LL_USART_InitTypeDef USART_InitStruct); +int32_t uart_worker(void* context); +void timerDone(void* context); +void serial_deinit(Uart* uart); +void serial_init(Uart* uart, uint8_t uart_ch); \ No newline at end of file diff --git a/ModbusApp/scenes/byte_input_scene.c b/ModbusApp/scenes/byte_input_scene.c new file mode 100644 index 00000000000..5dfff2a00e8 --- /dev/null +++ b/ModbusApp/scenes/byte_input_scene.c @@ -0,0 +1,58 @@ +#include "../Modbus.h" + +////////////////////////// ByteInput Scene //////////////////////// +void SetValue(void* context) { + App* app = context; + scene_manager_handle_back_event(app->sceneManager); +} +void app_scene_byte_input_on_enter(void* context) { + App* app = context; + uint8_t* buf = app->msgBuf; + uint8_t offset = + scene_manager_get_scene_state(app->sceneManager, app_scene_byte_input); + switch (scene_manager_get_scene_state(app->sceneManager, app_scene_byte_input)) { + case 0: + byte_input_set_header_text(app->byteInput, "Set Slave"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, + &SLAVE, 1); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; + case 1: + byte_input_set_header_text(app->byteInput, "Set Function"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, + &FUNCTION, 1); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; + case 2: + byte_input_set_header_text(app->byteInput, "Set Address"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, + &buf[2], 2); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; + case 3: + byte_input_set_header_text(app->byteInput, "Set value or quantity"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, + &buf[4], 2); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; + default: + if (FUNCTION == 0x0F) + offset += 2; + else + offset += offset - 3; + byte_input_set_header_text(app->byteInput, "Set x value"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, + &buf[offset], FUNCTION == 0x0F ? 1 : 2); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; + } +} +bool app_scene_byte_input_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void app_scene_byte_input_on_exit(void* context) { + App* app = context; + UNUSED(app); +} \ No newline at end of file diff --git a/ModbusApp/scenes/main_scene.c b/ModbusApp/scenes/main_scene.c new file mode 100644 index 00000000000..0cde7cbb1b5 --- /dev/null +++ b/ModbusApp/scenes/main_scene.c @@ -0,0 +1,70 @@ +#include "../Modbus.h" +#include "../modbus_storage/modbus_storage.h" + +////////////////////////// Main Scene ////////////////////////// +void mainOptionsCB(void* context, uint32_t index) { + App* app = context; + + switch (index) { + case Settings_Option: + scene_manager_set_scene_state(app->sceneManager, app_scene_main, + Settings_Option); + scene_manager_next_scene(app->sceneManager, app_scene_settings); + break; + case Sniffer_Option: + scene_manager_set_scene_state(app->sceneManager, app_scene_main, + Sniffer_Option); + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, + Sniffer_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + break; + case Sender_Option: + scene_manager_set_scene_state(app->sceneManager, app_scene_main, + Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sender); + break; + case Read_LOG_Option: + scene_manager_set_scene_state(app->sceneManager, app_scene_main, + Read_LOG_Option); + if (OpenLogFile(app)) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, + Read_LOG_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + } + break; + case About_Option: + scene_manager_set_scene_state(app->sceneManager, app_scene_main, + About_Option); + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, + About_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + break; + default: + break; + } +} + +void app_scene_main_on_enter(void* context) { + App* app = context; + submenu_reset(app->subMenu); + submenu_set_header(app->subMenu, "Main"); + submenu_add_item(app->subMenu, "Settings", Settings_Option, mainOptionsCB, + app); + submenu_add_item(app->subMenu, "Sniffer", Sniffer_Option, mainOptionsCB, app); + submenu_add_item(app->subMenu, "Sender", Sender_Option, mainOptionsCB, app); + submenu_add_item(app->subMenu, "Read LOG", Read_LOG_Option, mainOptionsCB, + app); + submenu_add_item(app->subMenu, "About", About_Option, mainOptionsCB, app); + submenu_set_selected_item(app->subMenu, scene_manager_get_scene_state( + app->sceneManager, app_scene_main)); + view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); +} +bool app_scene_main_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void app_scene_main_on_exit(void* context) { + App* app = context; + submenu_reset(app->subMenu); +} \ No newline at end of file diff --git a/ModbusApp/scenes/manual_sender_scene.c b/ModbusApp/scenes/manual_sender_scene.c new file mode 100644 index 00000000000..47764ffc039 --- /dev/null +++ b/ModbusApp/scenes/manual_sender_scene.c @@ -0,0 +1,203 @@ +#include "../Modbus.h" + +void BuildSender(App* app, uint8_t* buf); + +////////////////////////// Manual Sender Scene ////////////////////////// +const char* fns[] = {"0x01", "0x02", "0x03", "0x04", + "0x05", "0x06", "0x0F", "0x10"}; + +void itemChangeCB(VariableItem* item) { + App* app = variable_item_get_context(item); + uint8_t* buf = app->msgBuf; + uint8_t index = variable_item_get_current_value_index(item); + uint8_t selectedIndex = + variable_item_list_get_selected_item_index(app->varList); + uint16_t Value; + char str[10]; + switch (selectedIndex) { + case 0: + snprintf(str, sizeof(str), "%d", index + 1); + variable_item_set_current_value_text(item, strdup(str)); + buf[0] = index + 1; + break; + case 1: + variable_item_set_current_value_text(item, fns[index]); + FUNCTION = index <= 0x05 ? index + 1 : index + 9; + buf[4] = 0; + buf[5] = 1; + BuildSender(app, buf); + break; + case 2: + snprintf(str, sizeof(str), "%d", index); + variable_item_set_current_value_text(item, strdup(str)); + buf[2] = index >> 8 & 0x00FF; + buf[3] = index & 0x00FF; + break; + case 3: + if (FUNCTION != 0x05 && FUNCTION != 0x06) { + index++; + snprintf(str, sizeof(str), "%d", index); + variable_item_set_current_value_text(item, strdup(str)); + buf[4] = index >> 8 & 0x00FF; + buf[5] = index & 0x00FF; + if (FUNCTION >= 0x0F) { + Value = (buf[4] << 8 | buf[5]); + if (FUNCTION == 0x0F) + Value = Value % 8 ? Value / 8 + 1 : Value / 8; + else + Value = Value * 2; + item = variable_item_list_get(app->varList, 4); + snprintf(str, sizeof(str), "[ %d ]", Value); + variable_item_set_current_value_text(item, strdup(str)); + if (BYTECOUNT != Value) { + BYTECOUNT = Value; + BuildSender(app, buf); + } + } + } else { + Value = FUNCTION == 5 ? index ? 0xFF00 : 0x0000 : index; + snprintf(str, sizeof(str), "0x%04X", Value); + variable_item_set_current_value_text( + item, FUNCTION == 0x05 ? index ? "ON" : "OFF" : str); + buf[4] = Value >> 8 & 0x00FF; + buf[5] = Value & 0x00FF; + } + break; + default: + Value = index; + snprintf(str, sizeof(str), FUNCTION == 0x10 ? "0x%04X" : "0x%02X", Value); + variable_item_set_current_value_text(item, str); + if (FUNCTION == 0x0F) { + selectedIndex += 2; + buf[selectedIndex] = Value; + } else { + selectedIndex += selectedIndex - 3; + + buf[selectedIndex] = Value >> 8 & 0x0FF; + buf[selectedIndex + 1] = Value & 0x00FF; + } + break; + } +} + +void itemEnterCB(void* context, uint32_t index) { + App* app = context; + uint8_t* buf = app->msgBuf; + uint8_t SendButton = + FUNCTION >= 0x0F ? (FUNCTION == 0x0F ? BYTECOUNT : QUANTITY) + 5 : 4; + scene_manager_set_scene_state(app->sceneManager, app_scene_manual_sender, index); + if (index == SendButton) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, + Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + } + + else if (index == 1 || (FUNCTION >= 0x0F && index == 4)) { + } else { + if (!(FUNCTION == 0x05 && index == 3)) { + scene_manager_set_scene_state(app->sceneManager, app_scene_byte_input, index); + scene_manager_next_scene(app->sceneManager, app_scene_byte_input); + } + } +} +void BuildValues(App* app, uint16_t byteCount, uint8_t* buf, bool one) { + VariableItem* item; + char lbl[20]; + char val[10]; + for (uint16_t i = 0; i < byteCount; i += one ? 1 : 2) { + snprintf(lbl, sizeof(lbl), one ? "Byte %d" : "Register %d", + one ? i + 1 : i / 2 + 1); + snprintf(val, sizeof(val), one ? "0x%02X" : "0x%04X", + one ? buf[i] : buf[i] << 8 | buf[i + 1]); + item = variable_item_list_add(app->varList, strdup(lbl), 255, itemChangeCB, + app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index( + item, MIN(255, one ? buf[i] : buf[i] << 8 | buf[i + 1])); + } +} +void BuildSender(App* app, uint8_t* buf) { + variable_item_list_reset(app->varList); + VariableItem* item; + uint16_t Value = 0; + char val[10]; + SLAVE = MIN(SLAVE, 32); + snprintf(val, sizeof(val), "%d", SLAVE); + item = variable_item_list_add(app->varList, "Peripheral ID", 32, itemChangeCB, + app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index(item, SLAVE - 1); + item = variable_item_list_add(app->varList, "Function", 8, itemChangeCB, app); + variable_item_set_current_value_text( + item, fns[FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9]); + variable_item_set_current_value_index( + item, FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9); + Value = STARTADDRESS; + snprintf(val, sizeof(val), "%d", Value); + item = variable_item_list_add(app->varList, "Start Address", 255, + itemChangeCB, app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index(item, MIN(255, STARTADDRESS)); + if (FUNCTION != 0x05 && FUNCTION != 0x06) { + uint16_t max = FUNCTION == 0x10 ? 0x0A + : FUNCTION == 0x0F ? 0x50 + : FUNCTION <= 0x02 ? 0x7D0 + : 0x7D; + Value = MIN(buf[4] << 8 | buf[5], max); + snprintf(val, sizeof(val), "%d", Value); + item = variable_item_list_add(app->varList, "Quantity", max, itemChangeCB, + app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index(item, MIN(Value - 1, MIN(max, 255))); + buf[4] = Value >> 8 & 0x00FF; + buf[5] = Value & 0x00FF; + } else { + Value = buf[4] << 8 | buf[5]; + snprintf(val, sizeof(val), "0x%04X", Value); + item = variable_item_list_add( + app->varList, "Value", FUNCTION == 0x05 ? 2 : 255, itemChangeCB, app); + variable_item_set_current_value_text( + item, FUNCTION == 0x05 ? Value ? "ON" : "OFF" : strdup(val)); + variable_item_set_current_value_index( + item, FUNCTION == 0x05 ? Value ? 1 : 0 : MIN(Value, 255)); + Value = FUNCTION == 5 ? Value ? 0xFF00 : 0x0000 : Value; + buf[4] = Value >> 8 & 0x00FF; + buf[5] = Value & 0x00FF; + } + if (FUNCTION >= 0x0F) { + Value = (buf[4] << 8 | buf[5]); + if (FUNCTION == 0x0F) + Value = Value % 8 ? Value / 8 + 1 : Value / 8; + else + Value = Value * 2; + snprintf(val, sizeof(val), "[ %d ]", Value); + item = variable_item_list_add(app->varList, "ByteCount", 1, NULL, app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index(item, 0); + BYTECOUNT = Value; + app->msgLen = Value + 9; + BuildValues(app, Value, buf + 7, FUNCTION == 0x0F ? true : false); + } + + item = variable_item_list_add(app->varList, "Send Packet", 1, NULL, app); + variable_item_list_set_enter_callback(app->varList, itemEnterCB, app); + variable_item_set_current_value_text(item, ""); + variable_item_set_current_value_index(item, 0); +} +void app_scene_manual_sender_on_enter(void* context) { + App* app = context; + BuildSender(app, app->msgBuf); + variable_item_list_set_selected_item( + app->varList, + scene_manager_get_scene_state(app->sceneManager, app_scene_manual_sender)); + view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); +} +bool app_scene_manual_sender_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void app_scene_manual_sender_on_exit(void* context) { + App* app = context; + variable_item_list_reset(app->varList); +} \ No newline at end of file diff --git a/ModbusApp/scenes/msgs_buffer_scene.c b/ModbusApp/scenes/msgs_buffer_scene.c new file mode 100644 index 00000000000..1762978cbb0 --- /dev/null +++ b/ModbusApp/scenes/msgs_buffer_scene.c @@ -0,0 +1,51 @@ +#include "../Modbus.h" + +////////////////////////// MSGsBuffer Scene //////////////////////// +void OnItemEnterCB(void* context, uint32_t index) { + App* app = context; + uint8_t start = index ? app->ringBuffer->delimiters[index - 1] + 1 : 0; + for (uint8_t i = start; i <= app->ringBuffer->delimiters[index]; i++) { + app->msgBuf[i - start] = app->ringBuffer->ringBuffer[i]; + if (i == app->ringBuffer->delimiters[index]) + app->msgLen = i - start + 1; + } + scene_manager_next_scene(app->sceneManager, app_scene_manual_sender); +} +void BuildCMDList(App* app) { + submenu_set_header(app->subMenu, " ID | FN |Adss"); + RingBuffer* rb = app->ringBuffer; + rb->readIdx = 0; + uint8_t buf[255]; + uint8_t i = 0; + uint8_t delimiterIdx = 0; + uint8_t len = 0; + char lbl[30]; + do { + len = 0; + do { + snprintf(lbl, sizeof(lbl), " %d | %d | %d |", SLAVE, FUNCTION, + STARTADDRESS); + buf[len] = rb->ringBuffer[i]; + len++; + i++; + } while (i <= rb->delimiters[delimiterIdx] && i < 255); + delimiterIdx++; + if ((CRCH | CRCL << 8) == getCRC(buf, len - 2)) + submenu_add_item(app->subMenu, lbl, delimiterIdx - 1, OnItemEnterCB, app); + } while (i < 255); +} +void app_scene_msgs_buffer_on_enter(void* context) { + App* app = context; + submenu_reset(app->subMenu); + BuildCMDList(app); + view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); +} +bool app_scene_msgs_buffer_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void app_scene_msgs_buffer_on_exit(void* context) { + App* app = context; + submenu_reset(app->subMenu); +} \ No newline at end of file diff --git a/ModbusApp/scenes/sender_scene.c b/ModbusApp/scenes/sender_scene.c new file mode 100644 index 00000000000..097ab09206d --- /dev/null +++ b/ModbusApp/scenes/sender_scene.c @@ -0,0 +1,36 @@ +#include "../Modbus.h" + +////////////////////////// Sender Scene //////////////////////// +void SenderOptionsCB(void* context, uint32_t index) { + App* app = context; + if (index == Manual_Sender_Option) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sender, + Manual_Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_manual_sender); + } else if (index == Buffer_Sender_Option) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sender, + Buffer_Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_msgs_buffer); + } +} +void app_scene_sender_on_enter(void* context) { + App* app = context; + submenu_reset(app->subMenu); + submenu_set_header(app->subMenu, "Sender"); + submenu_add_item(app->subMenu, "Manual Sender", Manual_Sender_Option, + SenderOptionsCB, app); + submenu_add_item(app->subMenu, "Buffer Sender", Buffer_Sender_Option, + SenderOptionsCB, app); + submenu_set_selected_item(app->subMenu, scene_manager_get_scene_state( + app->sceneManager, app_scene_main)); + view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); +} +bool app_scene_sender_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void app_scene_sender_on_exit(void* context) { + App* app = context; + submenu_reset(app->subMenu); +} \ No newline at end of file diff --git a/ModbusApp/scenes/settings_scene.c b/ModbusApp/scenes/settings_scene.c new file mode 100644 index 00000000000..b0fc6ac0689 --- /dev/null +++ b/ModbusApp/scenes/settings_scene.c @@ -0,0 +1,117 @@ +#include "../Modbus.h" +#include "../modbus_storage/modbus_storage.h" +#include "../modbus_uart/modbus_uart.h" + +////////////////////////// Settings Scene ////////////////////////// +void itemChangedCB(VariableItem* item) { + App* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + uint8_t selectedIndex = + variable_item_list_get_selected_item_index(app->varList); + switch (selectedIndex) { + case BaudRate_Option: + variable_item_set_current_value_text(item, baudrateValues[index]); + app->uart->cfg->baudrate = index; + break; + case DataWidth_Option: + variable_item_set_current_value_text(item, dataWidthValues[index]); + app->uart->cfg->dataWidth = index; + break; + case StopBits_Option: + variable_item_set_current_value_text(item, stopBitsValues[index]); + app->uart->cfg->stopBits = index; + break; + case Parity_Option: + variable_item_set_current_value_text(item, parityValues[index]); + app->uart->cfg->timeout = index; + break; + case TimeOut_Option: + app->uart->cfg->timeout = index; + variable_item_set_current_value_index(item, index); + furi_string_printf(app->modbus->timeout, "%d", index * TIMEOUT_SCALER); + variable_item_set_current_value_text( + item, furi_string_get_cstr(app->modbus->timeout)); + break; + case OutputFormat_Option: + variable_item_set_current_value_text(item, outputFormatValues[index]); + app->uart->cfg->hexOutput = index; + break; + case SaveLOG_Option: + variable_item_set_current_value_text(item, saveLOGValues[index]); + app->uart->cfg->saveLOG = index; + break; + default: + break; + } +} +void app_scene_settings_on_enter(void* context) { + App* app = context; + VariableItem* item; + item = variable_item_list_add(app->varList, "Buadrate", BR_VALUES, + itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->baudrate); + variable_item_set_current_value_text( + item, baudrateValues[app->uart->cfg->baudrate]); + item = variable_item_list_add(app->varList, "Data size", DATAWIDTH_VALUES, + itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->dataWidth); + variable_item_set_current_value_text( + item, dataWidthValues[app->uart->cfg->dataWidth]); + item = variable_item_list_add(app->varList, "Stop bits", STOPBITS_VALUES, + itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->stopBits); + variable_item_set_current_value_text( + item, stopBitsValues[app->uart->cfg->stopBits]); + item = variable_item_list_add(app->varList, "Parity", PARITY_VALUES, + itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->parity); + variable_item_set_current_value_text(item, + parityValues[app->uart->cfg->parity]); + item = variable_item_list_add(app->varList, "TimeOut(ms)", TIMEOUT_VALUES, + itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->timeout); + furi_string_printf(app->modbus->timeout, "%d", + app->uart->cfg->timeout * TIMEOUT_SCALER); + variable_item_set_current_value_text( + item, furi_string_get_cstr(app->modbus->timeout)); + item = variable_item_list_add(app->varList, "Output Format", + DIGITALFORMAT_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, + app->uart->cfg->hexOutput ? 1 : 0); + variable_item_set_current_value_text( + item, outputFormatValues[app->uart->cfg->hexOutput ? 1 : 0]); + item = variable_item_list_add(app->varList, "Save LOG?", SAVE_LOG_VALUES, + itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->saveLOG ? 1 : 0); + variable_item_set_current_value_text( + item, saveLOGValues[app->uart->cfg->saveLOG ? 1 : 0]); + + variable_item_list_set_selected_item(app->varList, 0); + view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); +} +bool app_scene_settings_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} +void app_scene_settings_on_exit(void* context) { + App* app = context; + if (app->uart->cfg->saveLOG) { + strcpy(app->logFilePath, + sequential_file_resolve_path(app->storage, PATHLOGS, "Log", "log")); + if (app->logFilePath != NULL) { + if (storage_file_open(app->LOGfile, app->logFilePath, FSAM_WRITE, + FSOM_CREATE_ALWAYS)) { + furi_string_reset(app->text); + app->LOGfileReady = true; + } else { + dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); + } + } else { + dialog_message_show_storage_error(app->dialogs, + "Cannot resolve log path"); + } + } + uart_set_config(app); + variable_item_list_reset(app->varList); +} \ No newline at end of file diff --git a/ModbusApp/scenes/sniffer_scene.c b/ModbusApp/scenes/sniffer_scene.c new file mode 100644 index 00000000000..d75d7fba406 --- /dev/null +++ b/ModbusApp/scenes/sniffer_scene.c @@ -0,0 +1,58 @@ +#include "../Modbus.h" +#include "../modbus_uart/modbus_uart.h" + +////////////////////////// Sniffer Scene ////////////////////////// +void app_scene_sniffer_on_enter(void* context) { + App* app = context; + serial_init(app->uart, UART_CH); + if (scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == + Sniffer_Option || + scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer ) == + Sender_Option) { + text_box_set_font(app->textBox, TextBoxFontText); + text_box_set_focus(app->textBox, TextBoxFocusEnd); + furi_string_cat_printf(app->text, "Baudrate: %s", + baudrateValues[app->uart->cfg->baudrate]); + furi_string_cat_printf(app->text, "\nData Width: %s", + dataWidthValues[app->uart->cfg->dataWidth]); + furi_string_cat_printf(app->text, "\nStop bits: %s", + stopBitsValues[app->uart->cfg->stopBits]); + furi_string_cat_printf(app->text, "\nParity: %s", + parityValues[app->uart->cfg->parity]); + furi_string_cat_printf(app->text, "\nResponse TimeOut: %dms", + app->uart->cfg->timeout * TIMEOUT_SCALER); + } else if (scene_manager_get_scene_state( + app->sceneManager, app_scene_sniffer) == About_Option) { + text_box_set_font(app->textBox, TextBoxFontText); + text_box_set_focus(app->textBox, TextBoxFocusStart); + furi_string_cat_printf(app->text, "MODBUS APP\n"); + furi_string_cat_printf(app->text, "BY: ROBERTO ARELLANO\n"); + furi_string_cat_printf(app->text, "ELECTRONIC CATS\n"); + furi_string_cat_printf(app->text, + "https://github.com/ElectronicCats/" + "flipper-rs485modbus/tree/main/ModbusApp/Test1"); + } + view_dispatcher_switch_to_view(app->viewDispatcher, TextBox_View); + text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); + if (scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == + Sender_Option) { + furi_thread_flags_set(furi_thread_get_id(app->uart->rxThread), + WorkerEvtTxStart); + } +} +bool app_scene_sniffer_on_event(void* context, SceneManagerEvent event) { + App* app = context; + UNUSED(app); + bool consumed = false; + if (event.type == SceneManagerEventTypeCustom) { + consumed = true; + text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); + } + return consumed; +} +void app_scene_sniffer_on_exit(void* context) { + App* app = context; + text_box_reset(app->textBox); + furi_string_reset(app->text); + serial_deinit(app->uart); +} \ No newline at end of file diff --git a/ModbusApp/scenes_config/app_scene_config.h b/ModbusApp/scenes_config/app_scene_config.h new file mode 100644 index 00000000000..5508ff23fcd --- /dev/null +++ b/ModbusApp/scenes_config/app_scene_config.h @@ -0,0 +1,20 @@ +//--------------------------------------------------------------------- +// Here you gonna put all the scenes you wanna use, they have to be in +// order. +// +// For any scene you "add", you have to create 3 functions in every scene, +// they can be on one file or can be in differents files but must be included +// in the program +// +// The name of the functions will be given in the app_scene_functions.c +// there is a code that defines the names and the functions +//--------------------------------------------------------------------- + +ADD_SCENE(app, main, main) +ADD_SCENE(app, settings, settings) +ADD_SCENE(app, sniffer, sniffer) +ADD_SCENE(app, sender, sender) +ADD_SCENE(app, byte_input, byte_input) +ADD_SCENE(app, manual_sender, manual_sender) +ADD_SCENE(app, msgs_buffer, msgs_buffer) + \ No newline at end of file diff --git a/ModbusApp/scenes_config/app_scene_functions.c b/ModbusApp/scenes_config/app_scene_functions.c new file mode 100644 index 00000000000..48f056e6576 --- /dev/null +++ b/ModbusApp/scenes_config/app_scene_functions.c @@ -0,0 +1,49 @@ +#include "app_scene_functions.h" + +//-------------------------------------------------------------------- +// This part works to create the name of the functions +// of the "on_enter" for every scene. +//-------------------------------------------------------------------- + +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const app_on_enter_handlers[])(void*) = { +#include "app_scene_config.h" +}; +#undef ADD_SCENE + +//-------------------------------------------------------------------- +// This part works to create the name of the functions +// of the "on_event" for every scene. +//-------------------------------------------------------------------- + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const app_on_event_handlers[])(void* context, + SceneManagerEvent event) = { +#include "app_scene_config.h" +}; +#undef ADD_SCENE + +//-------------------------------------------------------------------- +// This part works to create the name of the functions +// of the "on_exit" for every scene. +//-------------------------------------------------------------------- + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const app_on_exit_handlers[])(void* context) = { +#include "app_scene_config.h" +}; +#undef ADD_SCENE + +//-------------------------------------------------------------------- +// Here we add the callback functions for the scenes. +//-------------------------------------------------------------------- + +// Initialize scene handlers configuration structure +const SceneManagerHandlers app_scene_handlers = { + .on_enter_handlers = app_on_enter_handlers, + .on_event_handlers = app_on_event_handlers, + .on_exit_handlers = app_on_exit_handlers, + .scene_num = app_scene_enum, +}; diff --git a/ModbusApp/scenes_config/app_scene_functions.h b/ModbusApp/scenes_config/app_scene_functions.h new file mode 100644 index 00000000000..d110dc4592d --- /dev/null +++ b/ModbusApp/scenes_config/app_scene_functions.h @@ -0,0 +1,50 @@ +#include + +//-------------------------------------------------------------------- +// This part of this code works to create the enum of the scenes +// They have to be in order from the app_scene_config +//-------------------------------------------------------------------- + +#define ADD_SCENE(prefix, name, id) app_scene_##id, +typedef enum { +#include "app_scene_config.h" + app_scene_enum, +} Appscenes; +#undef ADD_SCENE + +//--------------------------------------------------------------------- +//--------------------------------------------------------------------- +// This code define the functions for every scene we have, it gives the name +// the functions "on_enter", "on_exit" and "on_event" +//--------------------------------------------------------------------- +//--------------------------------------------------------------------- + +extern const SceneManagerHandlers + app_scene_handlers; // We define the scene manager handler + +//--------------------------------------------------------------------- +// This defines and name of the "on_enter" functions +//--------------------------------------------------------------------- + +#define ADD_SCENE(prefix, name, id) \ + void prefix##_scene_##name##_on_enter(void*); +#include "app_scene_config.h" +#undef ADD_SCENE + +//--------------------------------------------------------------------- +// This defines and name of the "on_event" functions +//--------------------------------------------------------------------- + +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "app_scene_config.h" +#undef ADD_SCENE + +//--------------------------------------------------------------------- +// This defines and name of the "on_exit" functions +//--------------------------------------------------------------------- + +#define ADD_SCENE(prefix, name, id) \ + void prefix##_scene_##name##_on_exit(void* context); +#include "app_scene_config.h" +#undef ADD_SCENE From f499d4e202b9dcc939a47731c59e7c717e79d2c3 Mon Sep 17 00:00:00 2001 From: Roberto Arellano Date: Wed, 21 Aug 2024 14:34:48 -0600 Subject: [PATCH 2/3] fix: crash when EXPANSION MODULE is activated --- ModbusApp/Modbus.c | 25 ++++++------------------- ModbusApp/Modbus.h | 6 ++++-- ModbusApp/modbus_parser/modbus_parser.c | 17 +++++++++++++++++ ModbusApp/modbus_parser/modbus_parser.h | 1 + ModbusApp/modbus_sender/modbus_sender.c | 1 + ModbusApp/scenes/msgs_buffer_scene.c | 2 +- ModbusApp/scenes/settings_scene.c | 3 ++- 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/ModbusApp/Modbus.c b/ModbusApp/Modbus.c index 34bfcc2134e..17b6ee4bdf3 100644 --- a/ModbusApp/Modbus.c +++ b/ModbusApp/Modbus.c @@ -45,23 +45,6 @@ const char* exceptionCodes[] = { "", "GATEWAY PATH\nUNAVAILABLE" "GATEWAY TARGET DEVICE\nFAILED TO RESPOND"}; - -uint16_t getCRC(uint8_t* buf, uint8_t len) { - uint16_t crc = 0xFFFF; - - for(int pos = 0; pos < len; pos++) { - crc ^= (uint16_t)buf[pos]; - - for(int i = 8; i != 0; i--) { - if((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; - } else - crc >>= 1; - } - } - return crc; -} ////////////////////////// ViewDispatcher Callbacks ////////////////////////// static bool CustomEventCB(void* context, uint32_t event) { furi_assert(context); @@ -196,18 +179,22 @@ void modbus_app_free(App* app) { storage_file_free(app->LOGfile); furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_DIALOGS); + furi_record_close(RECORD_EXPANSION); + expansion_enable(app->expansion); free(app); } ////////////////////////// Entry Point ////////////////////////// int32_t Modbus_app(void* p) { UNUSED(p); + App* app = modbus_app_alloc(); + Gui* gui = furi_record_open(RECORD_GUI); + app->expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(app->expansion); furi_hal_gpio_init_simple(&gpio_ext_pc0, GpioModeOutputPushPull); furi_hal_gpio_init_simple(&gpio_ext_pc1, GpioModeOutputPushPull); furi_hal_gpio_write(&gpio_ext_pc0, 0); furi_hal_gpio_write(&gpio_ext_pc1, 0); - App* app = modbus_app_alloc(); - Gui* gui = furi_record_open(RECORD_GUI); view_dispatcher_attach_to_gui(app->viewDispatcher, gui, ViewDispatcherTypeFullscreen); scene_manager_next_scene(app->sceneManager, app_scene_main); view_dispatcher_run(app->viewDispatcher); diff --git a/ModbusApp/Modbus.h b/ModbusApp/Modbus.h index f060fb81854..9d1606b02e8 100644 --- a/ModbusApp/Modbus.h +++ b/ModbusApp/Modbus.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -120,6 +122,7 @@ typedef struct { uint8_t msgBuf[RX_BUF_SIZE + 1]; size_t msgLen; RingBuffer* ringBuffer; + Expansion* expansion; } App; typedef enum { @@ -152,5 +155,4 @@ extern const char* parityValues[]; extern const char* saveLOGValues[]; extern const char* outputFormatValues[]; extern const char* functionNames[]; -extern const char* exceptionCodes[]; -uint16_t getCRC(uint8_t* buf, uint8_t len); \ No newline at end of file +extern const char* exceptionCodes[]; \ No newline at end of file diff --git a/ModbusApp/modbus_parser/modbus_parser.c b/ModbusApp/modbus_parser/modbus_parser.c index 448592fa38a..21717e87a4c 100644 --- a/ModbusApp/modbus_parser/modbus_parser.c +++ b/ModbusApp/modbus_parser/modbus_parser.c @@ -3,6 +3,23 @@ #include "../Modbus.h" #include "../modbus_ring_buffer/modbus_ring_buffer.h" +uint16_t getCRC(uint8_t* buf, uint8_t len) { + uint16_t crc = 0xFFFF; + + for(int pos = 0; pos < len; pos++) { + crc ^= (uint16_t)buf[pos]; + + for(int i = 8; i != 0; i--) { + if((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; + } else + crc >>= 1; + } + } + return crc; +} + static void discreteValuesParser(void* context, uint8_t* buff, size_t len, FuriString* data) { App* app = context; uint8_t value = 0; diff --git a/ModbusApp/modbus_parser/modbus_parser.h b/ModbusApp/modbus_parser/modbus_parser.h index e46d395a32d..27b34d74a5a 100644 --- a/ModbusApp/modbus_parser/modbus_parser.h +++ b/ModbusApp/modbus_parser/modbus_parser.h @@ -3,3 +3,4 @@ #include void handle_rx_data_cb(uint8_t* buf, size_t len, void* context); +uint16_t getCRC(uint8_t* buf, uint8_t len); diff --git a/ModbusApp/modbus_sender/modbus_sender.c b/ModbusApp/modbus_sender/modbus_sender.c index dbb41213f75..9cdb94ad02e 100644 --- a/ModbusApp/modbus_sender/modbus_sender.c +++ b/ModbusApp/modbus_sender/modbus_sender.c @@ -1,4 +1,5 @@ #include "modbus_sender.h" +#include "../modbus_parser/modbus_parser.h" void ModbusSender(void* context) { App* app = context; diff --git a/ModbusApp/scenes/msgs_buffer_scene.c b/ModbusApp/scenes/msgs_buffer_scene.c index 1762978cbb0..a740d53b3fa 100644 --- a/ModbusApp/scenes/msgs_buffer_scene.c +++ b/ModbusApp/scenes/msgs_buffer_scene.c @@ -1,6 +1,6 @@ #include "../Modbus.h" +#include "../modbus_parser/modbus_parser.h" -////////////////////////// MSGsBuffer Scene //////////////////////// void OnItemEnterCB(void* context, uint32_t index) { App* app = context; uint8_t start = index ? app->ringBuffer->delimiters[index - 1] + 1 : 0; diff --git a/ModbusApp/scenes/settings_scene.c b/ModbusApp/scenes/settings_scene.c index b0fc6ac0689..f7007e84797 100644 --- a/ModbusApp/scenes/settings_scene.c +++ b/ModbusApp/scenes/settings_scene.c @@ -2,7 +2,8 @@ #include "../modbus_storage/modbus_storage.h" #include "../modbus_uart/modbus_uart.h" -////////////////////////// Settings Scene ////////////////////////// + + void itemChangedCB(VariableItem* item) { App* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); From b033a77a9e782ef961e230c4e5ad6fa517f8880f Mon Sep 17 00:00:00 2001 From: Roberto Arellano Date: Wed, 21 Aug 2024 14:43:07 -0600 Subject: [PATCH 3/3] fix: precommit --- ModbusApp/Modbus.h | 3 +- .../modbus_ring_buffer/modbus_ring_buffer.c | 2 +- .../modbus_ring_buffer/modbus_ring_buffer.h | 4 +- ModbusApp/modbus_sender/modbus_sender.c | 2 +- ModbusApp/modbus_sender/modbus_sender.h | 2 +- ModbusApp/modbus_storage/modbus_storage.c | 2 +- ModbusApp/modbus_storage/modbus_storage.h | 2 +- ModbusApp/modbus_uart/modbus_uart.c | 2 +- ModbusApp/modbus_uart/modbus_uart.h | 2 +- ModbusApp/scenes/byte_input_scene.c | 81 ++--- ModbusApp/scenes/main_scene.c | 92 +++-- ModbusApp/scenes/manual_sender_scene.c | 328 +++++++++--------- ModbusApp/scenes/msgs_buffer_scene.c | 74 ++-- ModbusApp/scenes/sender_scene.c | 48 ++- ModbusApp/scenes/settings_scene.c | 174 ++++------ ModbusApp/scenes/sniffer_scene.c | 93 +++-- ModbusApp/scenes_config/app_scene_config.h | 1 - ModbusApp/scenes_config/app_scene_functions.c | 3 +- ModbusApp/scenes_config/app_scene_functions.h | 13 +- 19 files changed, 432 insertions(+), 496 deletions(-) diff --git a/ModbusApp/Modbus.h b/ModbusApp/Modbus.h index 9d1606b02e8..95433df3b05 100644 --- a/ModbusApp/Modbus.h +++ b/ModbusApp/Modbus.h @@ -19,7 +19,6 @@ #include "scenes_config/app_scene_functions.h" - #define PATHAPP "apps_data/modbus" #define PATHAPPEXT EXT_PATH(PATHAPP) #define PATHLOGS PATHAPPEXT "/logs" @@ -155,4 +154,4 @@ extern const char* parityValues[]; extern const char* saveLOGValues[]; extern const char* outputFormatValues[]; extern const char* functionNames[]; -extern const char* exceptionCodes[]; \ No newline at end of file +extern const char* exceptionCodes[]; diff --git a/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c index 1c4af91c20f..34d9ab70be5 100644 --- a/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c +++ b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c @@ -21,4 +21,4 @@ void writeRingBuffer(RingBuffer* rb, uint8_t* buf, size_t len) { } } rb->delimiterIdx++; -} \ No newline at end of file +} diff --git a/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h index 683ffd4a50e..e6bb99398cd 100644 --- a/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h +++ b/ModbusApp/modbus_ring_buffer/modbus_ring_buffer.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include @@ -6,4 +6,4 @@ RingBuffer* ring_buffer_alloc(); void ring_buffer_free(RingBuffer* buffer); -void writeRingBuffer(RingBuffer* rb, uint8_t* buf, size_t len); \ No newline at end of file +void writeRingBuffer(RingBuffer* rb, uint8_t* buf, size_t len); diff --git a/ModbusApp/modbus_sender/modbus_sender.c b/ModbusApp/modbus_sender/modbus_sender.c index 9cdb94ad02e..5653500b297 100644 --- a/ModbusApp/modbus_sender/modbus_sender.c +++ b/ModbusApp/modbus_sender/modbus_sender.c @@ -16,4 +16,4 @@ void ModbusSender(void* context) { furi_hal_gpio_write(&gpio_ext_pc1, false); app->modbus->slave = true; furi_timer_start(app->timer, app->uart->cfg->timeout * TIMEOUT_SCALER); -} \ No newline at end of file +} diff --git a/ModbusApp/modbus_sender/modbus_sender.h b/ModbusApp/modbus_sender/modbus_sender.h index a5242144438..1aaaee35bc6 100644 --- a/ModbusApp/modbus_sender/modbus_sender.h +++ b/ModbusApp/modbus_sender/modbus_sender.h @@ -4,4 +4,4 @@ #include "../Modbus.h" -void ModbusSender(void* context); \ No newline at end of file +void ModbusSender(void* context); diff --git a/ModbusApp/modbus_storage/modbus_storage.c b/ModbusApp/modbus_storage/modbus_storage.c index 13308581a7f..63e89b043ef 100644 --- a/ModbusApp/modbus_storage/modbus_storage.c +++ b/ModbusApp/modbus_storage/modbus_storage.c @@ -59,4 +59,4 @@ bool OpenLogFile(App* app) { furi_string_free(selected_filepath); furi_string_free(predefined_filepath); return true; -} \ No newline at end of file +} diff --git a/ModbusApp/modbus_storage/modbus_storage.h b/ModbusApp/modbus_storage/modbus_storage.h index 087716f5678..b7fc2f6c54c 100644 --- a/ModbusApp/modbus_storage/modbus_storage.h +++ b/ModbusApp/modbus_storage/modbus_storage.h @@ -10,4 +10,4 @@ char* sequential_file_resolve_path( const char* prefix, const char* extension); bool OpenLogFile(App* app); -void makePaths(App* app); \ No newline at end of file +void makePaths(App* app); diff --git a/ModbusApp/modbus_uart/modbus_uart.c b/ModbusApp/modbus_uart/modbus_uart.c index 4b5484394df..89e68d2cd12 100644 --- a/ModbusApp/modbus_uart/modbus_uart.c +++ b/ModbusApp/modbus_uart/modbus_uart.c @@ -124,4 +124,4 @@ int32_t uart_worker(void* context) { } return 0; -} \ No newline at end of file +} diff --git a/ModbusApp/modbus_uart/modbus_uart.h b/ModbusApp/modbus_uart/modbus_uart.h index af8c9128236..3151daacff0 100644 --- a/ModbusApp/modbus_uart/modbus_uart.h +++ b/ModbusApp/modbus_uart/modbus_uart.h @@ -9,4 +9,4 @@ void Serial_Begin(FuriHalSerialHandle* handle, LL_USART_InitTypeDef USART_InitSt int32_t uart_worker(void* context); void timerDone(void* context); void serial_deinit(Uart* uart); -void serial_init(Uart* uart, uint8_t uart_ch); \ No newline at end of file +void serial_init(Uart* uart, uint8_t uart_ch); diff --git a/ModbusApp/scenes/byte_input_scene.c b/ModbusApp/scenes/byte_input_scene.c index 5dfff2a00e8..bd1a4b1cd7d 100644 --- a/ModbusApp/scenes/byte_input_scene.c +++ b/ModbusApp/scenes/byte_input_scene.c @@ -2,57 +2,52 @@ ////////////////////////// ByteInput Scene //////////////////////// void SetValue(void* context) { - App* app = context; - scene_manager_handle_back_event(app->sceneManager); + App* app = context; + scene_manager_handle_back_event(app->sceneManager); } void app_scene_byte_input_on_enter(void* context) { - App* app = context; - uint8_t* buf = app->msgBuf; - uint8_t offset = - scene_manager_get_scene_state(app->sceneManager, app_scene_byte_input); - switch (scene_manager_get_scene_state(app->sceneManager, app_scene_byte_input)) { + App* app = context; + uint8_t* buf = app->msgBuf; + uint8_t offset = scene_manager_get_scene_state(app->sceneManager, app_scene_byte_input); + switch(scene_manager_get_scene_state(app->sceneManager, app_scene_byte_input)) { case 0: - byte_input_set_header_text(app->byteInput, "Set Slave"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, - &SLAVE, 1); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; + byte_input_set_header_text(app->byteInput, "Set Slave"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &SLAVE, 1); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; case 1: - byte_input_set_header_text(app->byteInput, "Set Function"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, - &FUNCTION, 1); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; + byte_input_set_header_text(app->byteInput, "Set Function"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &FUNCTION, 1); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; case 2: - byte_input_set_header_text(app->byteInput, "Set Address"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, - &buf[2], 2); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; + byte_input_set_header_text(app->byteInput, "Set Address"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &buf[2], 2); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; case 3: - byte_input_set_header_text(app->byteInput, "Set value or quantity"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, - &buf[4], 2); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; + byte_input_set_header_text(app->byteInput, "Set value or quantity"); + byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, &buf[4], 2); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; default: - if (FUNCTION == 0x0F) - offset += 2; - else - offset += offset - 3; - byte_input_set_header_text(app->byteInput, "Set x value"); - byte_input_set_result_callback(app->byteInput, SetValue, NULL, app, - &buf[offset], FUNCTION == 0x0F ? 1 : 2); - view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); - break; - } + if(FUNCTION == 0x0F) + offset += 2; + else + offset += offset - 3; + byte_input_set_header_text(app->byteInput, "Set x value"); + byte_input_set_result_callback( + app->byteInput, SetValue, NULL, app, &buf[offset], FUNCTION == 0x0F ? 1 : 2); + view_dispatcher_switch_to_view(app->viewDispatcher, ByteInput_View); + break; + } } bool app_scene_byte_input_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + UNUSED(context); + UNUSED(event); + return false; } void app_scene_byte_input_on_exit(void* context) { - App* app = context; - UNUSED(app); -} \ No newline at end of file + App* app = context; + UNUSED(app); +} diff --git a/ModbusApp/scenes/main_scene.c b/ModbusApp/scenes/main_scene.c index 0cde7cbb1b5..46067c9240d 100644 --- a/ModbusApp/scenes/main_scene.c +++ b/ModbusApp/scenes/main_scene.c @@ -3,68 +3,58 @@ ////////////////////////// Main Scene ////////////////////////// void mainOptionsCB(void* context, uint32_t index) { - App* app = context; + App* app = context; - switch (index) { + switch(index) { case Settings_Option: - scene_manager_set_scene_state(app->sceneManager, app_scene_main, - Settings_Option); - scene_manager_next_scene(app->sceneManager, app_scene_settings); - break; + scene_manager_set_scene_state(app->sceneManager, app_scene_main, Settings_Option); + scene_manager_next_scene(app->sceneManager, app_scene_settings); + break; case Sniffer_Option: - scene_manager_set_scene_state(app->sceneManager, app_scene_main, - Sniffer_Option); - scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, - Sniffer_Option); - scene_manager_next_scene(app->sceneManager, app_scene_sniffer); - break; + scene_manager_set_scene_state(app->sceneManager, app_scene_main, Sniffer_Option); + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, Sniffer_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + break; case Sender_Option: - scene_manager_set_scene_state(app->sceneManager, app_scene_main, - Sender_Option); - scene_manager_next_scene(app->sceneManager, app_scene_sender); - break; + scene_manager_set_scene_state(app->sceneManager, app_scene_main, Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sender); + break; case Read_LOG_Option: - scene_manager_set_scene_state(app->sceneManager, app_scene_main, - Read_LOG_Option); - if (OpenLogFile(app)) { - scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, - Read_LOG_Option); - scene_manager_next_scene(app->sceneManager, app_scene_sniffer); - } - break; + scene_manager_set_scene_state(app->sceneManager, app_scene_main, Read_LOG_Option); + if(OpenLogFile(app)) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, Read_LOG_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + } + break; case About_Option: - scene_manager_set_scene_state(app->sceneManager, app_scene_main, - About_Option); - scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, - About_Option); - scene_manager_next_scene(app->sceneManager, app_scene_sniffer); - break; + scene_manager_set_scene_state(app->sceneManager, app_scene_main, About_Option); + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, About_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + break; default: - break; - } + break; + } } void app_scene_main_on_enter(void* context) { - App* app = context; - submenu_reset(app->subMenu); - submenu_set_header(app->subMenu, "Main"); - submenu_add_item(app->subMenu, "Settings", Settings_Option, mainOptionsCB, - app); - submenu_add_item(app->subMenu, "Sniffer", Sniffer_Option, mainOptionsCB, app); - submenu_add_item(app->subMenu, "Sender", Sender_Option, mainOptionsCB, app); - submenu_add_item(app->subMenu, "Read LOG", Read_LOG_Option, mainOptionsCB, - app); - submenu_add_item(app->subMenu, "About", About_Option, mainOptionsCB, app); - submenu_set_selected_item(app->subMenu, scene_manager_get_scene_state( - app->sceneManager, app_scene_main)); - view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); + App* app = context; + submenu_reset(app->subMenu); + submenu_set_header(app->subMenu, "Main"); + submenu_add_item(app->subMenu, "Settings", Settings_Option, mainOptionsCB, app); + submenu_add_item(app->subMenu, "Sniffer", Sniffer_Option, mainOptionsCB, app); + submenu_add_item(app->subMenu, "Sender", Sender_Option, mainOptionsCB, app); + submenu_add_item(app->subMenu, "Read LOG", Read_LOG_Option, mainOptionsCB, app); + submenu_add_item(app->subMenu, "About", About_Option, mainOptionsCB, app); + submenu_set_selected_item( + app->subMenu, scene_manager_get_scene_state(app->sceneManager, app_scene_main)); + view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); } bool app_scene_main_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + UNUSED(context); + UNUSED(event); + return false; } void app_scene_main_on_exit(void* context) { - App* app = context; - submenu_reset(app->subMenu); -} \ No newline at end of file + App* app = context; + submenu_reset(app->subMenu); +} diff --git a/ModbusApp/scenes/manual_sender_scene.c b/ModbusApp/scenes/manual_sender_scene.c index 47764ffc039..faa4e19809a 100644 --- a/ModbusApp/scenes/manual_sender_scene.c +++ b/ModbusApp/scenes/manual_sender_scene.c @@ -3,201 +3,189 @@ void BuildSender(App* app, uint8_t* buf); ////////////////////////// Manual Sender Scene ////////////////////////// -const char* fns[] = {"0x01", "0x02", "0x03", "0x04", - "0x05", "0x06", "0x0F", "0x10"}; +const char* fns[] = {"0x01", "0x02", "0x03", "0x04", "0x05", "0x06", "0x0F", "0x10"}; void itemChangeCB(VariableItem* item) { - App* app = variable_item_get_context(item); - uint8_t* buf = app->msgBuf; - uint8_t index = variable_item_get_current_value_index(item); - uint8_t selectedIndex = - variable_item_list_get_selected_item_index(app->varList); - uint16_t Value; - char str[10]; - switch (selectedIndex) { + App* app = variable_item_get_context(item); + uint8_t* buf = app->msgBuf; + uint8_t index = variable_item_get_current_value_index(item); + uint8_t selectedIndex = variable_item_list_get_selected_item_index(app->varList); + uint16_t Value; + char str[10]; + switch(selectedIndex) { case 0: - snprintf(str, sizeof(str), "%d", index + 1); - variable_item_set_current_value_text(item, strdup(str)); - buf[0] = index + 1; - break; + snprintf(str, sizeof(str), "%d", index + 1); + variable_item_set_current_value_text(item, strdup(str)); + buf[0] = index + 1; + break; case 1: - variable_item_set_current_value_text(item, fns[index]); - FUNCTION = index <= 0x05 ? index + 1 : index + 9; - buf[4] = 0; - buf[5] = 1; - BuildSender(app, buf); - break; + variable_item_set_current_value_text(item, fns[index]); + FUNCTION = index <= 0x05 ? index + 1 : index + 9; + buf[4] = 0; + buf[5] = 1; + BuildSender(app, buf); + break; case 2: - snprintf(str, sizeof(str), "%d", index); - variable_item_set_current_value_text(item, strdup(str)); - buf[2] = index >> 8 & 0x00FF; - buf[3] = index & 0x00FF; - break; - case 3: - if (FUNCTION != 0x05 && FUNCTION != 0x06) { - index++; snprintf(str, sizeof(str), "%d", index); variable_item_set_current_value_text(item, strdup(str)); - buf[4] = index >> 8 & 0x00FF; - buf[5] = index & 0x00FF; - if (FUNCTION >= 0x0F) { - Value = (buf[4] << 8 | buf[5]); - if (FUNCTION == 0x0F) - Value = Value % 8 ? Value / 8 + 1 : Value / 8; - else - Value = Value * 2; - item = variable_item_list_get(app->varList, 4); - snprintf(str, sizeof(str), "[ %d ]", Value); - variable_item_set_current_value_text(item, strdup(str)); - if (BYTECOUNT != Value) { - BYTECOUNT = Value; - BuildSender(app, buf); - } + buf[2] = index >> 8 & 0x00FF; + buf[3] = index & 0x00FF; + break; + case 3: + if(FUNCTION != 0x05 && FUNCTION != 0x06) { + index++; + snprintf(str, sizeof(str), "%d", index); + variable_item_set_current_value_text(item, strdup(str)); + buf[4] = index >> 8 & 0x00FF; + buf[5] = index & 0x00FF; + if(FUNCTION >= 0x0F) { + Value = (buf[4] << 8 | buf[5]); + if(FUNCTION == 0x0F) + Value = Value % 8 ? Value / 8 + 1 : Value / 8; + else + Value = Value * 2; + item = variable_item_list_get(app->varList, 4); + snprintf(str, sizeof(str), "[ %d ]", Value); + variable_item_set_current_value_text(item, strdup(str)); + if(BYTECOUNT != Value) { + BYTECOUNT = Value; + BuildSender(app, buf); + } + } + } else { + Value = FUNCTION == 5 ? index ? 0xFF00 : 0x0000 : index; + snprintf(str, sizeof(str), "0x%04X", Value); + variable_item_set_current_value_text( + item, FUNCTION == 0x05 ? index ? "ON" : "OFF" : str); + buf[4] = Value >> 8 & 0x00FF; + buf[5] = Value & 0x00FF; } - } else { - Value = FUNCTION == 5 ? index ? 0xFF00 : 0x0000 : index; - snprintf(str, sizeof(str), "0x%04X", Value); - variable_item_set_current_value_text( - item, FUNCTION == 0x05 ? index ? "ON" : "OFF" : str); - buf[4] = Value >> 8 & 0x00FF; - buf[5] = Value & 0x00FF; - } - break; + break; default: - Value = index; - snprintf(str, sizeof(str), FUNCTION == 0x10 ? "0x%04X" : "0x%02X", Value); - variable_item_set_current_value_text(item, str); - if (FUNCTION == 0x0F) { - selectedIndex += 2; - buf[selectedIndex] = Value; - } else { - selectedIndex += selectedIndex - 3; + Value = index; + snprintf(str, sizeof(str), FUNCTION == 0x10 ? "0x%04X" : "0x%02X", Value); + variable_item_set_current_value_text(item, str); + if(FUNCTION == 0x0F) { + selectedIndex += 2; + buf[selectedIndex] = Value; + } else { + selectedIndex += selectedIndex - 3; - buf[selectedIndex] = Value >> 8 & 0x0FF; - buf[selectedIndex + 1] = Value & 0x00FF; - } - break; - } + buf[selectedIndex] = Value >> 8 & 0x0FF; + buf[selectedIndex + 1] = Value & 0x00FF; + } + break; + } } void itemEnterCB(void* context, uint32_t index) { - App* app = context; - uint8_t* buf = app->msgBuf; - uint8_t SendButton = - FUNCTION >= 0x0F ? (FUNCTION == 0x0F ? BYTECOUNT : QUANTITY) + 5 : 4; - scene_manager_set_scene_state(app->sceneManager, app_scene_manual_sender, index); - if (index == SendButton) { - scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, - Sender_Option); - scene_manager_next_scene(app->sceneManager, app_scene_sniffer); - } + App* app = context; + uint8_t* buf = app->msgBuf; + uint8_t SendButton = FUNCTION >= 0x0F ? (FUNCTION == 0x0F ? BYTECOUNT : QUANTITY) + 5 : 4; + scene_manager_set_scene_state(app->sceneManager, app_scene_manual_sender, index); + if(index == SendButton) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sniffer, Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_sniffer); + } - else if (index == 1 || (FUNCTION >= 0x0F && index == 4)) { - } else { - if (!(FUNCTION == 0x05 && index == 3)) { - scene_manager_set_scene_state(app->sceneManager, app_scene_byte_input, index); - scene_manager_next_scene(app->sceneManager, app_scene_byte_input); + else if(index == 1 || (FUNCTION >= 0x0F && index == 4)) { + } else { + if(!(FUNCTION == 0x05 && index == 3)) { + scene_manager_set_scene_state(app->sceneManager, app_scene_byte_input, index); + scene_manager_next_scene(app->sceneManager, app_scene_byte_input); + } } - } } void BuildValues(App* app, uint16_t byteCount, uint8_t* buf, bool one) { - VariableItem* item; - char lbl[20]; - char val[10]; - for (uint16_t i = 0; i < byteCount; i += one ? 1 : 2) { - snprintf(lbl, sizeof(lbl), one ? "Byte %d" : "Register %d", - one ? i + 1 : i / 2 + 1); - snprintf(val, sizeof(val), one ? "0x%02X" : "0x%04X", - one ? buf[i] : buf[i] << 8 | buf[i + 1]); - item = variable_item_list_add(app->varList, strdup(lbl), 255, itemChangeCB, - app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index( - item, MIN(255, one ? buf[i] : buf[i] << 8 | buf[i + 1])); - } + VariableItem* item; + char lbl[20]; + char val[10]; + for(uint16_t i = 0; i < byteCount; i += one ? 1 : 2) { + snprintf(lbl, sizeof(lbl), one ? "Byte %d" : "Register %d", one ? i + 1 : i / 2 + 1); + snprintf( + val, sizeof(val), one ? "0x%02X" : "0x%04X", one ? buf[i] : buf[i] << 8 | buf[i + 1]); + item = variable_item_list_add(app->varList, strdup(lbl), 255, itemChangeCB, app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index( + item, MIN(255, one ? buf[i] : buf[i] << 8 | buf[i + 1])); + } } void BuildSender(App* app, uint8_t* buf) { - variable_item_list_reset(app->varList); - VariableItem* item; - uint16_t Value = 0; - char val[10]; - SLAVE = MIN(SLAVE, 32); - snprintf(val, sizeof(val), "%d", SLAVE); - item = variable_item_list_add(app->varList, "Peripheral ID", 32, itemChangeCB, - app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, SLAVE - 1); - item = variable_item_list_add(app->varList, "Function", 8, itemChangeCB, app); - variable_item_set_current_value_text( - item, fns[FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9]); - variable_item_set_current_value_index( - item, FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9); - Value = STARTADDRESS; - snprintf(val, sizeof(val), "%d", Value); - item = variable_item_list_add(app->varList, "Start Address", 255, - itemChangeCB, app); - variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, MIN(255, STARTADDRESS)); - if (FUNCTION != 0x05 && FUNCTION != 0x06) { - uint16_t max = FUNCTION == 0x10 ? 0x0A - : FUNCTION == 0x0F ? 0x50 - : FUNCTION <= 0x02 ? 0x7D0 - : 0x7D; - Value = MIN(buf[4] << 8 | buf[5], max); - snprintf(val, sizeof(val), "%d", Value); - item = variable_item_list_add(app->varList, "Quantity", max, itemChangeCB, - app); + variable_item_list_reset(app->varList); + VariableItem* item; + uint16_t Value = 0; + char val[10]; + SLAVE = MIN(SLAVE, 32); + snprintf(val, sizeof(val), "%d", SLAVE); + item = variable_item_list_add(app->varList, "Peripheral ID", 32, itemChangeCB, app); variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, MIN(Value - 1, MIN(max, 255))); - buf[4] = Value >> 8 & 0x00FF; - buf[5] = Value & 0x00FF; - } else { - Value = buf[4] << 8 | buf[5]; - snprintf(val, sizeof(val), "0x%04X", Value); - item = variable_item_list_add( - app->varList, "Value", FUNCTION == 0x05 ? 2 : 255, itemChangeCB, app); - variable_item_set_current_value_text( - item, FUNCTION == 0x05 ? Value ? "ON" : "OFF" : strdup(val)); - variable_item_set_current_value_index( - item, FUNCTION == 0x05 ? Value ? 1 : 0 : MIN(Value, 255)); - Value = FUNCTION == 5 ? Value ? 0xFF00 : 0x0000 : Value; - buf[4] = Value >> 8 & 0x00FF; - buf[5] = Value & 0x00FF; - } - if (FUNCTION >= 0x0F) { - Value = (buf[4] << 8 | buf[5]); - if (FUNCTION == 0x0F) - Value = Value % 8 ? Value / 8 + 1 : Value / 8; - else - Value = Value * 2; - snprintf(val, sizeof(val), "[ %d ]", Value); - item = variable_item_list_add(app->varList, "ByteCount", 1, NULL, app); + variable_item_set_current_value_index(item, SLAVE - 1); + item = variable_item_list_add(app->varList, "Function", 8, itemChangeCB, app); + variable_item_set_current_value_text(item, fns[FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9]); + variable_item_set_current_value_index(item, FUNCTION <= 6 ? FUNCTION - 1 : FUNCTION - 9); + Value = STARTADDRESS; + snprintf(val, sizeof(val), "%d", Value); + item = variable_item_list_add(app->varList, "Start Address", 255, itemChangeCB, app); variable_item_set_current_value_text(item, strdup(val)); - variable_item_set_current_value_index(item, 0); - BYTECOUNT = Value; - app->msgLen = Value + 9; - BuildValues(app, Value, buf + 7, FUNCTION == 0x0F ? true : false); - } + variable_item_set_current_value_index(item, MIN(255, STARTADDRESS)); + if(FUNCTION != 0x05 && FUNCTION != 0x06) { + uint16_t max = FUNCTION == 0x10 ? 0x0A : + FUNCTION == 0x0F ? 0x50 : + FUNCTION <= 0x02 ? 0x7D0 : + 0x7D; + Value = MIN(buf[4] << 8 | buf[5], max); + snprintf(val, sizeof(val), "%d", Value); + item = variable_item_list_add(app->varList, "Quantity", max, itemChangeCB, app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index(item, MIN(Value - 1, MIN(max, 255))); + buf[4] = Value >> 8 & 0x00FF; + buf[5] = Value & 0x00FF; + } else { + Value = buf[4] << 8 | buf[5]; + snprintf(val, sizeof(val), "0x%04X", Value); + item = variable_item_list_add( + app->varList, "Value", FUNCTION == 0x05 ? 2 : 255, itemChangeCB, app); + variable_item_set_current_value_text( + item, FUNCTION == 0x05 ? Value ? "ON" : "OFF" : strdup(val)); + variable_item_set_current_value_index( + item, FUNCTION == 0x05 ? Value ? 1 : 0 : MIN(Value, 255)); + Value = FUNCTION == 5 ? Value ? 0xFF00 : 0x0000 : Value; + buf[4] = Value >> 8 & 0x00FF; + buf[5] = Value & 0x00FF; + } + if(FUNCTION >= 0x0F) { + Value = (buf[4] << 8 | buf[5]); + if(FUNCTION == 0x0F) + Value = Value % 8 ? Value / 8 + 1 : Value / 8; + else + Value = Value * 2; + snprintf(val, sizeof(val), "[ %d ]", Value); + item = variable_item_list_add(app->varList, "ByteCount", 1, NULL, app); + variable_item_set_current_value_text(item, strdup(val)); + variable_item_set_current_value_index(item, 0); + BYTECOUNT = Value; + app->msgLen = Value + 9; + BuildValues(app, Value, buf + 7, FUNCTION == 0x0F ? true : false); + } - item = variable_item_list_add(app->varList, "Send Packet", 1, NULL, app); - variable_item_list_set_enter_callback(app->varList, itemEnterCB, app); - variable_item_set_current_value_text(item, ""); - variable_item_set_current_value_index(item, 0); + item = variable_item_list_add(app->varList, "Send Packet", 1, NULL, app); + variable_item_list_set_enter_callback(app->varList, itemEnterCB, app); + variable_item_set_current_value_text(item, ""); + variable_item_set_current_value_index(item, 0); } void app_scene_manual_sender_on_enter(void* context) { - App* app = context; - BuildSender(app, app->msgBuf); - variable_item_list_set_selected_item( - app->varList, - scene_manager_get_scene_state(app->sceneManager, app_scene_manual_sender)); - view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); + App* app = context; + BuildSender(app, app->msgBuf); + variable_item_list_set_selected_item( + app->varList, scene_manager_get_scene_state(app->sceneManager, app_scene_manual_sender)); + view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); } bool app_scene_manual_sender_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + UNUSED(context); + UNUSED(event); + return false; } void app_scene_manual_sender_on_exit(void* context) { - App* app = context; - variable_item_list_reset(app->varList); -} \ No newline at end of file + App* app = context; + variable_item_list_reset(app->varList); +} diff --git a/ModbusApp/scenes/msgs_buffer_scene.c b/ModbusApp/scenes/msgs_buffer_scene.c index a740d53b3fa..48df14576ef 100644 --- a/ModbusApp/scenes/msgs_buffer_scene.c +++ b/ModbusApp/scenes/msgs_buffer_scene.c @@ -2,50 +2,48 @@ #include "../modbus_parser/modbus_parser.h" void OnItemEnterCB(void* context, uint32_t index) { - App* app = context; - uint8_t start = index ? app->ringBuffer->delimiters[index - 1] + 1 : 0; - for (uint8_t i = start; i <= app->ringBuffer->delimiters[index]; i++) { - app->msgBuf[i - start] = app->ringBuffer->ringBuffer[i]; - if (i == app->ringBuffer->delimiters[index]) - app->msgLen = i - start + 1; - } - scene_manager_next_scene(app->sceneManager, app_scene_manual_sender); + App* app = context; + uint8_t start = index ? app->ringBuffer->delimiters[index - 1] + 1 : 0; + for(uint8_t i = start; i <= app->ringBuffer->delimiters[index]; i++) { + app->msgBuf[i - start] = app->ringBuffer->ringBuffer[i]; + if(i == app->ringBuffer->delimiters[index]) app->msgLen = i - start + 1; + } + scene_manager_next_scene(app->sceneManager, app_scene_manual_sender); } void BuildCMDList(App* app) { - submenu_set_header(app->subMenu, " ID | FN |Adss"); - RingBuffer* rb = app->ringBuffer; - rb->readIdx = 0; - uint8_t buf[255]; - uint8_t i = 0; - uint8_t delimiterIdx = 0; - uint8_t len = 0; - char lbl[30]; - do { - len = 0; + submenu_set_header(app->subMenu, " ID | FN |Adss"); + RingBuffer* rb = app->ringBuffer; + rb->readIdx = 0; + uint8_t buf[255]; + uint8_t i = 0; + uint8_t delimiterIdx = 0; + uint8_t len = 0; + char lbl[30]; do { - snprintf(lbl, sizeof(lbl), " %d | %d | %d |", SLAVE, FUNCTION, - STARTADDRESS); - buf[len] = rb->ringBuffer[i]; - len++; - i++; - } while (i <= rb->delimiters[delimiterIdx] && i < 255); - delimiterIdx++; - if ((CRCH | CRCL << 8) == getCRC(buf, len - 2)) - submenu_add_item(app->subMenu, lbl, delimiterIdx - 1, OnItemEnterCB, app); - } while (i < 255); + len = 0; + do { + snprintf(lbl, sizeof(lbl), " %d | %d | %d |", SLAVE, FUNCTION, STARTADDRESS); + buf[len] = rb->ringBuffer[i]; + len++; + i++; + } while(i <= rb->delimiters[delimiterIdx] && i < 255); + delimiterIdx++; + if((CRCH | CRCL << 8) == getCRC(buf, len - 2)) + submenu_add_item(app->subMenu, lbl, delimiterIdx - 1, OnItemEnterCB, app); + } while(i < 255); } void app_scene_msgs_buffer_on_enter(void* context) { - App* app = context; - submenu_reset(app->subMenu); - BuildCMDList(app); - view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); + App* app = context; + submenu_reset(app->subMenu); + BuildCMDList(app); + view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); } bool app_scene_msgs_buffer_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + UNUSED(context); + UNUSED(event); + return false; } void app_scene_msgs_buffer_on_exit(void* context) { - App* app = context; - submenu_reset(app->subMenu); -} \ No newline at end of file + App* app = context; + submenu_reset(app->subMenu); +} diff --git a/ModbusApp/scenes/sender_scene.c b/ModbusApp/scenes/sender_scene.c index 097ab09206d..3eddcc00d34 100644 --- a/ModbusApp/scenes/sender_scene.c +++ b/ModbusApp/scenes/sender_scene.c @@ -2,35 +2,31 @@ ////////////////////////// Sender Scene //////////////////////// void SenderOptionsCB(void* context, uint32_t index) { - App* app = context; - if (index == Manual_Sender_Option) { - scene_manager_set_scene_state(app->sceneManager, app_scene_sender, - Manual_Sender_Option); - scene_manager_next_scene(app->sceneManager, app_scene_manual_sender); - } else if (index == Buffer_Sender_Option) { - scene_manager_set_scene_state(app->sceneManager, app_scene_sender, - Buffer_Sender_Option); - scene_manager_next_scene(app->sceneManager, app_scene_msgs_buffer); - } + App* app = context; + if(index == Manual_Sender_Option) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sender, Manual_Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_manual_sender); + } else if(index == Buffer_Sender_Option) { + scene_manager_set_scene_state(app->sceneManager, app_scene_sender, Buffer_Sender_Option); + scene_manager_next_scene(app->sceneManager, app_scene_msgs_buffer); + } } void app_scene_sender_on_enter(void* context) { - App* app = context; - submenu_reset(app->subMenu); - submenu_set_header(app->subMenu, "Sender"); - submenu_add_item(app->subMenu, "Manual Sender", Manual_Sender_Option, - SenderOptionsCB, app); - submenu_add_item(app->subMenu, "Buffer Sender", Buffer_Sender_Option, - SenderOptionsCB, app); - submenu_set_selected_item(app->subMenu, scene_manager_get_scene_state( - app->sceneManager, app_scene_main)); - view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); + App* app = context; + submenu_reset(app->subMenu); + submenu_set_header(app->subMenu, "Sender"); + submenu_add_item(app->subMenu, "Manual Sender", Manual_Sender_Option, SenderOptionsCB, app); + submenu_add_item(app->subMenu, "Buffer Sender", Buffer_Sender_Option, SenderOptionsCB, app); + submenu_set_selected_item( + app->subMenu, scene_manager_get_scene_state(app->sceneManager, app_scene_main)); + view_dispatcher_switch_to_view(app->viewDispatcher, Submenu_View); } bool app_scene_sender_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + UNUSED(context); + UNUSED(event); + return false; } void app_scene_sender_on_exit(void* context) { - App* app = context; - submenu_reset(app->subMenu); -} \ No newline at end of file + App* app = context; + submenu_reset(app->subMenu); +} diff --git a/ModbusApp/scenes/settings_scene.c b/ModbusApp/scenes/settings_scene.c index f7007e84797..dc3314ae30e 100644 --- a/ModbusApp/scenes/settings_scene.c +++ b/ModbusApp/scenes/settings_scene.c @@ -2,117 +2,97 @@ #include "../modbus_storage/modbus_storage.h" #include "../modbus_uart/modbus_uart.h" - - void itemChangedCB(VariableItem* item) { - App* app = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - uint8_t selectedIndex = - variable_item_list_get_selected_item_index(app->varList); - switch (selectedIndex) { + App* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + uint8_t selectedIndex = variable_item_list_get_selected_item_index(app->varList); + switch(selectedIndex) { case BaudRate_Option: - variable_item_set_current_value_text(item, baudrateValues[index]); - app->uart->cfg->baudrate = index; - break; + variable_item_set_current_value_text(item, baudrateValues[index]); + app->uart->cfg->baudrate = index; + break; case DataWidth_Option: - variable_item_set_current_value_text(item, dataWidthValues[index]); - app->uart->cfg->dataWidth = index; - break; + variable_item_set_current_value_text(item, dataWidthValues[index]); + app->uart->cfg->dataWidth = index; + break; case StopBits_Option: - variable_item_set_current_value_text(item, stopBitsValues[index]); - app->uart->cfg->stopBits = index; - break; + variable_item_set_current_value_text(item, stopBitsValues[index]); + app->uart->cfg->stopBits = index; + break; case Parity_Option: - variable_item_set_current_value_text(item, parityValues[index]); - app->uart->cfg->timeout = index; - break; + variable_item_set_current_value_text(item, parityValues[index]); + app->uart->cfg->timeout = index; + break; case TimeOut_Option: - app->uart->cfg->timeout = index; - variable_item_set_current_value_index(item, index); - furi_string_printf(app->modbus->timeout, "%d", index * TIMEOUT_SCALER); - variable_item_set_current_value_text( - item, furi_string_get_cstr(app->modbus->timeout)); - break; + app->uart->cfg->timeout = index; + variable_item_set_current_value_index(item, index); + furi_string_printf(app->modbus->timeout, "%d", index * TIMEOUT_SCALER); + variable_item_set_current_value_text(item, furi_string_get_cstr(app->modbus->timeout)); + break; case OutputFormat_Option: - variable_item_set_current_value_text(item, outputFormatValues[index]); - app->uart->cfg->hexOutput = index; - break; + variable_item_set_current_value_text(item, outputFormatValues[index]); + app->uart->cfg->hexOutput = index; + break; case SaveLOG_Option: - variable_item_set_current_value_text(item, saveLOGValues[index]); - app->uart->cfg->saveLOG = index; - break; + variable_item_set_current_value_text(item, saveLOGValues[index]); + app->uart->cfg->saveLOG = index; + break; default: - break; - } + break; + } } void app_scene_settings_on_enter(void* context) { - App* app = context; - VariableItem* item; - item = variable_item_list_add(app->varList, "Buadrate", BR_VALUES, - itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->baudrate); - variable_item_set_current_value_text( - item, baudrateValues[app->uart->cfg->baudrate]); - item = variable_item_list_add(app->varList, "Data size", DATAWIDTH_VALUES, - itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->dataWidth); - variable_item_set_current_value_text( - item, dataWidthValues[app->uart->cfg->dataWidth]); - item = variable_item_list_add(app->varList, "Stop bits", STOPBITS_VALUES, - itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->stopBits); - variable_item_set_current_value_text( - item, stopBitsValues[app->uart->cfg->stopBits]); - item = variable_item_list_add(app->varList, "Parity", PARITY_VALUES, - itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->parity); - variable_item_set_current_value_text(item, - parityValues[app->uart->cfg->parity]); - item = variable_item_list_add(app->varList, "TimeOut(ms)", TIMEOUT_VALUES, - itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->timeout); - furi_string_printf(app->modbus->timeout, "%d", - app->uart->cfg->timeout * TIMEOUT_SCALER); - variable_item_set_current_value_text( - item, furi_string_get_cstr(app->modbus->timeout)); - item = variable_item_list_add(app->varList, "Output Format", - DIGITALFORMAT_VALUES, itemChangedCB, app); - variable_item_set_current_value_index(item, - app->uart->cfg->hexOutput ? 1 : 0); - variable_item_set_current_value_text( - item, outputFormatValues[app->uart->cfg->hexOutput ? 1 : 0]); - item = variable_item_list_add(app->varList, "Save LOG?", SAVE_LOG_VALUES, - itemChangedCB, app); - variable_item_set_current_value_index(item, app->uart->cfg->saveLOG ? 1 : 0); - variable_item_set_current_value_text( - item, saveLOGValues[app->uart->cfg->saveLOG ? 1 : 0]); + App* app = context; + VariableItem* item; + item = variable_item_list_add(app->varList, "Buadrate", BR_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->baudrate); + variable_item_set_current_value_text(item, baudrateValues[app->uart->cfg->baudrate]); + item = variable_item_list_add(app->varList, "Data size", DATAWIDTH_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->dataWidth); + variable_item_set_current_value_text(item, dataWidthValues[app->uart->cfg->dataWidth]); + item = variable_item_list_add(app->varList, "Stop bits", STOPBITS_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->stopBits); + variable_item_set_current_value_text(item, stopBitsValues[app->uart->cfg->stopBits]); + item = variable_item_list_add(app->varList, "Parity", PARITY_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->parity); + variable_item_set_current_value_text(item, parityValues[app->uart->cfg->parity]); + item = variable_item_list_add(app->varList, "TimeOut(ms)", TIMEOUT_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->timeout); + furi_string_printf(app->modbus->timeout, "%d", app->uart->cfg->timeout * TIMEOUT_SCALER); + variable_item_set_current_value_text(item, furi_string_get_cstr(app->modbus->timeout)); + item = variable_item_list_add( + app->varList, "Output Format", DIGITALFORMAT_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->hexOutput ? 1 : 0); + variable_item_set_current_value_text( + item, outputFormatValues[app->uart->cfg->hexOutput ? 1 : 0]); + item = variable_item_list_add(app->varList, "Save LOG?", SAVE_LOG_VALUES, itemChangedCB, app); + variable_item_set_current_value_index(item, app->uart->cfg->saveLOG ? 1 : 0); + variable_item_set_current_value_text(item, saveLOGValues[app->uart->cfg->saveLOG ? 1 : 0]); - variable_item_list_set_selected_item(app->varList, 0); - view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); + variable_item_list_set_selected_item(app->varList, 0); + view_dispatcher_switch_to_view(app->viewDispatcher, VarList_View); } bool app_scene_settings_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + UNUSED(context); + UNUSED(event); + return false; } void app_scene_settings_on_exit(void* context) { - App* app = context; - if (app->uart->cfg->saveLOG) { - strcpy(app->logFilePath, - sequential_file_resolve_path(app->storage, PATHLOGS, "Log", "log")); - if (app->logFilePath != NULL) { - if (storage_file_open(app->LOGfile, app->logFilePath, FSAM_WRITE, - FSOM_CREATE_ALWAYS)) { - furi_string_reset(app->text); - app->LOGfileReady = true; - } else { - dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); - } - } else { - dialog_message_show_storage_error(app->dialogs, - "Cannot resolve log path"); + App* app = context; + if(app->uart->cfg->saveLOG) { + strcpy( + app->logFilePath, sequential_file_resolve_path(app->storage, PATHLOGS, "Log", "log")); + if(app->logFilePath != NULL) { + if(storage_file_open(app->LOGfile, app->logFilePath, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + furi_string_reset(app->text); + app->LOGfileReady = true; + } else { + dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); + } + } else { + dialog_message_show_storage_error(app->dialogs, "Cannot resolve log path"); + } } - } - uart_set_config(app); - variable_item_list_reset(app->varList); -} \ No newline at end of file + uart_set_config(app); + variable_item_list_reset(app->varList); +} diff --git a/ModbusApp/scenes/sniffer_scene.c b/ModbusApp/scenes/sniffer_scene.c index d75d7fba406..e1f0974018f 100644 --- a/ModbusApp/scenes/sniffer_scene.c +++ b/ModbusApp/scenes/sniffer_scene.c @@ -3,56 +3,51 @@ ////////////////////////// Sniffer Scene ////////////////////////// void app_scene_sniffer_on_enter(void* context) { - App* app = context; - serial_init(app->uart, UART_CH); - if (scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == - Sniffer_Option || - scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer ) == - Sender_Option) { - text_box_set_font(app->textBox, TextBoxFontText); - text_box_set_focus(app->textBox, TextBoxFocusEnd); - furi_string_cat_printf(app->text, "Baudrate: %s", - baudrateValues[app->uart->cfg->baudrate]); - furi_string_cat_printf(app->text, "\nData Width: %s", - dataWidthValues[app->uart->cfg->dataWidth]); - furi_string_cat_printf(app->text, "\nStop bits: %s", - stopBitsValues[app->uart->cfg->stopBits]); - furi_string_cat_printf(app->text, "\nParity: %s", - parityValues[app->uart->cfg->parity]); - furi_string_cat_printf(app->text, "\nResponse TimeOut: %dms", - app->uart->cfg->timeout * TIMEOUT_SCALER); - } else if (scene_manager_get_scene_state( - app->sceneManager, app_scene_sniffer) == About_Option) { - text_box_set_font(app->textBox, TextBoxFontText); - text_box_set_focus(app->textBox, TextBoxFocusStart); - furi_string_cat_printf(app->text, "MODBUS APP\n"); - furi_string_cat_printf(app->text, "BY: ROBERTO ARELLANO\n"); - furi_string_cat_printf(app->text, "ELECTRONIC CATS\n"); - furi_string_cat_printf(app->text, - "https://github.com/ElectronicCats/" - "flipper-rs485modbus/tree/main/ModbusApp/Test1"); - } - view_dispatcher_switch_to_view(app->viewDispatcher, TextBox_View); - text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); - if (scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == - Sender_Option) { - furi_thread_flags_set(furi_thread_get_id(app->uart->rxThread), - WorkerEvtTxStart); - } + App* app = context; + serial_init(app->uart, UART_CH); + if(scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == Sniffer_Option || + scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == Sender_Option) { + text_box_set_font(app->textBox, TextBoxFontText); + text_box_set_focus(app->textBox, TextBoxFocusEnd); + furi_string_cat_printf( + app->text, "Baudrate: %s", baudrateValues[app->uart->cfg->baudrate]); + furi_string_cat_printf( + app->text, "\nData Width: %s", dataWidthValues[app->uart->cfg->dataWidth]); + furi_string_cat_printf( + app->text, "\nStop bits: %s", stopBitsValues[app->uart->cfg->stopBits]); + furi_string_cat_printf(app->text, "\nParity: %s", parityValues[app->uart->cfg->parity]); + furi_string_cat_printf( + app->text, "\nResponse TimeOut: %dms", app->uart->cfg->timeout * TIMEOUT_SCALER); + } else if(scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == About_Option) { + text_box_set_font(app->textBox, TextBoxFontText); + text_box_set_focus(app->textBox, TextBoxFocusStart); + furi_string_cat_printf(app->text, "MODBUS APP\n"); + furi_string_cat_printf(app->text, "BY: ROBERTO ARELLANO\n"); + furi_string_cat_printf(app->text, "ELECTRONIC CATS\n"); + furi_string_cat_printf( + app->text, + "https://github.com/ElectronicCats/" + "flipper-rs485modbus/tree/main/ModbusApp/Test1"); + } + view_dispatcher_switch_to_view(app->viewDispatcher, TextBox_View); + text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); + if(scene_manager_get_scene_state(app->sceneManager, app_scene_sniffer) == Sender_Option) { + furi_thread_flags_set(furi_thread_get_id(app->uart->rxThread), WorkerEvtTxStart); + } } bool app_scene_sniffer_on_event(void* context, SceneManagerEvent event) { - App* app = context; - UNUSED(app); - bool consumed = false; - if (event.type == SceneManagerEventTypeCustom) { - consumed = true; - text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); - } - return consumed; + App* app = context; + UNUSED(app); + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + text_box_set_text(app->textBox, furi_string_get_cstr(app->text)); + } + return consumed; } void app_scene_sniffer_on_exit(void* context) { - App* app = context; - text_box_reset(app->textBox); - furi_string_reset(app->text); - serial_deinit(app->uart); -} \ No newline at end of file + App* app = context; + text_box_reset(app->textBox); + furi_string_reset(app->text); + serial_deinit(app->uart); +} diff --git a/ModbusApp/scenes_config/app_scene_config.h b/ModbusApp/scenes_config/app_scene_config.h index 5508ff23fcd..cddb3349b78 100644 --- a/ModbusApp/scenes_config/app_scene_config.h +++ b/ModbusApp/scenes_config/app_scene_config.h @@ -17,4 +17,3 @@ ADD_SCENE(app, sender, sender) ADD_SCENE(app, byte_input, byte_input) ADD_SCENE(app, manual_sender, manual_sender) ADD_SCENE(app, msgs_buffer, msgs_buffer) - \ No newline at end of file diff --git a/ModbusApp/scenes_config/app_scene_functions.c b/ModbusApp/scenes_config/app_scene_functions.c index 48f056e6576..98e664c16aa 100644 --- a/ModbusApp/scenes_config/app_scene_functions.c +++ b/ModbusApp/scenes_config/app_scene_functions.c @@ -18,8 +18,7 @@ void (*const app_on_enter_handlers[])(void*) = { // Generate scene on_event handlers array #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const app_on_event_handlers[])(void* context, - SceneManagerEvent event) = { +bool (*const app_on_event_handlers[])(void* context, SceneManagerEvent event) = { #include "app_scene_config.h" }; #undef ADD_SCENE diff --git a/ModbusApp/scenes_config/app_scene_functions.h b/ModbusApp/scenes_config/app_scene_functions.h index d110dc4592d..ee7c1c0ced6 100644 --- a/ModbusApp/scenes_config/app_scene_functions.h +++ b/ModbusApp/scenes_config/app_scene_functions.h @@ -8,7 +8,7 @@ #define ADD_SCENE(prefix, name, id) app_scene_##id, typedef enum { #include "app_scene_config.h" - app_scene_enum, + app_scene_enum, } Appscenes; #undef ADD_SCENE @@ -19,15 +19,13 @@ typedef enum { //--------------------------------------------------------------------- //--------------------------------------------------------------------- -extern const SceneManagerHandlers - app_scene_handlers; // We define the scene manager handler +extern const SceneManagerHandlers app_scene_handlers; // We define the scene manager handler //--------------------------------------------------------------------- // This defines and name of the "on_enter" functions //--------------------------------------------------------------------- -#define ADD_SCENE(prefix, name, id) \ - void prefix##_scene_##name##_on_enter(void*); +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); #include "app_scene_config.h" #undef ADD_SCENE @@ -36,7 +34,7 @@ extern const SceneManagerHandlers //--------------------------------------------------------------------- #define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); #include "app_scene_config.h" #undef ADD_SCENE @@ -44,7 +42,6 @@ extern const SceneManagerHandlers // This defines and name of the "on_exit" functions //--------------------------------------------------------------------- -#define ADD_SCENE(prefix, name, id) \ - void prefix##_scene_##name##_on_exit(void* context); +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); #include "app_scene_config.h" #undef ADD_SCENE