From 57b3f62511d59ceaff3900c7c57c4896c697d650 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sat, 15 Mar 2025 12:38:42 +0100 Subject: [PATCH] add a default grpseq, make the program command clear ta, make all save the program only, no groups in seq = ps and refactor init logic --- README.md | 1 + src/ascii_cmd.c | 14 ++++++--- src/rds.c | 82 +++++++++++++++++++++++-------------------------- src/rds.h | 40 ++++++++++++++---------- 4 files changed, 73 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index a30fbaa..14eefe8 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ # rds95 +rds95 is a ligth weigth RDS encoder for fm95, on a RPI 3B it takes 10% of the cpu, the command pipe expects commands similliar to the PIRA32/P164 with some commands not supported \ No newline at end of file diff --git a/src/ascii_cmd.c b/src/ascii_cmd.c index 72ebe9a..11d7a19 100644 --- a/src/ascii_cmd.c +++ b/src/ascii_cmd.c @@ -227,12 +227,19 @@ static void handle_program(unsigned char *arg, RDSModulator* mod) { int16_t program = strtol((char *)arg, NULL, 10)-1; if(program >= PROGRAMS) program = (PROGRAMS-1); if(program < 0) program = 0; + mod->enc->data[mod->enc->program].ta = 0; + mod->enc->data[(uint8_t)program].ta = 0; mod->enc->program = (uint8_t)program; } static void handle_grpseq(unsigned char *arg, RDSModulator* mod) { - memset(&(mod->enc->data[mod->enc->program].grp_sqc), 0, 24); - memcpy(&(mod->enc->data[mod->enc->program].grp_sqc), arg, 24); + if (arg[0] == '\0') { + memset(&(mod->enc->data[mod->enc->program].grp_sqc), 0, 24); + memcpy(&(mod->enc->data[mod->enc->program].grp_sqc), DEFAULT_GRPSQC, 24); + } else { + memset(&(mod->enc->data[mod->enc->program].grp_sqc), 0, 24); + memcpy(&(mod->enc->data[mod->enc->program].grp_sqc), arg, 24); + } } static void handle_level(unsigned char *arg, RDSModulator* mod) { @@ -305,8 +312,7 @@ static void handle_udg2(unsigned char *arg, RDSModulator* mod) { static void handle_init(unsigned char *arg, RDSModulator* mod) { (void)arg; - removerds(); - init_rds_encoder(mod->enc); + set_rds_defaults(mod->enc, mod->enc->program) } // Command tables organized by delimiter position and command length diff --git a/src/rds.c b/src/rds.c index 59fb28f..ae09df3 100644 --- a/src/rds.c +++ b/src/rds.c @@ -9,17 +9,6 @@ void saveToFile(RDSEncoder *emp, const char *option) { snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsEncoder", getenv("HOME")); FILE *file; - if (strcmp(option, "ALL") == 0) { - file = fopen(encoderPath, "wb"); - if (file == NULL) { - perror("Error opening file"); - return; - } - fwrite(emp, sizeof(RDSEncoder), 1, file); - fclose(file); - return; - } - RDSEncoder tempEncoder; file = fopen(encoderPath, "rb"); if (file != NULL) { @@ -86,6 +75,13 @@ void saveToFile(RDSEncoder *emp, const char *option) { } else if (strcmp(option, "UDG2") == 0) { memcpy(tempEncoder.data[emp->program].udg2, emp->data[emp->program].udg2, sizeof(emp->data[emp->program].udg2)); tempEncoder.data[emp->program].udg2_len = emp->data[emp->program].udg2_len; + } else if (strcmp(option, "ALL") == 0) { + memcpy(emp->data[emp->program], tempEncoder.data[emp->program], sizeof(RDSData)); + memcpy(emp->state[emp->program], tempEncoder.state[emp->program], sizeof(RDSState)); + memcpy(emp->oda_state[emp->program], tempEncoder.oda_state[emp->program], sizeof(RDSODAState)); + memcpy(emp->odas[emp->program], tempEncoder.odas[emp->program], sizeof(RDSODA)*MAX_ODAS); + memcpy(emp->rtpData[emp->program], tempEncoder.rtpData[emp->program], sizeof(RDSRTPlusData)); + tempEncoder.program = emp->program } file = fopen(encoderPath, "wb"); @@ -119,12 +115,6 @@ int rdssaved() { } return 0; } -void removerds() { - char encoderPath[256]; - snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsEncoder", getenv("HOME")); - remove(encoderPath); -} - static void register_oda(RDSEncoder* enc, uint8_t group, uint16_t aid, uint16_t scb) { if (enc->oda_state[enc->program].count >= MAX_ODAS) return; @@ -382,7 +372,7 @@ static void get_rds_group(RDSEncoder* enc, uint16_t *blocks) { else cant_find_group = 0; if(!good_group && cant_find_group == 23) { cant_find_group = 0; - return; + get_rds_ps_group(enc, blocks); break; } } @@ -460,36 +450,42 @@ void get_rds_bits(RDSEncoder* enc, uint8_t *bits) { add_checkwords(out_blocks, bits); } -static void init_rtplus(RDSEncoder* enc, uint8_t group) { +static void init_rtplus(RDSEncoder* enc, uint8_t group, uint8_t program) { register_oda(enc, group, ODA_AID_RTPLUS, 0); - enc->rtpData[enc->program].group = group; - enc->rtpData[enc->program].enabled = 0; + enc->rtpData[program].group = group; + enc->rtpData[program].enabled = 0; +} + +void set_rds_defaults(RDSEncoder* enc, uint8_t program) { + memset(enc->data[program], 0, sizeof(RDSData)); + memset(enc->state[program], 0, sizeof(RDSState)); + memset(enc->oda_state[program], 0, sizeof(RDSODAState)); + memset(enc->odas[program], 0, sizeof(RDSODA)*MAX_ODAS); + memset(enc->rtpData[program], 0, sizeof(RDSRTPlusData)); + + enc->data[program].ct = 1; + enc->data[program].di = 1; + enc->data[program].ecclic_enabled = 1; + strcpy((char *)enc->data[program].grp_sqc, DEFAULT_GRPSQC); + enc->data[program].ms = 1; + enc->data[program].pi = 0xFFFF; + strcpy((char *)enc->data[enc->program].ps, "* RDS * "); + enc->data[program].rt1_enabled = 1; + + memset(enc->data[program].rt1, ' ', 64); + enc->data[program].rt1[0] = '\r'; + + enc->state[program].rt_ab = 1; + enc->state[program].ptyn_ab = 1; + enc->state[program].rt_update = 1; + enc->state[program].ps_update = 1; + + init_rtplus(enc, GROUP_11A, program); } void init_rds_encoder(RDSEncoder* enc) { - memset(enc, 0, sizeof(RDSEncoder)); - for(int i = 0; i < PROGRAMS; i++) { - enc->program = i; - - enc->data[enc->program].ct = 1; - enc->data[enc->program].di = 1; - enc->data[enc->program].ecclic_enabled = 1; - strcpy((char *)enc->data[enc->program].grp_sqc, "002222"); - enc->data[enc->program].ms = 1; - enc->data[enc->program].pi = 0xFFFF; - strcpy((char *)enc->data[enc->program].ps, "* RDS * "); - enc->data[enc->program].rt1_enabled = 1; - - memset(enc->data[enc->program].rt1, ' ', 64); - enc->data[enc->program].rt1[0] = '\r'; - - enc->state[enc->program].rt_ab = 1; - enc->state[enc->program].ptyn_ab = 1; - enc->state[enc->program].rt_update = 1; - enc->state[enc->program].ps_update = 1; - - init_rtplus(enc, GROUP_11A); + set_rds_defaults(enc, i); } if (rdssaved()) { diff --git a/src/rds.h b/src/rds.h index 3bb9488..b20fd8f 100644 --- a/src/rds.h +++ b/src/rds.h @@ -19,15 +19,9 @@ #define PS_LENGTH 8 #define PTYN_LENGTH 8 #define LPS_LENGTH 32 - +#define DEFAULT_GRPSQC "022E1022EA022XYR" #define MAX_AFS 25 -typedef struct { - uint8_t num_entries; - uint8_t num_afs; - uint8_t afs[MAX_AFS]; -} RDSAFs; - #define AF_CODE_FILLER 205 #define AF_CODE_NO_AF 224 #define AF_CODE_NUM_AFS_BASE AF_CODE_NO_AF @@ -35,7 +29,25 @@ typedef struct { #define PROGRAMS 2 +#define MAX_ODAS 8 +// List of ODAs: https://www.nrscstandards.org/committees/dsm/archive/rds-oda-aids.pdf +#define ODA_AID_RTPLUS 0x4bd7 + #pragma pack(1) +typedef struct { + uint8_t num_entries; + uint8_t num_afs; + uint8_t afs[MAX_AFS]; +} RDSAFs; +typedef struct { + uint8_t enabled; + uint16_t pi; + uint8_t pin[4]; + unsigned char ps[8]; + uint8_t ta; + uint8_t tp; + RDSAFs af; +} RDSEONs; typedef struct { uint16_t pi; @@ -75,6 +87,8 @@ typedef struct { uint16_t udg1[8][3]; uint16_t udg2[8][3]; + + RDSEONs eon[4]; } RDSData; typedef struct { uint8_t ecc_or_lic; @@ -109,22 +123,15 @@ typedef struct { uint8_t last_ct_minute; } RDSState; - -#define MAX_ODAS 8 - -// List of ODAs: https://www.nrscstandards.org/committees/dsm/archive/rds-oda-aids.pdf -#define ODA_AID_RTPLUS 0x4bd7 -typedef struct rds_oda_t { +typedef struct { uint8_t group; uint16_t aid; uint16_t scb; } RDSODA; - typedef struct { uint8_t current; uint8_t count; } RDSODAState; - typedef struct { uint8_t group; uint8_t enabled; @@ -134,7 +141,6 @@ typedef struct { uint8_t start[2]; uint8_t len[2]; } RDSRTPlusData; - typedef struct { RDSData data[PROGRAMS]; @@ -295,8 +301,8 @@ typedef struct void saveToFile(RDSEncoder *emp, const char *option); void loadFromFile(RDSEncoder *emp); int rdssaved(); -void removerds(); +void set_rds_defaults(RDSEncoder* enc, uint8_t program); void init_rds_encoder(RDSEncoder* enc); void get_rds_bits(RDSEncoder* enc, uint8_t *bits); void set_rds_rt1(RDSEncoder* enc, unsigned char *rt1);