Skip to content

Commit

Permalink
Merge pull request #5 from ElectronicCats/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
sabas1080 authored Aug 22, 2024
2 parents 6583e13 + b033a77 commit ed88727
Show file tree
Hide file tree
Showing 22 changed files with 1,311 additions and 1,151 deletions.
1,174 changes: 23 additions & 1,151 deletions ModbusApp/Modbus.c

Large diffs are not rendered by default.

157 changes: 157 additions & 0 deletions ModbusApp/Modbus.h
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>

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

Check failure on line 15 in ModbusApp/Modbus.h

View workflow job for this annotation

GitHub Actions / ufbt: Build for Dev branch

expansion/expansion_settings.h: No such file or directory

#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[];
202 changes: 202 additions & 0 deletions ModbusApp/modbus_parser/modbus_parser.c
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);
}
}
6 changes: 6 additions & 0 deletions ModbusApp/modbus_parser/modbus_parser.h
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);
24 changes: 24 additions & 0 deletions ModbusApp/modbus_ring_buffer/modbus_ring_buffer.c
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++;
}
Loading

0 comments on commit ed88727

Please sign in to comment.