From 33eb2c1c60281fab09031564c921d2b8b4dce110 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sun, 26 Apr 2026 11:43:14 +0200 Subject: [PATCH] encode_group --- plugin.lua | 9 +++++++++ readme.md | 2 ++ scripts/98-uecp.lua | 10 ++++++++++ scripts/99-data.lua | 4 ---- src/lua_api.c | 23 +++++++++++++++++++++++ src/lua_api.h | 3 ++- src/lua_rds.c | 2 ++ src/rds.c | 40 +++++++++++++++++----------------------- src/rds.h | 2 ++ 9 files changed, 67 insertions(+), 28 deletions(-) diff --git a/plugin.lua b/plugin.lua index ad6ff79..4e22211 100644 --- a/plugin.lua +++ b/plugin.lua @@ -95,6 +95,7 @@ hooks.ps_transmission = {} function hooks.data_handle(data) end ---This function is called an unknown group is seen in the group sequence. See set_grpseq +---This will be also called on recognized groups - if they can't be properly encoded by the core ---Please remember that the core always fills in PTY and TP and PI in C if this is an B group ---It should be defined by the user in the script. ---@param group string group this was called in from the group sequence @@ -118,6 +119,14 @@ function hooks.rds2_group(stream) end rds = {} +---Returns an encoded group by the core - groups that could not be encoded decay to PS +---@param group string One character, just one +---@return boolean generated Was this properly generated, or is the PS? +---@return integer b +---@return integer c +---@return integer d +function rds.encode_group(group) end + ---@type integer rds.eon_count = 0 diff --git a/readme.md b/readme.md index 6116333..38dc960 100644 --- a/readme.md +++ b/readme.md @@ -31,6 +31,8 @@ RDS95 is the only (as far as i can tell) encoder to transmit the 9-bit AF codes Yet another unique feature, the Lua engine allows you to control the encoder, almost entirely. +Every RDS2 subcarrier is in full control of Lua (except tunneling - core fills in PTY and the rest) + ### RFT For a long time there was no RFT in RDS95, but on 28th December 2025 that changed when i implemented it in lua, just call the load function with the path and id 0, and see the your station's logo in the decoder diff --git a/scripts/98-uecp.lua b/scripts/98-uecp.lua index 3c0421a..383f7b0 100644 --- a/scripts/98-uecp.lua +++ b/scripts/98-uecp.lua @@ -243,6 +243,16 @@ mec_handlers[0x19] = function (data) end) return 2 end +mec_handlers[0x16] = function (data) + -- Group sequence for stream 0 + local dsn = string.byte(data, 2) + local mel = string.byte(data, 3) + local group_sequence = string.sub(data, 4, 3+mel) + dsn_helper(dsn, function () + rds.set_grpseq(group_sequence) + end) + return 4 + mel +end mec_handlers[0x23] = function (data) -- Site address local control_bits = string.byte(data, 2) diff --git a/scripts/99-data.lua b/scripts/99-data.lua index fd2bacd..fe4029b 100644 --- a/scripts/99-data.lua +++ b/scripts/99-data.lua @@ -77,7 +77,6 @@ function hooks.data_handle(data) return string.format("ERTPRUN=%d\r\n", f1) elseif data == "lps" then return string.format("LPS=%s\r\n", rds.get_lps()) elseif data == "ert" then return string.format("ERT=%s\r\n", rds.ext.get_ert()) - elseif data == "grpseq" then return string.format("GRPSEQ=%s\r\n", rds.get_grpseq()) else local eon_cmd, eon_num = data:match("^eon(%d+)([a-z]+)$") if eon_cmd then @@ -251,9 +250,6 @@ function hooks.data_handle(data) dp.set_writing_program(program-1) rds.set_ta(false) return "+\r\n" - elseif cmd == "grpseq" then - rds.set_grpseq(value) - return "+\r\n" elseif cmd == "rtp" or cmd == "ertp" then local is_ertp = (cmd == "ertp") local t1, s1, l1, t2, s2, l2 = value:match("(%d+),(%d+),(%d+),(%d+),(%d+),(%d+)") diff --git a/src/lua_api.c b/src/lua_api.c index 35a5274..b87f7d7 100644 --- a/src/lua_api.c +++ b/src/lua_api.c @@ -385,4 +385,27 @@ int lua_convert_to_rdscharset(lua_State *localL) { lua_pushstring(localL, output); return 1; +} + +int lua_encode_group(lua_State *localL) { + size_t len; + const char *grp = luaL_checklstring(localL, 1, &len); + if(len != 1) return luaL_error(localL, "expected a length of 1"); + char PS_GROUP = 0; + + RDSGroup group; + uint8_t good = check_rds_good_group(enc, grp); + if(good == 0) { + lua_pushboolean(localL, 0); + get_rds_sequence_group(enc, &group, 1, &PS_GROUP); + } else { + lua_pushboolean(localL, 1); + get_rds_sequence_group(enc, &group, 1, grp); + } + + lua_pushinteger(localL, group.b); + lua_pushinteger(localL, group.c); + lua_pushinteger(localL, group.d); + + return 4; } \ No newline at end of file diff --git a/src/lua_api.h b/src/lua_api.h index 30e6149..88d4f43 100644 --- a/src/lua_api.h +++ b/src/lua_api.h @@ -85,4 +85,5 @@ int lua_get_rds_eon(lua_State *localL); int lua_crc16(lua_State *localL); -int lua_convert_to_rdscharset(lua_State *localL); \ No newline at end of file +int lua_convert_to_rdscharset(lua_State *localL); +int lua_encode_group(lua_State *localL); \ No newline at end of file diff --git a/src/lua_rds.c b/src/lua_rds.c index cbad916..c5a36ae 100644 --- a/src/lua_rds.c +++ b/src/lua_rds.c @@ -144,6 +144,8 @@ void init_lua(RDSEncoder* _enc) { lua_registertotable(L, "set_streams", lua_set_rds_streams); lua_registertotable(L, "get_streams", lua_get_rds_streams); + lua_registertotable(L, "encode_group", lua_encode_group); + lua_setglobal(L, "rds"); if (luaL_loadfile(L, "/etc/rds95.lua") != LUA_OK) { diff --git a/src/rds.c b/src/rds.c index ee74eac..45bea9b 100644 --- a/src/rds.c +++ b/src/rds.c @@ -21,7 +21,12 @@ uint8_t get_rds_custom_groups(RDSEncoder* enc, RDSGroup *group); uint8_t get_rds_custom_groups2(RDSEncoder* enc, RDSGroup *group); int get_rdsp_lua_group(RDSGroup *group, const char grp); -static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp) { +void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, uint8_t good_group, char* grp) { + if(good_group == 0) { + if(get_rdsp_lua_group(group, *grp) == 0) get_rds_ps_group(enc, group); + return; + } + switch (*grp) { case 0: get_rds_ps_group(enc, group); @@ -52,7 +57,7 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp) } } -static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) { +uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) { if(*grp == 2) { if(enc->data[enc->program].ecc != 0 || enc->data[enc->program].slc_data != 0) return 1; return 0; @@ -108,7 +113,6 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) { } uint8_t good_group = 0; - uint8_t cant_find_group = 0; uint8_t grp_sqc_idx = 0; char grp; @@ -129,28 +133,18 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) { if(get_rds_custom_groups(enc, group)) goto group_coded; - while(good_group == 0) { - grp_sqc_idx = enc->state[enc->program].grp_seq_idx; - if(grp_sqc_idx > enc->data[enc->program].grp_sqc_len) { - enc->state[enc->program].grp_seq_idx = 0; - grp_sqc_idx = 0; - } - grp = enc->data[enc->program].grp_sqc[grp_sqc_idx]; - - good_group = check_rds_good_group(enc, &grp); - - if(!good_group) cant_find_group++; - else cant_find_group = 0; - if(!good_group && cant_find_group >= 23) { - cant_find_group = 0; - break; - } - - enc->state[enc->program].grp_seq_idx++; + grp_sqc_idx = enc->state[enc->program].grp_seq_idx; + if(grp_sqc_idx > enc->data[enc->program].grp_sqc_len) { + enc->state[enc->program].grp_seq_idx = 0; + grp_sqc_idx = 0; } - if(!good_group) grp = 0; + grp = enc->data[enc->program].grp_sqc[grp_sqc_idx]; - get_rds_sequence_group(enc, group, &grp); + good_group = check_rds_good_group(enc, &grp); + + enc->state[enc->program].grp_seq_idx++; + + get_rds_sequence_group(enc, group, good_group, &grp); group_coded_rds2: if (group->a == 0 && stream != 0) { diff --git a/src/rds.h b/src/rds.h index 6fd9ba6..52fce22 100644 --- a/src/rds.h +++ b/src/rds.h @@ -158,6 +158,8 @@ void reset_rds_state(RDSEncoder* enc, uint8_t program); void set_rds_defaults(RDSEncoder* enc, uint8_t program); void init_rds_encoder(RDSEncoder* enc); void add_checkwords(RDSGroup *group, uint8_t *bits); +uint8_t check_rds_good_group(RDSEncoder* enc, char* grp); +void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, uint8_t good_group, char* grp); void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream); void get_rds_bits(RDSEncoder* enc, uint8_t *bits, uint8_t stream);