mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-02-26 20:33:53 +01:00
remove c ascii parsing
This commit is contained in:
132
src/ascii_cmd.c
132
src/ascii_cmd.c
@@ -1,132 +0,0 @@
|
||||
#include "ascii_cmd.h"
|
||||
|
||||
typedef struct {
|
||||
const char *cmd;
|
||||
void (*handler)(char *arg, RDSModulator* mod, char* output);
|
||||
uint8_t cmd_length;
|
||||
} command_handler_t;
|
||||
|
||||
typedef struct {
|
||||
const char *prefix;
|
||||
const char *suffix;
|
||||
void (*handler)(char *arg, char *pattern, RDSModulator* mod, char* output);
|
||||
} pattern_command_handler_t;
|
||||
|
||||
static void handle_udg(char *arg, char *pattern, RDSModulator* mod, char* output) {
|
||||
uint8_t all_scanned = 1, bad_format = 0;
|
||||
uint16_t blocks[8][3];
|
||||
int sets = 0;
|
||||
char *ptr = arg;
|
||||
|
||||
while (sets < 8) {
|
||||
int count = sscanf(ptr, "%4hx%4hx%4hx", &blocks[sets][0], &blocks[sets][1], &blocks[sets][2]);
|
||||
if (count != 3) {
|
||||
all_scanned = 0;
|
||||
break;
|
||||
}
|
||||
sets++;
|
||||
while (*ptr && *ptr != ',') ptr++;
|
||||
if (*ptr == ',') ptr++;
|
||||
else {
|
||||
bad_format = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(pattern, "1") == 0) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1), &blocks, sets * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg1_len = sets;
|
||||
} else if(strcmp(pattern, "2") == 0) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2), &blocks, sets * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg2_len = sets;
|
||||
} else strcpy(output, "!");
|
||||
if(bad_format) strcpy(output, "-");
|
||||
else if(all_scanned) strcpy(output, "+");
|
||||
else strcpy(output, "/");
|
||||
}
|
||||
|
||||
static void handle_udg2(char *arg, char *pattern, RDSModulator* mod, char* output) {
|
||||
uint8_t all_scanned = 1, bad_format = 0;
|
||||
uint16_t blocks[8][4];
|
||||
int sets = 0;
|
||||
char *ptr = arg;
|
||||
|
||||
while (sets < 8) {
|
||||
int count = sscanf(ptr, "%4hx%4hx%4hx%4hx", &blocks[sets][0], &blocks[sets][1], &blocks[sets][2], &blocks[sets][3]);
|
||||
if (count != 4) {
|
||||
all_scanned = 0;
|
||||
break;
|
||||
}
|
||||
sets++;
|
||||
while (*ptr && *ptr != ',') ptr++;
|
||||
if (*ptr == ',') ptr++;
|
||||
else {
|
||||
bad_format = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(pattern, "1") == 0) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1_rds2), &blocks, sets * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg1_len_rds2 = sets;
|
||||
} else if(strcmp(pattern, "2") == 0) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2_rds2), &blocks, sets * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg2_len_rds2 = sets;
|
||||
} else strcpy(output, "!");
|
||||
if(bad_format) strcpy(output, "-");
|
||||
else if(all_scanned) strcpy(output, "+");
|
||||
else strcpy(output, "/");
|
||||
}
|
||||
|
||||
|
||||
static const pattern_command_handler_t pattern_commands[] = {
|
||||
{"UDG", "", handle_udg},
|
||||
{"2UDG", "", handle_udg2},
|
||||
};
|
||||
|
||||
static bool process_pattern_commands(char *cmd, char *arg, char *output, RDSModulator* mod) {
|
||||
size_t cmd_len = strlen(cmd);
|
||||
char pattern_buffer[16] = {0};
|
||||
for (size_t i = 0; i < sizeof(pattern_commands) / sizeof(pattern_command_handler_t); i++) {
|
||||
const pattern_command_handler_t *handler = &pattern_commands[i];
|
||||
size_t prefix_len = strlen(handler->prefix);
|
||||
size_t suffix_len = strlen(handler->suffix);
|
||||
if (cmd_len > (prefix_len + suffix_len) && strncmp(cmd, handler->prefix, prefix_len) == 0 && strcmp(cmd + cmd_len - suffix_len, handler->suffix) == 0) {
|
||||
size_t pattern_len = cmd_len - prefix_len - suffix_len;
|
||||
if (pattern_len < sizeof(pattern_buffer)) {
|
||||
strncpy(pattern_buffer, cmd + prefix_len, pattern_len);
|
||||
pattern_buffer[pattern_len] = 0;
|
||||
handler->handler(arg, pattern_buffer, mod, output);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output) {
|
||||
(void)cmd_output;
|
||||
char *cmd, *arg;
|
||||
|
||||
char output[255];
|
||||
memset(output, 0, sizeof(output));
|
||||
|
||||
char upper_str[CTL_BUFFER_SIZE];
|
||||
uint16_t cmd_len = _strnlen((const char*)str, CTL_BUFFER_SIZE);
|
||||
for(uint16_t i = 0; i < cmd_len; i++) if(str[i] == '\t') str[i] = ' ';
|
||||
|
||||
strncpy(upper_str, str, CTL_BUFFER_SIZE);
|
||||
upper_str[CTL_BUFFER_SIZE-1] = 0;
|
||||
|
||||
for(uint16_t i = 0; i < cmd_len && upper_str[i] != '='; i++) {
|
||||
if(upper_str[i] >= 'a' && upper_str[i] <= 'z') upper_str[i] = upper_str[i] - 'a' + 'A';
|
||||
}
|
||||
|
||||
char *equals_pos = strchr(upper_str, '=');
|
||||
if (equals_pos != NULL) {
|
||||
cmd = upper_str;
|
||||
cmd[equals_pos - upper_str] = 0;
|
||||
arg = equals_pos + 1;
|
||||
process_pattern_commands(cmd, arg, output, mod);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "rds.h"
|
||||
#include "fs.h"
|
||||
#include "modulator.h"
|
||||
#include "lib.h"
|
||||
#define CMD_BUFFER_SIZE 255
|
||||
#define CTL_BUFFER_SIZE (CMD_BUFFER_SIZE * 2)
|
||||
#define READ_TIMEOUT_MS 225
|
||||
|
||||
void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output);
|
||||
@@ -2,8 +2,7 @@ if type(data) == "string" and data ~= nil then
|
||||
local cmd, value = data:match("([^=]+)=([^=]+)")
|
||||
if cmd == nil then
|
||||
data = data:lower()
|
||||
if data == "ver" then
|
||||
return string.format("rds95 v. %s - (C) 2025 radio95 - lua parser", core_version)
|
||||
if data == "ver" then return string.format("rds95 v. %s - (C) 2025 radio95 - lua parser", core_version)
|
||||
elseif data == "init" then
|
||||
set_rds_program_defaults()
|
||||
return "+"
|
||||
@@ -48,28 +47,17 @@ if type(data) == "string" and data ~= nil then
|
||||
local eon_cmd, eon_num = data:match("^eon(%d+)([a-z]+)$")
|
||||
if eon_cmd then
|
||||
local eon_idx = tonumber(eon_cmd)
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > eon_count then
|
||||
return "?"
|
||||
end
|
||||
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > eon_count then return "?" end
|
||||
eon_idx = eon_idx - 1
|
||||
|
||||
local enabled, pi, tp, ta, pty, ps, afs, data_val = get_rds_eon(eon_idx)
|
||||
|
||||
if eon_num == "en" then
|
||||
return string.format("EON%dEN=%d\r\n", eon_idx + 1, enabled and 1 or 0)
|
||||
elseif eon_num == "pi" then
|
||||
return string.format("EON%dPI=%x\r\n", eon_idx + 1, pi)
|
||||
elseif eon_num == "ps" then
|
||||
return string.format("EON%dPS=%s\r\n", eon_idx + 1, ps)
|
||||
elseif eon_num == "pty" then
|
||||
return string.format("EON%dPTY=%d\r\n", eon_idx + 1, pty)
|
||||
elseif eon_num == "ta" then
|
||||
return string.format("EON%dTA=%d\r\n", eon_idx + 1, ta and 1 or 0)
|
||||
elseif eon_num == "tp" then
|
||||
return string.format("EON%dTP=%d\r\n", eon_idx + 1, tp and 1 or 0)
|
||||
elseif eon_num == "dt" then
|
||||
return string.format("EON%dDT=%x\r\n", eon_idx + 1, data_val)
|
||||
if eon_num == "en" then return string.format("EON%dEN=%d\r\n", eon_idx + 1, enabled and 1 or 0)
|
||||
elseif eon_num == "pi" then return string.format("EON%dPI=%x\r\n", eon_idx + 1, pi)
|
||||
elseif eon_num == "ps" then return string.format("EON%dPS=%s\r\n", eon_idx + 1, ps)
|
||||
elseif eon_num == "pty" then return string.format("EON%dPTY=%d\r\n", eon_idx + 1, pty)
|
||||
elseif eon_num == "ta" then return string.format("EON%dTA=%d\r\n", eon_idx + 1, ta and 1 or 0)
|
||||
elseif eon_num == "tp" then return string.format("EON%dTP=%d\r\n", eon_idx + 1, tp and 1 or 0)
|
||||
elseif eon_num == "dt" then return string.format("EON%dDT=%x\r\n", eon_idx + 1, data_val)
|
||||
end
|
||||
end
|
||||
return "?"
|
||||
@@ -81,58 +69,44 @@ if type(data) == "string" and data ~= nil then
|
||||
local eon_num, eon_type = cmd:match("^eon(%d+)([a-z]+)$")
|
||||
if eon_num then
|
||||
local eon_idx = tonumber(eon_num)
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > eon_count then
|
||||
return "?"
|
||||
end
|
||||
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > eon_count then return "?" end
|
||||
eon_idx = eon_idx - 1
|
||||
|
||||
local enabled, pi, tp, ta, pty, ps, afs, data_val = get_rds_eon(eon_idx)
|
||||
|
||||
if eon_type == "en" then
|
||||
local en_val = tonumber(value)
|
||||
if not en_val then return "-" end
|
||||
enabled = (en_val ~= 0)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "pi" then
|
||||
local pi_val = tonumber(value, 16)
|
||||
if not pi_val then return "-" end
|
||||
set_rds_eon(eon_idx, enabled, pi_val, tp, ta, pty, ps, afs, data_val)
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "ps" then
|
||||
local ps_val = value:sub(1, 24)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps_val, afs, data_val)
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "pty" then
|
||||
local pty_val = tonumber(value)
|
||||
if not pty_val then return "-" end
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty_val, ps, afs, data_val)
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "ta" then
|
||||
if not enabled or not tp then
|
||||
return "-"
|
||||
end
|
||||
if not enabled or not tp then return "-" end
|
||||
local ta_val = tonumber(value)
|
||||
if not ta_val then return "-" end
|
||||
ta = (ta_val ~= 0)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
if ta then
|
||||
set_rds_ta(true)
|
||||
end
|
||||
if ta then set_rds_ta(true) end
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "tp" then
|
||||
local tp_val = tonumber(value)
|
||||
if not tp_val then return "-" end
|
||||
tp = (tp_val ~= 0)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "af" then
|
||||
local af_table = {}
|
||||
if value == "" or value == "0" then
|
||||
@@ -141,24 +115,49 @@ if type(data) == "string" and data ~= nil then
|
||||
end
|
||||
for freq_str in value:gmatch("([^,]+)") do
|
||||
local f = tonumber(freq_str)
|
||||
if f then
|
||||
table.insert(af_table, f)
|
||||
else
|
||||
return "-"
|
||||
end
|
||||
if f then table.insert(af_table, f)
|
||||
else return "-" end
|
||||
end
|
||||
if #af_table > 25 then return "-" end
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, af_table, data_val)
|
||||
return "+"
|
||||
|
||||
elseif eon_type == "dt" then
|
||||
local dt_val = tonumber(value, 16)
|
||||
if not dt_val then return "-" end
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, dt_val)
|
||||
return "+"
|
||||
else
|
||||
return "?"
|
||||
else return "?" end
|
||||
end
|
||||
|
||||
local udg_num = cmd:match("^udg([12])$")
|
||||
local udg2_num = cmd:match("^2udg([12])$")
|
||||
if udg_num then
|
||||
local xy = (udg_num == "1")
|
||||
local groups = {}
|
||||
|
||||
for segment in value:gmatch("([^,]+)") do
|
||||
local b, c, d = segment:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$")
|
||||
if not (b and c and d) then return "-" end
|
||||
table.insert(groups, {tonumber(b, 16), tonumber(c, 16), tonumber(d, 16)})
|
||||
end
|
||||
|
||||
if #groups > 8 or #groups == 0 then return "-" end
|
||||
set_rds_udg(xy, groups)
|
||||
return "+"
|
||||
end
|
||||
if udg2_num then
|
||||
local xy = (udg2_num == "1")
|
||||
local groups = {}
|
||||
|
||||
for segment in value:gmatch("([^,]+)") do
|
||||
local a, b, c, d = segment:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$")
|
||||
if not (a and b and c and d) then return "-" end
|
||||
table.insert(groups, {tonumber(a, 16), tonumber(b, 16), tonumber(c, 16), tonumber(d, 16)})
|
||||
end
|
||||
|
||||
if #groups > 8 or #groups == 0 then return "-" end
|
||||
set_rds_udg2(xy, groups)
|
||||
return "+"
|
||||
end
|
||||
|
||||
if cmd == "pi" then
|
||||
|
||||
@@ -61,6 +61,7 @@ int lua_set_rds_##name(lua_State *localL) { \
|
||||
for (int i = 1; i <= n; i++) { \
|
||||
lua_rawgeti(localL, 1, i); \
|
||||
if (lua_isnumber(localL, -1)) add_func(&new_af, lua_tonumber(localL, -1)); \
|
||||
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); \
|
||||
lua_pop(localL, 1); \
|
||||
} \
|
||||
memcpy(&(mod->enc->data[mod->enc->program].af_field), &new_af, sizeof(new_af)); \
|
||||
@@ -296,14 +297,15 @@ int lua_set_rds_eon(lua_State *localL) {
|
||||
memset(&(mod->enc->data[mod->enc->program].eon[eon].af), 0, sizeof(RDSAFs));
|
||||
return 0;
|
||||
}
|
||||
if(n > 25) return luaL_error(localL, "table length over 25"); \
|
||||
if(n > 25) return luaL_error(localL, "table length over 25");
|
||||
|
||||
RDSAFs new_af;
|
||||
memset(&new_af, 0, sizeof(RDSAFs));
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 8, i); \
|
||||
lua_rawgeti(localL, 8, i);
|
||||
if (lua_isnumber(localL, -1)) add_rds_af(&new_af, lua_tonumber(localL, -1));
|
||||
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
memcpy(&(mod->enc->data[mod->enc->program].eon[eon].af), &new_af, sizeof(new_af));
|
||||
@@ -324,6 +326,77 @@ int lua_get_rds_eon(lua_State *localL) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
int lua_set_rds_udg(lua_State *localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int xy = lua_toboolean(localL, 1);
|
||||
luaL_checktype(localL, 2, LUA_TTABLE);
|
||||
int n = lua_rawlen(localL, 2);
|
||||
if(n > 8) return luaL_error(localL, "table length over 8");
|
||||
|
||||
uint16_t blocks[8][3] = {0};
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 2, i);
|
||||
if(lua_istable(localL, -1)) {
|
||||
int n2 = lua_rawlen(localL, -1);
|
||||
if(n2 > 3) return luaL_error(localL, "table length over 3");
|
||||
for(int j = 1; j <= n2; j++) {
|
||||
lua_rawgeti(localL, -1, j);
|
||||
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
|
||||
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
}
|
||||
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2), blocks, n * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg2_len = n;
|
||||
} else {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1), blocks, n * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg1_len = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int lua_set_rds_udg2(lua_State *localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int xy = lua_toboolean(localL, 1);
|
||||
luaL_checktype(localL, 2, LUA_TTABLE);
|
||||
int n = lua_rawlen(localL, 2);
|
||||
if(n > 8) return luaL_error(localL, "table length over 8");
|
||||
|
||||
uint16_t blocks[8][4] = {0};
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 2, i);
|
||||
if(lua_istable(localL, -1)) {
|
||||
int n2 = lua_rawlen(localL, -1);
|
||||
if(n2 > 4) return luaL_error(localL, "table length over 4");
|
||||
for(int j = 1; j <= n2; j++) {
|
||||
lua_rawgeti(localL, -1, j);
|
||||
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
|
||||
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
}
|
||||
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg2_len_rds2 = n;
|
||||
} else {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg1_len_rds2 = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_lua(RDSModulator* rds_mod) {
|
||||
mod = rds_mod;
|
||||
L = luaL_newstate();
|
||||
@@ -436,6 +509,9 @@ void init_lua(RDSModulator* rds_mod) {
|
||||
|
||||
lua_register(L, "set_rds_eon", lua_set_rds_eon);
|
||||
lua_register(L, "get_rds_eon", lua_get_rds_eon);
|
||||
|
||||
lua_register(L, "set_rds_udg", lua_set_rds_udg);
|
||||
lua_register(L, "set_rds_udg2", lua_set_rds_udg2);
|
||||
}
|
||||
|
||||
void run_lua(char *str, char *cmd_output) {
|
||||
|
||||
@@ -59,7 +59,6 @@ void poll_udp_server() {
|
||||
strncpy(cmd_buf, token, BUF_SIZE - 1);
|
||||
|
||||
memset(cmd_output, 0, BUF_SIZE);
|
||||
process_ascii_cmd(mod, cmd_buf, NULL);
|
||||
run_lua(cmd_buf, cmd_output);
|
||||
|
||||
size_t out_len = strlen(cmd_output);
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include "modulator.h"
|
||||
#include "ascii_cmd.h"
|
||||
#include "lua_rds.h"
|
||||
|
||||
#define CMD_BUFFER_SIZE 255
|
||||
#define CTL_BUFFER_SIZE (CMD_BUFFER_SIZE * 2)
|
||||
#define READ_TIMEOUT_MS 225
|
||||
|
||||
int open_udp_server(int port, RDSModulator *rds_mod);
|
||||
void poll_udp_server();
|
||||
void close_udp_server();
|
||||
|
||||
Reference in New Issue
Block a user