working blob reading system

master
Ondřej Hruška 9 years ago
parent 29b2390442
commit 0b4ae04d37
  1. 18
      main.c
  2. 55
      scpi_parser.c
  3. 23
      scpi_parser.h

@ -9,6 +9,7 @@ void cmd_APPL_TRI_cb(const SCPI_argval_t *args);
void cmd_FREQ_cb(const SCPI_argval_t *args); void cmd_FREQ_cb(const SCPI_argval_t *args);
void cmd_DISP_TEXT_cb(const SCPI_argval_t *args); void cmd_DISP_TEXT_cb(const SCPI_argval_t *args);
void cmd_DATA_BLOB_cb(const SCPI_argval_t *args); void cmd_DATA_BLOB_cb(const SCPI_argval_t *args);
void cmd_DATA_BLOB_data(const uint8_t *bytes);
const SCPI_command_t scpi_cmd_lang[] = { const SCPI_command_t scpi_cmd_lang[] = {
{ {
@ -38,8 +39,10 @@ const SCPI_command_t scpi_cmd_lang[] = {
}, },
{ {
.levels = {"DATA", "BLOB"}, .levels = {"DATA", "BLOB"},
.params = {SCPI_DT_BLOB}, .params = {SCPI_DT_FLOAT, SCPI_DT_BLOB},
.callback = cmd_DATA_BLOB_cb .callback = cmd_DATA_BLOB_cb,
.blob_chunk = 4,
.blob_callback = cmd_DATA_BLOB_data
}, },
{0} // end marker {0} // end marker
}; };
@ -73,9 +76,16 @@ void cmd_DISP_TEXT_cb(const SCPI_argval_t *args)
printf("cb DISPlay:TEXT %s, %d\n", args[0].STRING, args[1].BOOL); printf("cb DISPlay:TEXT %s, %d\n", args[0].STRING, args[1].BOOL);
} }
void cmd_DATA_BLOB_cb(const SCPI_argval_t *args) void cmd_DATA_BLOB_cb(const SCPI_argval_t *args)
{ {
// noop printf("cb DATA:BLOB %f, <%d>\n", args[0].FLOAT, args[1].BLOB_LEN);
}
void cmd_DATA_BLOB_data(const uint8_t *bytes)
{
printf("blob item: %s\n", bytes);
} }
@ -85,7 +95,7 @@ int main()
// const char *inp = "FREQ 50\n"; // const char *inp = "FREQ 50\n";
//const char *inp = "DISPlay:TEXT 'banana', OFF\nDISP:TEXT \"dblquot!\", 1\r\nFREQ 50\r\n"; //const char *inp = "DISPlay:TEXT 'banana', OFF\nDISP:TEXT \"dblquot!\", 1\r\nFREQ 50\r\n";
const char *inp = "DATA:BLOB #49080\n"; const char *inp = "DATA:BLOB 13.456, #216AbcdEfghIjklMnop\nFREQ 50\r\n";
for (int i = 0; i < strlen(inp); i++) { for (int i = 0; i < strlen(inp); i++) {
scpi_handle_byte(inp[i]); scpi_handle_byte(inp[i]);

@ -13,9 +13,11 @@ typedef enum {
PARS_ARG_STR_APOS, // collect arg - string with single quotes PARS_ARG_STR_APOS, // collect arg - string with single quotes
PARS_ARG_STR_QUOT, // collect arg - string with double quotes PARS_ARG_STR_QUOT, // collect arg - string with double quotes
PARS_ARG_BLOB_PREAMBLE, PARS_ARG_BLOB_PREAMBLE,
PARS_ARG_BLOB_BODY, // blob body, callback for each group
// command with no args terminated by whitespace, discard whitespace until newline and then run callback. // command with no args terminated by whitespace, discard whitespace until newline and then run callback.
// error on non-whitespace // error on non-whitespace
PARS_TRAILING_WHITE, PARS_TRAILING_WHITE,
PARS_TRAILING_WHITE_NOCB, // no callback.
PARS_DISCARD_LINE, // used after detecting error PARS_DISCARD_LINE, // used after detecting error
} parser_state_t; } parser_state_t;
@ -32,7 +34,8 @@ static struct {
char charbuf[MAX_CHARBUF_LEN]; char charbuf[MAX_CHARBUF_LEN];
uint16_t charbuf_i; uint16_t charbuf_i;
int8_t blob_preamble_cnt; // preamble counter, if 0, was just #, must read count int32_t blob_cnt; // preamble counter, if 0, was just #, must read count. Used also for blob body.
int32_t blob_len; // total blob length to read
// recognized complete command level strings (FUNCtion) - exact copy from command struct // recognized complete command level strings (FUNCtion) - exact copy from command struct
char cur_levels[MAX_LEVEL_COUNT][MAX_CMD_LEN]; char cur_levels[MAX_LEVEL_COUNT][MAX_CMD_LEN];
@ -52,6 +55,8 @@ static struct {
.cur_level_i = 0, .cur_level_i = 0,
.cmdbuf_kept = false, .cmdbuf_kept = false,
.matched_cmd = NULL, .matched_cmd = NULL,
.blob_cnt = 0,
.blob_len = 0,
.arg_i = 0 .arg_i = 0
}; };
@ -102,6 +107,8 @@ static void pars_reset_cmd(void)
pst.cmdbuf_kept = false; pst.cmdbuf_kept = false;
pst.matched_cmd = NULL; pst.matched_cmd = NULL;
pst.arg_i = 0; pst.arg_i = 0;
pst.blob_cnt = 0;
pst.blob_len = 0;
} }
@ -120,6 +127,8 @@ static void pars_reset_cmd_keeplevel(void)
pst.matched_cmd = NULL; pst.matched_cmd = NULL;
pst.arg_i = 0; pst.arg_i = 0;
pst.blob_cnt = 0;
pst.blob_len = 0;
} }
@ -231,10 +240,14 @@ void scpi_handle_byte(const uint8_t b)
break; break;
case PARS_TRAILING_WHITE: case PARS_TRAILING_WHITE:
case PARS_TRAILING_WHITE_NOCB:
if (IS_WHITESPACE(c)) break; if (IS_WHITESPACE(c)) break;
if (c == '\n') { if (c == '\n') {
pars_run_callback(); if(pst.state != PARS_TRAILING_WHITE_NOCB) {
pars_run_callback();
}
pars_reset_cmd(); pars_reset_cmd();
} else { } else {
printf("ERROR unexpected char '%c' in trailing whitespace.\n", c);//TODO error printf("ERROR unexpected char '%c' in trailing whitespace.\n", c);//TODO error
@ -264,7 +277,7 @@ void scpi_handle_byte(const uint8_t b)
} }
break; break;
// TODO escape sequence in string // TODO escape sequence in string
case PARS_ARG_STR_APOS: case PARS_ARG_STR_APOS:
if (c == '\'') { if (c == '\'') {
@ -293,6 +306,25 @@ void scpi_handle_byte(const uint8_t b)
case PARS_ARG_BLOB_PREAMBLE: case PARS_ARG_BLOB_PREAMBLE:
// #<digits><dddddd><BLOB> // #<digits><dddddd><BLOB>
pars_blob_preamble_char(c); pars_blob_preamble_char(c);
break;
case PARS_ARG_BLOB_BODY:
charbuf_append(c);
pst.blob_cnt++;
if (pst.charbuf_i >= pst.matched_cmd->blob_chunk) {
charbuf_terminate();
if (pst.matched_cmd->blob_callback != NULL) {
pst.matched_cmd->blob_callback((uint8_t *)pst.charbuf);
}
}
if (pst.blob_cnt == pst.blob_len) {
pst.state = PARS_TRAILING_WHITE_NOCB; // discard trailing whitespace until newline
}
break;
} }
} }
@ -539,7 +571,7 @@ static void pars_arg_char(char c)
case SCPI_DT_BLOB: case SCPI_DT_BLOB:
if (c == '#') { if (c == '#') {
pst.state = PARS_ARG_BLOB_PREAMBLE; pst.state = PARS_ARG_BLOB_PREAMBLE;
pst.blob_preamble_cnt = 0; pst.blob_cnt = 0;
} else { } else {
printf("ERROR unexpected char '%c', binary block should start with #\n", c);//TODO error printf("ERROR unexpected char '%c', binary block should start with #\n", c);//TODO error
pst.state = PARS_DISCARD_LINE; pst.state = PARS_DISCARD_LINE;
@ -689,14 +721,14 @@ static void arg_convert_value(void)
static void pars_blob_preamble_char(uint8_t c) static void pars_blob_preamble_char(uint8_t c)
{ {
if (pst.blob_preamble_cnt == 0) { if (pst.blob_cnt == 0) {
if (!INRANGE(c, '1', '9')) { if (!INRANGE(c, '1', '9')) {
printf("ERROR expected ASCII 1-9 after #\n");//TODO error printf("ERROR expected ASCII 1-9 after #\n");//TODO error
pst.state = PARS_DISCARD_LINE; pst.state = PARS_DISCARD_LINE;
return; return;
} }
pst.blob_preamble_cnt = c - '0'; // 1-9 pst.blob_cnt = c - '0'; // 1-9
} else { } else {
if (c == '\n') { if (c == '\n') {
printf("ERROR unexpected newline in blob preamble\n");//TODO error printf("ERROR unexpected newline in blob preamble\n");//TODO error
@ -711,17 +743,18 @@ static void pars_blob_preamble_char(uint8_t c)
} }
charbuf_append(c); charbuf_append(c);
if (--pst.blob_preamble_cnt == 0) { if (--pst.blob_cnt == 0) {
// end of preamble sequence // end of preamble sequence
charbuf_terminate(); charbuf_terminate();
int bytecnt; sscanf(pst.charbuf, "%d", &pst.blob_len);
sscanf(pst.charbuf, "%d", &bytecnt);
printf("BLOB byte count = %d\n", bytecnt); // TODO pst.args[pst.arg_i].BLOB_LEN = pst.blob_len;
pars_run_callback();
// Call handler, enter special blob mode // Call handler, enter special blob mode
pst.state = PARS_DISCARD_LINE;//FIXME pst.state = PARS_ARG_BLOB_BODY;
pst.blob_cnt = 0;
} }
} }
} }

@ -27,20 +27,31 @@ typedef union {
int32_t INT; int32_t INT;
bool BOOL; bool BOOL;
char STRING[MAX_STRING_LEN+1]; // terminator char STRING[MAX_STRING_LEN+1]; // terminator
uint32_t BLOB; uint32_t BLOB_LEN;
} SCPI_argval_t; } SCPI_argval_t;
/** SCPI command preset */ /**
* SCPI command preset
* NOTE: command array is terminated by {0} - zero in levels[0][0]
*/
typedef struct { typedef struct {
// NOTE: command array is terminated by {0} - zero in levels[0][0] // levels MUST BE FIRST!
const char levels[MAX_LEVEL_COUNT][MAX_CMD_LEN]; // up to 4 parts const char levels[MAX_LEVEL_COUNT][MAX_CMD_LEN]; // up to 4 parts
const SCPI_datatype_t params[MAX_PARAM_COUNT]; // parameter types (0 for unused)
// called when the command is completed. BLOB arg must be last in the argument list, // called when the command is completed. BLOB arg must be last in the argument list,
// and only the first part is collected. // and only the first part is collected.
void (*callback)(const SCPI_argval_t * args); void (*callback)(const SCPI_argval_t *args);
// Param types - optional (defaults to zeros)
const SCPI_datatype_t params[MAX_PARAM_COUNT]; // parameter types (0 for unused)
// --- OPTIONAL (only for blob) ---
// Number of bytes in a blob callback
const uint8_t blob_chunk;
// Blob chunk callback (every blob_chunk bytes)
void (*blob_callback)(const uint8_t *bytes);
} SCPI_command_t; } SCPI_command_t;
// Zero terminated command struct array // Zero terminated command struct array

Loading…
Cancel
Save