mirror of
https://github.com/eddyem/tty_term.git
synced 2025-12-06 02:25:11 +03:00
add modbus input mode
This commit is contained in:
parent
57235dccdd
commit
33658a57a4
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
set(PROJ tty_term)
|
set(PROJ tty_term)
|
||||||
set(MINOR_VERSION "1")
|
set(MINOR_VERSION "2")
|
||||||
set(MID_VERSION "1")
|
set(MID_VERSION "1")
|
||||||
set(MAJOR_VERSION "0")
|
set(MAJOR_VERSION "0")
|
||||||
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||||
|
|||||||
@ -39,10 +39,11 @@
|
|||||||
#include "string_functions.h"
|
#include "string_functions.h"
|
||||||
|
|
||||||
enum { // using colors
|
enum { // using colors
|
||||||
BKG_NO = 1,
|
BKG_NO = 1, // normal status string
|
||||||
BKGMARKED_NO = 2,
|
BKGMARKED_NO, // marked status string
|
||||||
NORMAL_NO = 3,
|
NORMAL_NO, // normal output
|
||||||
MARKED_NO = 4
|
MARKED_NO, // marked output
|
||||||
|
ERROR_NO // error displayed
|
||||||
};
|
};
|
||||||
#define COLOR(x) COLOR_PAIR(x ## _NO)
|
#define COLOR(x) COLOR_PAIR(x ## _NO)
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ static bool should_exit = false;
|
|||||||
|
|
||||||
static disptype disp_type = DISP_TEXT; // type of displaying data
|
static disptype disp_type = DISP_TEXT; // type of displaying data
|
||||||
static disptype input_type = DISP_TEXT; // parsing type of input data
|
static disptype input_type = DISP_TEXT; // parsing type of input data
|
||||||
const char *dispnames[] = {"TEXT", "RAW", "HEX"};
|
const char *dispnames[DISP_SIZE] = {"TEXT", "RAW", "HEX", "RTU (RAW)", "RTU (HEX)", "Error"};
|
||||||
|
|
||||||
static chardevice *dtty = NULL;
|
static chardevice *dtty = NULL;
|
||||||
|
|
||||||
@ -121,6 +122,18 @@ static void forward_to_readline(char c){
|
|||||||
rl_callback_read_char();
|
rl_callback_read_char();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief show_err - show error on status string
|
||||||
|
* @param text - text to display
|
||||||
|
*/
|
||||||
|
static void show_err(const char *text){
|
||||||
|
wclear(sep_win);
|
||||||
|
wattron(sep_win, COLOR(ERROR));
|
||||||
|
wprintw(sep_win, "%s", text);
|
||||||
|
wattroff(sep_win, COLOR(ERROR));
|
||||||
|
wrefresh(sep_win);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ptrtobuf - get n'th string of `formatted_buffer`
|
* @brief ptrtobuf - get n'th string of `formatted_buffer`
|
||||||
* @param lineno - line number
|
* @param lineno - line number
|
||||||
@ -128,7 +141,7 @@ static void forward_to_readline(char c){
|
|||||||
*/
|
*/
|
||||||
static char *ptrtobuf(size_t lineno){
|
static char *ptrtobuf(size_t lineno){
|
||||||
if(!linebuffer->line_array_idx){
|
if(!linebuffer->line_array_idx){
|
||||||
WARNX("line_array_idx not inited");
|
show_err("line_array_idx not inited");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(lineno > linebuffer->lnarr_curr) return NULL;
|
if(lineno > linebuffer->lnarr_curr) return NULL;
|
||||||
@ -523,11 +536,12 @@ void init_ncurses(){
|
|||||||
}
|
}
|
||||||
if(!msg_win || !sep_win || !cmd_win)
|
if(!msg_win || !sep_win || !cmd_win)
|
||||||
fail_exit("Failed to allocate windows");
|
fail_exit("Failed to allocate windows");
|
||||||
wtimeout(cmd_win, 4);
|
wtimeout(cmd_win, 5);
|
||||||
keypad(cmd_win, TRUE);
|
keypad(cmd_win, TRUE);
|
||||||
if(has_colors()){
|
if(has_colors()){
|
||||||
init_pair(BKG_NO, COLOR_WHITE, COLOR_BLUE);
|
init_pair(BKG_NO, COLOR_WHITE, COLOR_BLUE);
|
||||||
init_pair(BKGMARKED_NO, 1, COLOR_BLUE); // COLOR_RED used in my usefull_macros
|
init_pair(BKGMARKED_NO, 1, COLOR_BLUE); // COLOR_RED used in my usefull_macros
|
||||||
|
init_pair(ERROR_NO, COLOR_BLACK, 1);
|
||||||
init_pair(NORMAL_NO, COLOR_WHITE, COLOR_BLACK);
|
init_pair(NORMAL_NO, COLOR_WHITE, COLOR_BLACK);
|
||||||
init_pair(MARKED_NO, COLOR_CYAN, COLOR_BLACK);
|
init_pair(MARKED_NO, COLOR_CYAN, COLOR_BLACK);
|
||||||
wbkgd(sep_win, COLOR(BKG));
|
wbkgd(sep_win, COLOR(BKG));
|
||||||
@ -560,9 +574,9 @@ static void got_command(char *line){
|
|||||||
if(!*line) return; // zero length
|
if(!*line) return; // zero length
|
||||||
if(!previous_line || strcmp(previous_line, line)) add_history(line); // omit repeats
|
if(!previous_line || strcmp(previous_line, line)) add_history(line); // omit repeats
|
||||||
FREE(previous_line);
|
FREE(previous_line);
|
||||||
if(convert_and_send(input_type, line) == -1){
|
int res = convert_and_send(input_type, line);
|
||||||
ERRX("Device disconnected");
|
if(res == 0) show_err("Wrong data format");
|
||||||
}
|
else if(res == -1) ERRX("Device disconnected");
|
||||||
previous_line = line;
|
previous_line = line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,7 +602,7 @@ static void change_disp(disptype in, disptype out){
|
|||||||
input_type = in;
|
input_type = in;
|
||||||
DBG("input -> %s", dispnames[in]);
|
DBG("input -> %s", dispnames[in]);
|
||||||
}
|
}
|
||||||
if(out >= DISP_TEXT && out < DISP_UNCHANGED && out != disp_type){
|
if(out >= DISP_TEXT && out <= DISP_HEX && out != disp_type){
|
||||||
disp_type = out;
|
disp_type = out;
|
||||||
DBG("output -> %s", dispnames[out]);
|
DBG("output -> %s", dispnames[out]);
|
||||||
resize(); // reformat everything
|
resize(); // reformat everything
|
||||||
@ -636,6 +650,8 @@ static const char *help[] = {
|
|||||||
" F2 - text mode",
|
" F2 - text mode",
|
||||||
" F3 - raw mode (all symbols in hex codes)",
|
" F3 - raw mode (all symbols in hex codes)",
|
||||||
" F4 - hexdump mode (like hexdump output)",
|
" F4 - hexdump mode (like hexdump output)",
|
||||||
|
" F5 - modbus RTU mode (only for sending), input like RAW: ID data",
|
||||||
|
" F6 - modbus RTU mode (only for sending), input like HEX: ID data",
|
||||||
" mouse scroll - scroll text output",
|
" mouse scroll - scroll text output",
|
||||||
" q,^c,^d - quit",
|
" q,^c,^d - quit",
|
||||||
" TAB - switch between scroll and edit modes",
|
" TAB - switch between scroll and edit modes",
|
||||||
@ -690,6 +706,14 @@ void *cmdline(void* arg){
|
|||||||
DBG("\n\nIN HEX mode\n\n");
|
DBG("\n\nIN HEX mode\n\n");
|
||||||
dt = DISP_HEX;
|
dt = DISP_HEX;
|
||||||
break;
|
break;
|
||||||
|
case KEY_F(5): // RTU mode
|
||||||
|
DBG("\n\nIN RTU RAW mode\n\n");
|
||||||
|
dt = DISP_RTURAW;
|
||||||
|
break;
|
||||||
|
case KEY_F(6): // RTU mode
|
||||||
|
DBG("\n\nIN RTU HEX mode\n\n");
|
||||||
|
dt = DISP_RTUHEX;
|
||||||
|
break;
|
||||||
case KEY_MOUSE:
|
case KEY_MOUSE:
|
||||||
if(getmouse(&event) == OK){
|
if(getmouse(&event) == OK){
|
||||||
if(event.bstate & (BUTTON4_PRESSED)) rolldown(1); // wheel up
|
if(event.bstate & (BUTTON4_PRESSED)) rolldown(1); // wheel up
|
||||||
|
|||||||
@ -26,7 +26,10 @@ typedef enum{ // display/input data as
|
|||||||
DISP_TEXT, // text (non-ASCII input and output as \xxx)
|
DISP_TEXT, // text (non-ASCII input and output as \xxx)
|
||||||
DISP_RAW, // hex output as xx xx xx, input in as numbers in bin (0bxx), oct(0xx), hex (0xxx||0Xxx) or dec and letters
|
DISP_RAW, // hex output as xx xx xx, input in as numbers in bin (0bxx), oct(0xx), hex (0xxx||0Xxx) or dec and letters
|
||||||
DISP_HEX, // hexdump output, input in hex only (with or without spaces)
|
DISP_HEX, // hexdump output, input in hex only (with or without spaces)
|
||||||
DISP_UNCHANGED // old
|
DISP_RTURAW, // modbus RTU (only to send): first number is node address, all other - data; CRC calculated
|
||||||
|
DISP_RTUHEX, // RTU, input in hex (in raw - like RAW)
|
||||||
|
DISP_UNCHANGED, // old
|
||||||
|
DISP_SIZE // sizeof
|
||||||
} disptype;
|
} disptype;
|
||||||
|
|
||||||
void init_readline();
|
void init_readline();
|
||||||
|
|||||||
@ -79,7 +79,7 @@ void popup_msg(WINDOW *parent, const char *const *msg){
|
|||||||
getmaxyx(parent, maxy, maxx);
|
getmaxyx(parent, maxy, maxx);
|
||||||
// borders
|
// borders
|
||||||
//x0 = (maxx > 12) ? 2 : ((maxx > 9) ? 1 : 0);
|
//x0 = (maxx > 12) ? 2 : ((maxx > 9) ? 1 : 0);
|
||||||
x0 = (maxx > 80) ? maxx/2-40 : maxx / 32;
|
x0 = (maxx > 80) ? maxx/2-60 : maxx / 32;
|
||||||
y0 = (maxy > 20) ? 2 : ((maxy > 16) ? 1 : 0);
|
y0 = (maxy > 20) ? 2 : ((maxy > 16) ? 1 : 0);
|
||||||
int wide = maxx - 2*x0;
|
int wide = maxx - 2*x0;
|
||||||
int high = maxy - 2*y0;
|
int high = maxy - 2*y0;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ static int eollen = 1;
|
|||||||
|
|
||||||
// read text string and throw out all < 31 and > 126
|
// read text string and throw out all < 31 and > 126
|
||||||
static inline const char *omit_nonletters(disptype input_type, const char *line){
|
static inline const char *omit_nonletters(disptype input_type, const char *line){
|
||||||
int start = (input_type == DISP_TEXT) ? 31 : 32; // remove spaces for RAW and HEX modes
|
int start = (input_type == DISP_TEXT) ? 31 : 32; // remove spaces for non-TEXT modes
|
||||||
while(*line){
|
while(*line){
|
||||||
char c = *line;
|
char c = *line;
|
||||||
if(c > start && c < 127) break;
|
if(c > start && c < 127) break;
|
||||||
@ -159,6 +159,17 @@ static inline const char *getspec(const char *line, int *ch){
|
|||||||
*ch = got;
|
*ch = got;
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
static inline const char* getu32(const char *str, uint32_t *val){
|
||||||
|
char *eptr;
|
||||||
|
if(!str) return NULL;
|
||||||
|
long ll = strtol(str, &eptr, 0);
|
||||||
|
if(ll < 0 || ll > UINT32_MAX){ // wrong number
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(val) *val = (uint32_t)ll;
|
||||||
|
return omit_nonletters(DISP_RTU, eptr);
|
||||||
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief convert_and_send - convert input line and send it (in text mode add `eol`)
|
* @brief convert_and_send - convert input line and send it (in text mode add `eol`)
|
||||||
@ -171,11 +182,14 @@ int convert_and_send(disptype input_type, const char *line){
|
|||||||
size_t curpos = 0; // position in `buf`
|
size_t curpos = 0; // position in `buf`
|
||||||
line = omit_nonletters(input_type, line);
|
line = omit_nonletters(input_type, line);
|
||||||
DBG("got: '%s' to send", line);
|
DBG("got: '%s' to send", line);
|
||||||
while(*line){
|
void CHKbufsiz(size_t sz){
|
||||||
if(curpos >= bufsiz){ // out ouptut buffer can't be larger than input
|
if(curpos + sz >= bufsiz){ // out ouptut buffer can't be larger than input
|
||||||
bufsiz += BUFSIZ;
|
bufsiz += BUFSIZ;
|
||||||
buf = realloc(buf, bufsiz);
|
buf = realloc(buf, bufsiz);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
while(*line){
|
||||||
|
CHKbufsiz(1);
|
||||||
int ch = -1;
|
int ch = -1;
|
||||||
switch(input_type){
|
switch(input_type){
|
||||||
case DISP_TEXT: // only check for '\'
|
case DISP_TEXT: // only check for '\'
|
||||||
@ -183,6 +197,7 @@ int convert_and_send(disptype input_type, const char *line){
|
|||||||
if(ch == '\\') line = getspec(line, &ch);
|
if(ch == '\\') line = getspec(line, &ch);
|
||||||
break;
|
break;
|
||||||
case DISP_RAW: // read next uint8_t and put into buffer
|
case DISP_RAW: // read next uint8_t and put into buffer
|
||||||
|
case DISP_RTURAW: // the same (but calculate CRC at the end)
|
||||||
ch = *line++;
|
ch = *line++;
|
||||||
if(ch == '0'){ // number: 0, 0xHH, 0OOO, 0bBBBBBBBB
|
if(ch == '0'){ // number: 0, 0xHH, 0OOO, 0bBBBBBBBB
|
||||||
ch = *line;
|
ch = *line;
|
||||||
@ -205,6 +220,7 @@ int convert_and_send(disptype input_type, const char *line){
|
|||||||
} // else - letter (without escape-symbols!)
|
} // else - letter (without escape-symbols!)
|
||||||
break;
|
break;
|
||||||
case DISP_HEX: // read next 2 hex bytes and put into buffer
|
case DISP_HEX: // read next 2 hex bytes and put into buffer
|
||||||
|
case DISP_RTUHEX: // the same (but calculate CRC at the end)
|
||||||
line = gethex(line, &ch);
|
line = gethex(line, &ch);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -222,6 +238,20 @@ int convert_and_send(disptype input_type, const char *line){
|
|||||||
memcpy(buf+curpos, eol, eollen);
|
memcpy(buf+curpos, eol, eollen);
|
||||||
curpos += eollen;
|
curpos += eollen;
|
||||||
DBG("Add EOL");
|
DBG("Add EOL");
|
||||||
|
}else if(input_type == DISP_RTURAW || input_type == DISP_RTUHEX){ // calculate CRC
|
||||||
|
CHKbufsiz(2);
|
||||||
|
uint16_t crc = 0xFFFF;
|
||||||
|
for(size_t pos = 0; pos < curpos; ++pos){
|
||||||
|
crc ^= (uint16_t)buf[pos];
|
||||||
|
for(int i = 8; i; --i){
|
||||||
|
if((crc & 1)){
|
||||||
|
crc >>= 1;
|
||||||
|
crc ^= 0xA001;
|
||||||
|
}else crc >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[curpos++] = crc & 0xff; // Lo
|
||||||
|
buf[curpos++] = crc >> 8; // Hi
|
||||||
}
|
}
|
||||||
return SendData(buf, curpos);
|
return SendData(buf, curpos);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user