0
1
mirror of https://github.com/radio95-rnt/rds95.git synced 2026-02-27 12:53:53 +01:00

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

This commit is contained in:
2025-03-15 12:38:42 +01:00
parent afdc17146b
commit 57b3f62511
4 changed files with 73 additions and 64 deletions

View File

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

View File

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

View File

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

View File

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