From ac8f5d5f9ecdebe15438d28580a76cded3b74902 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Fri, 14 Mar 2025 16:39:03 +0100 Subject: [PATCH] add grpseq --- .vscode/.server-controller-port.log | 2 +- src/ascii_cmd.c | 13 +-- src/rds.c | 166 +++++++++++++++------------- src/rds.h | 63 +++-------- 4 files changed, 116 insertions(+), 128 deletions(-) diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 3e0550a..1ffa33a 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1741789102822, + "time": 1741953769473, "version": "0.0.3" } \ No newline at end of file diff --git a/src/ascii_cmd.c b/src/ascii_cmd.c index fe11646..4b8eecb 100644 --- a/src/ascii_cmd.c +++ b/src/ascii_cmd.c @@ -12,11 +12,6 @@ typedef struct { } command_handler_t; // Command handlers -static void handle_text(unsigned char *arg) { - arg[RT_LENGTH * 2] = 0; - set_rds_rt1(xlat(arg)); -} - static void handle_ptyn(unsigned char *arg) { arg[PTYN_LENGTH] = 0; set_rds_ptyn(xlat(arg)); @@ -212,6 +207,9 @@ static void handle_eccen(unsigned char *arg) { set_rds_ecclic_toggle(arg[0]); } +static void handle_grpseq(unsigned char *arg) { + +} // Command tables organized by delimiter position and command length static const command_handler_t commands_eq3[] = { {"PS", handle_ps, 2}, @@ -236,7 +234,7 @@ static const command_handler_t commands_eq4[] = { }; static const command_handler_t commands_eq5[] = { - {"TEXT", handle_text, 4}, + {"TEXT", handle_rt1, 4}, {"PTYN", handle_ptyn, 4}, {"AFCH", handle_afch, 4}, }; @@ -253,7 +251,8 @@ static const command_handler_t commands_eq6[] = { static const command_handler_t commands_eq7[] = { {"PTYNEN", handle_ptynen, 6}, - {"RTPRUN", handle_rtprun, 6} + {"RTPRUN", handle_rtprun, 6}, + {"GRPSEQ", handle_grpseq, 6} }; // Process a command using the appropriate command table diff --git a/src/rds.c b/src/rds.c index 2e8ccae..e954d21 100644 --- a/src/rds.c +++ b/src/rds.c @@ -10,7 +10,6 @@ static struct rds_params_t rds_data; static struct { uint8_t ecclic_enabled; uint8_t ecc_or_lic; - uint8_t pin_enabled; uint8_t ps_update; uint8_t tps_update; @@ -28,6 +27,8 @@ static struct { uint8_t lps_segments; uint16_t custom_group[GROUP_LENGTH]; + + uint8_t rtp_oda; } rds_state; // #region ODA @@ -126,10 +127,6 @@ static uint8_t get_rds_rt_group(uint16_t *blocks) { rt_state = 0; } - if(!rds_state.rt1_enabled) { - return 0; - } - blocks[1] |= 2 << 12; blocks[1] |= rds_state.rt_ab << 4; blocks[1] |= rt_state; @@ -146,10 +143,6 @@ static uint8_t get_rds_rt_group(uint16_t *blocks) { static void get_rds_oda_group(uint16_t *blocks) { struct rds_oda_t this_oda = odas[oda_state.current]; - if(this_oda.aid == ODA_AID_RTPLUS && rtplus_cfg.enabled == 0) { - return; - } - blocks[1] |= 3 << 12; blocks[1] |= GET_GROUP_TYPE(this_oda.group) << 1; @@ -206,6 +199,10 @@ static void get_rds_ptyn_group(uint16_t *blocks) { rds_state.ptyn_update = 0; } + if(!rds_state.ptyn_enabled) { + return 0; + } + blocks[1] |= 10 << 12 | ptyn_state; blocks[1] |= rds_state.ptyn_ab << 4; blocks[2] = ptyn_text[ptyn_state * 4 + 0] << 8; @@ -238,28 +235,24 @@ static void get_rds_lps_group(uint16_t *blocks) { static void get_rds_ecc_group(uint16_t *blocks) { blocks[1] |= 1 << 12; - if(rds_state.ecclic_enabled) { - blocks[2] = rds_data.ecc; - } + blocks[2] = rds_data.ecc; - if(rds_state.pin_enabled) { - blocks[3] = rds_data.pin_day << 11; - blocks[3] |= rds_data.pin_hour << 6; - blocks[3] |= rds_data.pin_minute; + if(rds_data.pin[0]) { + blocks[3] = rds_data.pin[1] << 11; // day + blocks[3] |= rds_data.pin[2] << 6; // hour + blocks[3] |= rds_data.pin[3]; // minute } } static void get_rds_lic_group(uint16_t *blocks) { blocks[1] |= 1 << 12; - if(rds_state.ecclic_enabled) { - blocks[2] = 0x3000; // 0b0011000000000000 - blocks[2] |= rds_data.lic; - } + blocks[2] = 0x3000; // 0b0011000000000000 + blocks[2] |= rds_data.lic; - if(rds_state.pin_enabled) { - blocks[3] = rds_data.pin_day << 11; - blocks[3] |= rds_data.pin_hour << 6; - blocks[3] |= rds_data.pin_minute; + if(rds_data.pin[0]) { + blocks[3] = rds_data.pin[1] << 11; // day + blocks[3] |= rds_data.pin[2] << 6; // hour + blocks[3] |= rds_data.pin[3]; // minute } } static void get_rds_rtplus_group(uint16_t *blocks) { @@ -329,22 +322,6 @@ static uint8_t get_rds_other_groups(uint16_t *blocks) { return 0; } -static uint8_t get_rds_long_text_groups(uint16_t *blocks) { - static uint8_t group_selector = 0; - - if (group_selector == 4 && rds_data.lps[0]) { - get_rds_lps_group(blocks); - goto group_coded; - } - - if (++group_selector >= 8) group_selector = 0; - return 0; - -group_coded: - if (++group_selector >= 8) group_selector = 0; - return 1; -} - static uint8_t get_rds_custom_groups(uint16_t *blocks) { if(rds_state.custom_group[0] == 1) { rds_state.custom_group[0] = 0; @@ -374,23 +351,66 @@ static void get_rds_group(uint16_t *blocks) { goto group_coded; } - if (get_rds_long_text_groups(blocks)) { - goto group_coded; - } - if (get_rds_other_groups(blocks)) { - goto group_coded; + uint8_t good_group = 0; + char grp; + + while(good_group == 0) { + uint8_t grp_sqc_idx = rds_data.grp_sqc[0]++; + if(rds_data.grp_sqc[grp_sqc_idx+1] == '\0') { + rds_data.grp_sqc[0] = 0; + grp_sqc_idx = 0; + } + grp = rds_data.grp_sqc[grp_sqc_idx+1]; + + if(grp == '0') good_group = 1; + if(grp == '1' && rds_state.ecclic_enabled) good_group = 1; + if(grp == '2' && rds_state.rt1_enabled) good_group = 1; + if(grp == 'A' && rds_state.ptyn_enabled) good_group = 1; + if(grp == 'R' && rtplus_cfg.enabled) good_group = 1; + if(grp == '3' && oda_state.count != 0) good_group = 1; + if(grp == 'F' && rds_data.lps[0] != '\0') good_group = 1; } - if(state < 6) { - get_rds_ps_group(blocks); - state++; - } else if(state >= 6) { - if(!get_rds_rt_group(blocks)) { - get_rds_ps_group(blocks); - } - state++; + switch (grp) + { + default: + case '0': + if(rds_data.grp_sqc[1] != 3) rds_data.grp_sqc[0]--; + rds_data.grp_sqc[1]++; + get_rds_ps_group(); + goto group_coded; + case '1': + if(rds_state.ecc_or_lic == 0) { + get_rds_ecc_group(blocks); + } else { + get_rds_lic_group(blocks); + } + rds_state.ecc_or_lic ^= 1; + goto group_coded; + case'2': + get_rds_rt_group(blocks); + goto group_coded; + case 'A': + get_rds_ptyn_group(blocks); + goto group_coded; + // TODO: Add EON and UDG + case 'R': + if(rds_state.rtp_oda == 0) { + get_rds_rtplus_group(blocks); + } else { + get_rds_oda_group(blocks); + } + rds_state.rtp_oda ^= 1; + goto group_coded; + // TODO: add uecp + case '3': + get_rds_oda_group(blocks); + goto group_coded; + case 'F': + get_rds_lps_group(blocks); + goto group_coded; } - if (state >= 12) state = 0; + group_coded: if (IS_TYPE_B(blocks)) { @@ -435,6 +455,7 @@ void init_rds_encoder(struct rds_params_t rds_params) { set_rds_ct(1); set_rds_ms(1); set_rds_di(DI_STEREO | DI_DPTY); + set_rds_grpseq("00012222FF"); init_rtplus(GROUP_11A); @@ -458,13 +479,13 @@ void set_rds_ecclic_toggle(uint8_t toggle) { } void set_rds_pin_enabled(uint8_t enabled) { - rds_state.pin_enabled = enabled & INT8_0; + rds_data.pin[0] = enabled & 1; } void set_rds_pin(uint8_t day, uint8_t hour, uint8_t minute) { - rds_data.pin_day = (day & INT8_L5); - rds_data.pin_hour = (hour & INT8_L5); - rds_data.pin_minute = (minute & INT8_L6); + rds_data.pin[1] = (day & INT8_L5); + rds_data.pin[2] = (hour & INT8_L5); + rds_data.pin[3] = (minute & INT8_L6); } void set_rds_rt1_enabled(uint8_t rt1en) { @@ -473,13 +494,6 @@ void set_rds_rt1_enabled(uint8_t rt1en) { void set_rds_rt1(unsigned char *rt1) { uint8_t i = 0, len = 0; - if(rt1[0] == '\0') { - rds_state.rt1_enabled = 0; - return; - } else { - rds_state.rt1_enabled = 1; - } - rds_state.rt_update = 1; memset(rds_data.rt1, ' ', RT_LENGTH); @@ -549,11 +563,7 @@ void set_rds_lps(unsigned char *lps) { } void set_rds_rtplus_flags(uint8_t flags) { - if(flags == 2) { - rtplus_cfg.enabled = 0; - } else { - rtplus_cfg.enabled = 1; - } + rtplus_cfg.enabled = (flags==2); rtplus_cfg.running = flags & INT8_0; } @@ -579,22 +589,23 @@ void clear_rds_af() { } void set_rds_pty(uint8_t pty) { - rds_data.pty = pty & INT8_L5; + rds_data.pty = pty & 31; } void set_rds_ptyn_enabled(uint8_t enabled) { - rds_state.ptyn_enabled = enabled & INT8_0; + rds_state.ptyn_enabled = enabled & 1; } void set_rds_ptyn(unsigned char *ptyn) { uint8_t len = 0; - if (!ptyn[0]) { + rds_state.ptyn_update = 1; + + if(ptyn[0] == '\0') { memset(rds_data.ptyn, 0, PTYN_LENGTH); return; } - rds_state.ptyn_update = 1; memset(rds_data.ptyn, ' ', PTYN_LENGTH); while (*ptyn != 0 && len < PTYN_LENGTH) rds_data.ptyn[len++] = *ptyn++; @@ -626,3 +637,10 @@ void set_rds_cg(uint16_t* blocks) { rds_state.custom_group[2] = blocks[1]; rds_state.custom_group[3] = blocks[2]; } + +void set_rds_grpseq(unsigned char* grpseq) { + uint8_t len; + memset(rds_data.grp_sqc+2, ' ', 24); + while (*grpseq != 0 && len < 24) + rds_data.grp_sqc[2+len++] = *grpseq++; +} \ No newline at end of file diff --git a/src/rds.h b/src/rds.h index bb6fab7..3ebe7bc 100644 --- a/src/rds.h +++ b/src/rds.h @@ -15,17 +15,11 @@ #define FILTER_SIZE 24 #define SAMPLE_BUFFER_SIZE (SAMPLES_PER_BIT + FILTER_SIZE) -/* Text items - * - */ #define RT_LENGTH 64 #define PS_LENGTH 8 #define PTYN_LENGTH 8 #define LPS_LENGTH 32 -/* AF list size - * - */ #define MAX_AFS 25 typedef struct rds_af_t { @@ -34,56 +28,39 @@ typedef struct rds_af_t { uint8_t afs[MAX_AFS]; } rds_af_t; -/* AF codes */ #define AF_CODE_FILLER 205 #define AF_CODE_NO_AF 224 #define AF_CODE_NUM_AFS_BASE AF_CODE_NO_AF #define AF_CODE_LFMF_FOLLOWS 250 typedef struct rds_params_t { - uint16_t pi; /*Program Identification*/ - uint16_t lic; /* Language Identification code. lic should have 12 bits, 16 is the closest */ - uint8_t ecc; /* Extended Country Code*/ - uint8_t ta; /* Traffic Annoucement*/ - uint8_t pty; /* Program Type */ - uint8_t tp; /* Traffic Program */ - uint8_t ms; /* Music/Speech */ - uint8_t di; /* Decoder ID */ + uint16_t pi; + uint16_t lic; + uint8_t ecc; + uint8_t ta; + uint8_t pty; + uint8_t tp; + uint8_t ms; + uint8_t di; - /* Program Service */ unsigned char ps[PS_LENGTH]; - /* Traffic PS */ unsigned char tps[PS_LENGTH]; - /* Radio Text */ unsigned char rt1[RT_LENGTH]; - /* Program Type Name */ unsigned char ptyn[PTYN_LENGTH]; - /* Alternative Frequencies */ struct rds_af_t af; - /* Clock-time */ uint8_t ct; - /* Long PS */ unsigned char lps[LPS_LENGTH]; - /* Program Item Number */ - uint8_t pin_day; - uint8_t pin_hour; - uint8_t pin_minute; -} rds_params_t; -/* Here, the first member of the struct must be a scalar to avoid a - warning on -Wmissing-braces with GCC < 4.8.3 - (bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) -*/ + uint8_t pin[4]; + + unsigned char grp_sqc[26]; +} rds_params_t; -/* Group type - * - * 0-15 - */ #define GROUP_TYPE_0 ( 0 << 4) #define GROUP_TYPE_1 ( 1 << 4) #define GROUP_TYPE_2 ( 2 << 4) @@ -101,15 +78,9 @@ typedef struct rds_params_t { #define GROUP_TYPE_14 (14 << 4) #define GROUP_TYPE_15 (15 << 4) -/* Group versions - * - * The first 4 bits are the group number and the remaining 4 are - * the group version - */ #define GROUP_VER_A 0 #define GROUP_VER_B 1 -/* Version A groups */ #define GROUP_0A (GROUP_TYPE_0 | GROUP_VER_A) #define GROUP_1A (GROUP_TYPE_1 | GROUP_VER_A) #define GROUP_2A (GROUP_TYPE_2 | GROUP_VER_A) @@ -127,7 +98,6 @@ typedef struct rds_params_t { #define GROUP_14A (GROUP_TYPE_14 | GROUP_VER_A) #define GROUP_15A (GROUP_TYPE_15 | GROUP_VER_A) -/* Version B groups */ #define GROUP_0B (GROUP_TYPE_0 | GROUP_VER_B) #define GROUP_1B (GROUP_TYPE_1 | GROUP_VER_B) #define GROUP_2B (GROUP_TYPE_2 | GROUP_VER_B) @@ -148,10 +118,10 @@ typedef struct rds_params_t { #define GET_GROUP_TYPE(x) ((x >> 4) & 15) #define GET_GROUP_VER(x) (x & 1) /* only check bit 0 */ -#define DI_STEREO (1 << 0) /* 1 - Stereo */ -#define DI_AH (1 << 1) /* 2 - Artificial Head */ -#define DI_COMPRESSED (1 << 2) /* 4 - Compressed */ -#define DI_DPTY (1 << 3) /* 8 - Dynamic PTY */ +#define DI_STEREO (1 << 0) +#define DI_AH (1 << 1) +#define DI_COMPRESSED (1 << 2) +#define DI_DPTY (1 << 3) /* Bit mask */ @@ -286,5 +256,6 @@ extern void set_rds_ct(uint8_t ct); extern void set_rds_di(uint8_t di); extern float get_rds_sample(); extern void set_rds_cg(uint16_t* blocks); +extern void set_rds_grpseq(unsigned char* grpseq); #endif /* RDS_H */