0
1
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:
2025-12-23 12:07:55 +01:00
parent e4fb5ca264
commit 412db1f293
7 changed files with 137 additions and 195 deletions

View File

@@ -226,4 +226,13 @@ function set_rds_eon(eon, enabled, pi, tp, ta, pty, ps, afs, data) end
---@return string ps
---@return table _ this is empty, getting afs is not supported yet
---@return integer data
function get_rds_eon(eon) end
function get_rds_eon(eon) end
---Sets the X/Y of the UDG
---@param xy boolean
---@param groups table Table of tables, this should be up to 8 tables containing 3 integers
function set_rds_udg(xy, groups) end
---Sets the X/Y of the UDG for RDS2
---@param xy boolean
---@param groups table Table of tables, this should be up to 8 tables containing 4 integers
function set_rds_udg2(xy, groups) end

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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();