mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-02-26 20:33:53 +01:00
last oda in c
This commit is contained in:
@@ -3,6 +3,8 @@ _Af_Oda_state = 0
|
||||
_Af_Oda_len = 0
|
||||
_Af_Oda_afs = {}
|
||||
|
||||
local USERDATA_OFFSET = 270
|
||||
|
||||
---@param freq number
|
||||
---@return table
|
||||
local function encode_af(freq)
|
||||
@@ -13,10 +15,10 @@ local function encode_af(freq)
|
||||
table.insert(out, math.tointeger((freq * 10) - 384))
|
||||
elseif freq >= 153 and freq <= 279 then
|
||||
table.insert(out, 250) -- LFMF incoming
|
||||
table.insert(out, (freq - 153) / 9 + 1)
|
||||
table.insert(out, math.tointeger((freq - 153) / 9 + 1))
|
||||
elseif freq >= 531 and freq <= 1602 then
|
||||
table.insert(out, 250) -- LFMF incoming
|
||||
table.insert(out, (freq - 531) / 9 + 16)
|
||||
table.insert(out, math.tointeger((freq - 531) / 9 + 16))
|
||||
end
|
||||
return out
|
||||
end
|
||||
@@ -61,9 +63,16 @@ local function init_af_oda()
|
||||
end
|
||||
end
|
||||
|
||||
---Sets the AFs included in the ODA
|
||||
---@param afs table List of numbers (e.g., {98.1, 102.5})
|
||||
function set_rds_af_oda(afs)
|
||||
local function save_af_to_userdata(afs)
|
||||
local count = #afs
|
||||
if count > 25 then count = 25 end
|
||||
|
||||
local payload = string.pack("B", count)
|
||||
for i = 1, count do payload = payload .. string.pack("f", afs[i]) end
|
||||
set_userdata_offset(USERDATA_OFFSET, #payload, payload)
|
||||
end
|
||||
|
||||
local function _process_af_list(afs)
|
||||
_Af_Oda_afs = {}
|
||||
_Af_Oda_len = #afs
|
||||
for _, f in ipairs(afs) do
|
||||
@@ -73,9 +82,36 @@ function set_rds_af_oda(afs)
|
||||
end
|
||||
end
|
||||
_Af_Oda_state = 0
|
||||
if _Af_Oda_id == nil then init_af_oda() end
|
||||
init_af_oda()
|
||||
end
|
||||
|
||||
local function load_af_from_userdata()
|
||||
local header = get_userdata_offset(USERDATA_OFFSET, 1)
|
||||
if header == "" or header == nil then return end
|
||||
|
||||
local count = string.unpack("B", header)
|
||||
if count == 0 or count > 25 then return end
|
||||
|
||||
local data = get_userdata_offset(USERDATA_OFFSET + 1, count * 4)
|
||||
if #data < (count * 4) then return end
|
||||
|
||||
local afs = {}
|
||||
for i = 1, count do
|
||||
local val = string.unpack("f", data, (i-1)*4 + 1)
|
||||
table.insert(afs, val)
|
||||
end
|
||||
|
||||
_process_af_list(afs)
|
||||
end
|
||||
|
||||
---Sets the AFs included in the ODA and saves them
|
||||
---@param afs table List of numbers (e.g., {98.1, 102.5})
|
||||
function set_rds_af_oda(afs)
|
||||
_process_af_list(afs)
|
||||
save_af_to_userdata(afs)
|
||||
end
|
||||
|
||||
function on_state()
|
||||
init_af_oda()
|
||||
load_af_from_userdata()
|
||||
if _Af_Oda_len ~= 0 then init_af_oda() end
|
||||
end
|
||||
30
src/lib.c
30
src/lib.c
@@ -47,36 +47,6 @@ inline uint16_t get_block_from_group(RDSGroup *group, uint8_t block) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t add_rds_af_oda(RDSAFsODA *af_list, float freq) {
|
||||
uint16_t af;
|
||||
|
||||
uint8_t entries_reqd = 1;
|
||||
if (freq < 64.1f || freq > 107.9f) entries_reqd = 2;
|
||||
|
||||
if (af_list->num_afs + entries_reqd > MAX_AFS) return 1;
|
||||
|
||||
if(freq >= 87.6f && freq <= 107.9f) {
|
||||
af = (uint16_t)(freq * 10.0f) - 875;
|
||||
af_list->afs[af_list->num_entries] = af;
|
||||
} else if (freq >= 64.1f && freq <= 88.0f) {
|
||||
af = (uint16_t)(freq * 10.0f) - 384;
|
||||
af_list->afs[af_list->num_entries] = af;
|
||||
} else if (freq >= 153.0f && freq <= 279.0f) {
|
||||
af = (uint16_t)(freq - 153.0f) / 9 + 1;
|
||||
af_list->afs[af_list->num_entries + 0] = AF_CODE_LFMF_FOLLOWS;
|
||||
af_list->afs[af_list->num_entries + 1] = af;
|
||||
} else if (freq >= 531.0f && freq <= 1602.0f) {
|
||||
af = (uint16_t)(freq - 531.0f) / 9 + 16;
|
||||
af_list->afs[af_list->num_entries + 0] = AF_CODE_LFMF_FOLLOWS;
|
||||
af_list->afs[af_list->num_entries + 1] = af;
|
||||
} else return 1;
|
||||
|
||||
af_list->num_entries += entries_reqd;
|
||||
af_list->num_afs++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t add_rds_af(RDSAFs *af_list, float freq) {
|
||||
uint16_t af;
|
||||
|
||||
|
||||
@@ -12,6 +12,5 @@ uint16_t crc16_ccitt(char *data, uint16_t len);
|
||||
|
||||
uint16_t get_block_from_group(RDSGroup *group, uint8_t block);
|
||||
|
||||
uint8_t add_rds_af_oda(RDSAFsODA *af_list, float freq);
|
||||
uint8_t add_rds_af(RDSAFs *af_list, float freq);
|
||||
char *convert_to_rdscharset(const char *str);
|
||||
@@ -280,7 +280,6 @@ int lua_set_rds_grp_sqc(lua_State *localL) {
|
||||
STR_RAW_GETTER(grp_sqc, 32)
|
||||
|
||||
AF_SETTER(af_group0, af, RDSAFs, add_rds_af)
|
||||
AF_SETTER(af_oda, af_oda, RDSAFsODA, add_rds_af_oda)
|
||||
|
||||
int lua_set_rds_eon(lua_State *localL) {
|
||||
int eon = luaL_checkinteger(localL, 1);
|
||||
@@ -507,7 +506,6 @@ void init_lua(RDSModulator* rds_mod) {
|
||||
lua_register(L, "put_rds2_custom_group", lua_put_rds2_custom_group);
|
||||
|
||||
lua_register(L, "set_rds_af_group0", lua_set_rds_af_group0);
|
||||
lua_register(L, "set_rds_af_oda", lua_set_rds_af_oda);
|
||||
|
||||
lua_register(L, "set_rds_eon", lua_set_rds_eon);
|
||||
lua_register(L, "get_rds_eon", lua_get_rds_eon);
|
||||
|
||||
14
src/rds.c
14
src/rds.c
@@ -7,13 +7,10 @@
|
||||
|
||||
// declarations (stupid c)
|
||||
uint16_t get_next_af(RDSEncoder* enc);
|
||||
void get_next_af_oda(RDSEncoder* enc, uint16_t* af_group);
|
||||
uint16_t get_next_af_eon(RDSEncoder* enc, uint8_t eon_index);
|
||||
void get_rds_ps_group(RDSEncoder* enc, RDSGroup *group);
|
||||
void get_rds_fasttuning_group(RDSEncoder* enc, RDSGroup *group);
|
||||
void get_rds_rt_group(RDSEncoder* enc, RDSGroup *group);
|
||||
void get_rdsp_oda_af_oda_group(RDSGroup *group);
|
||||
void get_rds_oda_af_group(RDSEncoder* enc, RDSGroup *group);
|
||||
void get_rdsp_ct_group(RDSGroup *group, time_t now);
|
||||
void get_rds_lps_group(RDSEncoder* enc, RDSGroup *group);
|
||||
void get_rds_ecc_group(RDSEncoder* enc, RDSGroup *group);
|
||||
@@ -23,8 +20,6 @@ void get_rds_eon_group(RDSEncoder* enc, RDSGroup *group);
|
||||
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);
|
||||
void get_rds_user_oda_group(RDSEncoder* enc, RDSGroup *group);
|
||||
int get_rds_user_oda_group_content(RDSEncoder* enc, RDSGroup *group);
|
||||
|
||||
#define HANDLE_UDG_STREAM(chan_idx, udg_prefix) \
|
||||
do { \
|
||||
@@ -96,12 +91,8 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp,
|
||||
case 'S':
|
||||
case 'O':
|
||||
case 'K':
|
||||
if(get_rdsp_lua_group(group, *grp) == 0) get_rds_ps_group(enc, group);
|
||||
break;
|
||||
case 'U':
|
||||
if(enc->state[enc->program].af_oda == 0) get_rds_oda_af_group(enc, group);
|
||||
else get_rdsp_oda_af_oda_group(group);
|
||||
TOGGLE(enc->state[enc->program].af_oda);
|
||||
if(get_rdsp_lua_group(group, *grp) == 0) get_rds_ps_group(enc, group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -124,8 +115,7 @@ static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) {
|
||||
if(*grp == 'Y' && enc->data[enc->program].udg2_len != 0) good_group = 1;
|
||||
if(*grp == 'F' && enc->data[enc->program].lps[0] != '\0') good_group = 1;
|
||||
if(*grp == 'T') good_group = 1;
|
||||
if(*grp == 'L' || *grp == 'R' || *grp == 'P' || *grp == 'S' || *grp == 'O' || *grp == 'K') good_group = 1;
|
||||
if(*grp == 'U' && enc->data[enc->program].af_oda.num_afs) good_group = 1;
|
||||
if(*grp == 'L' || *grp == 'R' || *grp == 'P' || *grp == 'S' || *grp == 'O' || *grp == 'K' || *grp == 'U') good_group = 1;
|
||||
return good_group;
|
||||
}
|
||||
|
||||
|
||||
11
src/rds.h
11
src/rds.h
@@ -27,14 +27,6 @@
|
||||
#define PROGRAMS 3
|
||||
#define EONs 4
|
||||
|
||||
// List of ODAs: https://www.nrscstandards.org/committees/dsm/archive/rds-oda-aids.pdf
|
||||
#define ODA_AID_ODAAF 0x6365
|
||||
|
||||
typedef struct {
|
||||
uint8_t num_entries : 6;
|
||||
uint8_t num_afs : 5;
|
||||
uint16_t afs[MAX_AFS]; // 9 bit, there was no uint9_t
|
||||
} RDSAFsODA;
|
||||
typedef struct {
|
||||
uint8_t num_entries : 6;
|
||||
uint8_t num_afs : 5;
|
||||
@@ -79,7 +71,6 @@ typedef struct {
|
||||
char ptyn[PTYN_LENGTH];
|
||||
|
||||
RDSAFs af;
|
||||
RDSAFsODA af_oda;
|
||||
|
||||
uint8_t ct : 1;
|
||||
|
||||
@@ -139,7 +130,6 @@ typedef struct {
|
||||
uint8_t rt_switching_period_state;
|
||||
uint8_t rt_text_timeout_state;
|
||||
|
||||
uint8_t af_oda : 1;
|
||||
uint8_t data_ecc : 1;
|
||||
uint8_t grp_seq_idx[4];
|
||||
uint8_t udg_idxs[2];
|
||||
@@ -158,7 +148,6 @@ typedef struct {
|
||||
RDSEONState eon_states[4];
|
||||
|
||||
uint8_t af_state : 6;
|
||||
uint8_t af_oda_state : 6;
|
||||
|
||||
uint8_t eon_linkage : 1;
|
||||
|
||||
|
||||
@@ -21,21 +21,6 @@ uint16_t get_next_af(RDSEncoder* enc) {
|
||||
return out;
|
||||
}
|
||||
|
||||
void get_next_af_oda(RDSEncoder* enc, uint16_t* af_group) {
|
||||
uint8_t offset = 0;
|
||||
if (enc->state[enc->program].af_oda_state == 0) af_group[0] = (AF_CODE_NUM_AFS_BASE + enc->data[enc->program].af_oda.num_afs);
|
||||
else {
|
||||
af_group[0] = enc->data[enc->program].af_oda.afs[enc->state[enc->program].af_oda_state++];
|
||||
offset++;
|
||||
}
|
||||
for(int i = 0; i < 3; i++) {
|
||||
if (enc->data[enc->program].af_oda.afs[enc->state[enc->program].af_oda_state + offset]) af_group[i + 1] = enc->data[enc->program].af_oda.afs[enc->state[enc->program].af_oda_state + offset];
|
||||
else af_group[i + 1] = AF_CODE_FILLER;
|
||||
enc->state[enc->program].af_oda_state++;
|
||||
}
|
||||
if (enc->state[enc->program].af_oda_state >= enc->data[enc->program].af_oda.num_entries) enc->state[enc->program].af_oda_state = 0;
|
||||
}
|
||||
|
||||
uint16_t get_next_af_eon(RDSEncoder* enc, uint8_t eon_index) {
|
||||
uint16_t out;
|
||||
|
||||
@@ -142,26 +127,6 @@ void get_rds_rt_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
if (enc->state[enc->program].rt_state >= segments || enc->state[enc->program].rt_state >= 16) enc->state[enc->program].rt_state = 0;
|
||||
}
|
||||
|
||||
void get_rdsp_oda_af_oda_group(RDSGroup *group) {
|
||||
group->b |= 3 << 12;
|
||||
group->b |= 7 << 1;
|
||||
group->d = ODA_AID_ODAAF;
|
||||
}
|
||||
|
||||
void get_rds_oda_af_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
uint16_t af[4];
|
||||
get_next_af_oda(enc, af);
|
||||
|
||||
group->b |= 7 << 12;
|
||||
for (int i = 0; i < 4; i++) group->b |= ((af[i] >> 8) & 1) << i;
|
||||
|
||||
group->c = (af[0] & 0xFF) << 8;
|
||||
group->c |= af[1] & 0xFF;
|
||||
|
||||
group->d = (af[2] & 0xFF) << 8;
|
||||
group->d |= af[3] & 0xFF;
|
||||
}
|
||||
|
||||
void get_rdsp_ct_group(RDSGroup *group, time_t now) {
|
||||
struct tm *utc, *local_time;
|
||||
uint8_t l;
|
||||
|
||||
Reference in New Issue
Block a user