forked from flipperdevices/flipperzero-firmware
-
-
Notifications
You must be signed in to change notification settings - Fork 545
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from ElectronicCats/dev
Dev
- Loading branch information
Showing
22 changed files
with
1,311 additions
and
1,151 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#pragma once | ||
|
||
#include <furi.h> | ||
#include <furi_hal.h> | ||
#include <gui/gui.h> | ||
#include <gui/modules/byte_input.h> | ||
#include <gui/modules/submenu.h> | ||
#include <gui/modules/text_box.h> | ||
#include <gui/modules/variable_item_list.h> | ||
#include <gui/scene_manager.h> | ||
#include <gui/view_dispatcher.h> | ||
#include <dialogs/dialogs.h> | ||
#include <storage/storage.h> | ||
#include <expansion/expansion.h> | ||
#include <expansion/expansion_settings.h> | ||
|
||
#include <stm32wbxx_ll_lpuart.h> | ||
#include <stm32wbxx_ll_usart.h> | ||
|
||
#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; | ||
Expansion* expansion; | ||
} 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[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
#include "modbus_parser.h" | ||
|
||
#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; | ||
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#pragma once | ||
|
||
#include <furi.h> | ||
|
||
void handle_rx_data_cb(uint8_t* buf, size_t len, void* context); | ||
uint16_t getCRC(uint8_t* buf, uint8_t len); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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++; | ||
} |
Oops, something went wrong.