mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-02-26 20:33:53 +01:00
change some ascii logic, reduce source code size, redo some functions and add another way to save rdsmodulator data (this one needs both enc and mod data refresh)
This commit is contained in:
174
src/ascii_cmd.c
174
src/ascii_cmd.c
@@ -17,26 +17,26 @@ typedef struct {
|
||||
} pattern_command_handler_t;
|
||||
|
||||
static void handle_ptyn(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[PTYN_LENGTH * 2] = 0;
|
||||
set_rds_ptyn(mod->enc, convert_to_rds_charset(arg));
|
||||
arg[PTYN_LENGTH+1] = 0;
|
||||
set_rds_ptyn(mod->enc, convert_to_rdscharset(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
static void handle_tps(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[PS_LENGTH * 2] = 0;
|
||||
set_rds_tps(mod->enc, convert_to_rds_charset(arg));
|
||||
arg[PS_LENGTH+1] = 0;
|
||||
set_rds_tps(mod->enc, convert_to_rdscharset(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
static void handle_rt1(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[RT_LENGTH * 2] = 0;
|
||||
set_rds_rt1(mod->enc, convert_to_rds_charset(arg));
|
||||
arg[RT_LENGTH+1] = 0;
|
||||
set_rds_rt1(mod->enc, convert_to_rdscharset(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
static void handle_rt2(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[RT_LENGTH * 2] = 0;
|
||||
set_rds_rt2(mod->enc, convert_to_rds_charset(arg));
|
||||
arg[RT_LENGTH+1] = 0;
|
||||
set_rds_rt2(mod->enc, convert_to_rdscharset(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -56,9 +56,7 @@ static void handle_rtp(char *arg, RDSModulator* mod, char* output) {
|
||||
if (sscanf((char *)arg, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", &tags[0], &tags[1], &tags[2], &tags[3], &tags[4], &tags[5]) == 6) {
|
||||
set_rds_rtplus_tags(mod->enc, tags);
|
||||
strcpy(output, "+\0");
|
||||
} else {
|
||||
strcpy(output, "-\0");
|
||||
}
|
||||
} else strcpy(output, "-\0");
|
||||
}
|
||||
|
||||
static void handle_ertp(char *arg, RDSModulator* mod, char* output) {
|
||||
@@ -67,9 +65,7 @@ static void handle_ertp(char *arg, RDSModulator* mod, char* output) {
|
||||
if (sscanf((char *)arg, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", &tags[0], &tags[1], &tags[2], &tags[3], &tags[4], &tags[5]) == 6) {
|
||||
set_rds_ertplus_tags(mod->enc, tags);
|
||||
strcpy(output, "+\0");
|
||||
} else {
|
||||
strcpy(output, "-\0");
|
||||
}
|
||||
} else strcpy(output, "-\0");
|
||||
}
|
||||
|
||||
static void handle_link(char *arg, RDSModulator* mod, char* output) {
|
||||
@@ -83,20 +79,20 @@ static void handle_link(char *arg, RDSModulator* mod, char* output) {
|
||||
}
|
||||
|
||||
static void handle_lps(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[LPS_LENGTH * 2] = 0;
|
||||
arg[LPS_LENGTH+1] = 0;
|
||||
set_rds_lps(mod->enc, arg);
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
static void handle_ert(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[ERT_LENGTH * 2] = 0;
|
||||
arg[ERT_LENGTH+1] = 0;
|
||||
set_rds_ert(mod->enc, arg);
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
static void handle_ps(char *arg, RDSModulator* mod, char* output) {
|
||||
arg[PS_LENGTH * 2] = 0;
|
||||
set_rds_ps(mod->enc, convert_to_rds_charset(arg));
|
||||
arg[PS_LENGTH+1] = 0;
|
||||
set_rds_ps(mod->enc, convert_to_rdscharset(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -136,10 +132,6 @@ static void handle_pi(char *arg, RDSModulator* mod, char* output) {
|
||||
}
|
||||
|
||||
static void handle_af(char *arg, RDSModulator* mod, char* output) {
|
||||
if (arg[0] == 'A' || arg[0] == 'B') {
|
||||
strcpy(output, "-\0");
|
||||
return;
|
||||
}
|
||||
if(arg[0] == '\0') {
|
||||
memset(&(mod->enc->data[mod->enc->program].af), 0, sizeof(mod->enc->data[mod->enc->program].af));
|
||||
return;
|
||||
@@ -174,10 +166,6 @@ static void handle_af(char *arg, RDSModulator* mod, char* output) {
|
||||
}
|
||||
|
||||
static void handle_afo(char *arg, RDSModulator* mod, char* output) {
|
||||
if (arg[0] == 'A' || arg[0] == 'B') {
|
||||
strcpy(output, "-\0");
|
||||
return;
|
||||
}
|
||||
if(arg[0] == '\0') {
|
||||
memset(&(mod->enc->data[mod->enc->program].af_oda), 0, sizeof(mod->enc->data[mod->enc->program].af_oda));
|
||||
return;
|
||||
@@ -242,7 +230,7 @@ static void handle_rt2en(char *arg, RDSModulator* mod, char* output) {
|
||||
|
||||
static void handle_rtper(char *arg, RDSModulator* mod, char* output) {
|
||||
mod->enc->data[mod->enc->program].rt_switching_period = atoi(arg);
|
||||
mod->enc->data[mod->enc->program].orignal_rt_switching_period = mod->enc->data[mod->enc->program].rt_switching_period;
|
||||
mod->enc->state[mod->enc->program].rt_switching_period_state = mod->enc->data[mod->enc->program].rt_switching_period;
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -256,9 +244,7 @@ static void handle_rtprun(char *arg, RDSModulator* mod, char* output) {
|
||||
if (sscanf(arg, "%d,%d", &flag1, &flag2) == 2) {
|
||||
set_rds_rtplus_flags(mod->enc, flag1);
|
||||
if(flag2) mod->enc->rtpState[mod->enc->program][0].toggle ^= 1;
|
||||
} else {
|
||||
set_rds_rtplus_flags(mod->enc, atoi(arg));
|
||||
}
|
||||
} else set_rds_rtplus_flags(mod->enc, atoi(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -267,9 +253,7 @@ static void handle_ertprun(char *arg, RDSModulator* mod, char* output) {
|
||||
if (sscanf(arg, "%d,%d", &flag1, &flag2) == 2) {
|
||||
set_rds_ertplus_flags(mod->enc, flag1);
|
||||
if(flag2) mod->enc->rtpState[mod->enc->program][1].toggle ^= 1;
|
||||
} else {
|
||||
set_rds_ertplus_flags(mod->enc, atoi(arg));
|
||||
}
|
||||
} else set_rds_ertplus_flags(mod->enc, atoi(arg));
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -293,19 +277,13 @@ static void handle_rds2mod(char *arg, RDSModulator* mod, char* output) {
|
||||
}
|
||||
|
||||
static void handle_grpseq(char *arg, RDSModulator* mod, char* output) {
|
||||
if (arg[0] == '\0') {
|
||||
set_rds_grpseq(mod->enc, DEFAULT_GRPSQC);
|
||||
} else {
|
||||
set_rds_grpseq(mod->enc, arg);
|
||||
}
|
||||
if (arg[0] == '\0') set_rds_grpseq(mod->enc, DEFAULT_GRPSQC);
|
||||
else set_rds_grpseq(mod->enc, arg);
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
static void handle_grpseq2(char *arg, RDSModulator* mod, char* output) {
|
||||
if (arg[0] == '\0') {
|
||||
set_rds_grpseq2(mod->enc, "\0");
|
||||
} else {
|
||||
set_rds_grpseq2(mod->enc, arg);
|
||||
}
|
||||
if (arg[0] == '\0') set_rds_grpseq2(mod->enc, "\0");
|
||||
else set_rds_grpseq2(mod->enc, arg);
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -323,9 +301,7 @@ static void handle_level(char *arg, RDSModulator* mod, char* output) {
|
||||
static void handle_reset(char *arg, RDSModulator* mod, char* output) {
|
||||
(void)arg;
|
||||
loadFromFile(mod->enc);
|
||||
for(int i = 0; i < PROGRAMS; i++) {
|
||||
reset_rds_state(mod->enc, i);
|
||||
}
|
||||
for(int i = 0; i < PROGRAMS; i++) reset_rds_state(mod->enc, i);
|
||||
Modulator_loadFromFile(&mod->params);
|
||||
strcpy(output, "\0");
|
||||
}
|
||||
@@ -342,23 +318,15 @@ static void handle_udg(char *arg, char *pattern, RDSModulator* mod, char* output
|
||||
char *ptr = arg;
|
||||
|
||||
while (sets < 8) {
|
||||
int count = sscanf((char *)ptr, "%4hx%4hx%4hx",
|
||||
&blocks[sets][0], &blocks[sets][1], &blocks[sets][2]);
|
||||
|
||||
int count = sscanf((char *)ptr, "%4hx%4hx%4hx", &blocks[sets][0], &blocks[sets][1], &blocks[sets][2]);
|
||||
if (count != 3) {
|
||||
all_scanned = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
sets++;
|
||||
|
||||
while (*ptr && *ptr != ',') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (*ptr == ',') {
|
||||
ptr++;
|
||||
} else {
|
||||
while (*ptr && *ptr != ',') ptr++;
|
||||
if (*ptr == ',') ptr++;
|
||||
else {
|
||||
bad_format = 1;
|
||||
break;
|
||||
}
|
||||
@@ -370,9 +338,7 @@ static void handle_udg(char *arg, char *pattern, RDSModulator* mod, char* output
|
||||
} else if(strcmp(pattern, "2") == 0) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2), &blocks, sets * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg2_len = sets;
|
||||
} else {
|
||||
strcpy(output, "!\0");
|
||||
}
|
||||
} else strcpy(output, "!\0");
|
||||
if(bad_format) strcpy(output, "-\0");
|
||||
else if(all_scanned) strcpy(output, "+\0");
|
||||
else strcpy(output, "/\0");
|
||||
@@ -392,7 +358,7 @@ static void handle_init(char *arg, RDSModulator* mod, char* output) {
|
||||
static void handle_ver(char *arg, RDSModulator* mod, char* output) {
|
||||
(void)arg;
|
||||
(void)mod;
|
||||
sprintf(output, "Encoder v. %s - (C) 2025 radio95", VERSION);
|
||||
sprintf(output, "RDS95 v. %s - (C) 2025 radio95", VERSION);
|
||||
}
|
||||
|
||||
static void handle_eonen(char *arg, char *pattern, RDSModulator* mod, char* output) {
|
||||
@@ -413,7 +379,7 @@ static void handle_eonps(char *arg, char *pattern, RDSModulator* mod, char* outp
|
||||
|
||||
uint16_t len = 0;
|
||||
while (*arg != 0 && len < 24) eon->ps[len++] = *arg++;
|
||||
|
||||
|
||||
strcpy(output, "+\0");
|
||||
}
|
||||
|
||||
@@ -423,7 +389,7 @@ static void handle_eonpty(char *arg, char *pattern, RDSModulator* mod, char* out
|
||||
}
|
||||
|
||||
static void handle_eonta(char *arg, char *pattern, RDSModulator* mod, char* output) {
|
||||
if (!mod->enc->data[mod->enc->program].eon[atoi(pattern)-1].enabled ||
|
||||
if (!mod->enc->data[mod->enc->program].eon[atoi(pattern)-1].enabled ||
|
||||
!mod->enc->data[mod->enc->program].eon[atoi(pattern)-1].tp) {
|
||||
strcpy(output, "-\0");
|
||||
return;
|
||||
@@ -538,7 +504,6 @@ static const command_handler_t commands_exact[] = {
|
||||
{"INIT", handle_init, 4},
|
||||
{"VER", handle_ver, 3},
|
||||
{"RESET", handle_reset, 5},
|
||||
// TODO: handle help, status
|
||||
};
|
||||
|
||||
static const pattern_command_handler_t pattern_commands[] = {
|
||||
@@ -567,49 +532,38 @@ static bool process_command_table(const command_handler_t *table, int table_size
|
||||
static bool process_pattern_commands(char *cmd, char *arg, char *output, RDSModulator* mod) {
|
||||
size_t cmd_len = strlen(cmd);
|
||||
char pattern_buffer[16] = {0};
|
||||
|
||||
for (size_t i = 0; i < sizeof(pattern_commands) / sizeof(pattern_command_handler_t); i++) {
|
||||
const pattern_command_handler_t *handler = &pattern_commands[i];
|
||||
size_t prefix_len = strlen(handler->prefix);
|
||||
size_t suffix_len = strlen(handler->suffix);
|
||||
|
||||
if (cmd_len > (prefix_len + suffix_len) &&
|
||||
strncmp(cmd, handler->prefix, prefix_len) == 0 &&
|
||||
strcmp(cmd + cmd_len - suffix_len, handler->suffix) == 0) {
|
||||
|
||||
if (cmd_len > (prefix_len + suffix_len) && strncmp(cmd, handler->prefix, prefix_len) == 0 && strcmp(cmd + cmd_len - suffix_len, handler->suffix) == 0) {
|
||||
size_t pattern_len = cmd_len - prefix_len - suffix_len;
|
||||
if (pattern_len < sizeof(pattern_buffer)) {
|
||||
strncpy(pattern_buffer, cmd + prefix_len, pattern_len);
|
||||
pattern_buffer[pattern_len] = 0;
|
||||
|
||||
handler->handler(arg, pattern_buffer, mod, output);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output) {
|
||||
char *cmd, *arg;
|
||||
|
||||
char output[255];
|
||||
memset(output, 0, sizeof(output));
|
||||
|
||||
char upper_str[CTL_BUFFER_SIZE];
|
||||
|
||||
uint16_t cmd_len = _strnlen((const char*)str, CTL_BUFFER_SIZE);
|
||||
|
||||
for(uint16_t i = 0; i < cmd_len; i++) {
|
||||
if(str[i] == '\t') str[i] = ' ';
|
||||
}
|
||||
for(uint16_t i = 0; i < cmd_len; i++) if(str[i] == '\t') str[i] = ' ';
|
||||
|
||||
strncpy(upper_str, str, CTL_BUFFER_SIZE);
|
||||
upper_str[CTL_BUFFER_SIZE-1] = '\0';
|
||||
|
||||
for(uint16_t i = 0; i < cmd_len && upper_str[i] != '='; i++) {
|
||||
if(upper_str[i] >= 'a' && upper_str[i] <= 'z') {
|
||||
upper_str[i] = upper_str[i] - 'a' + 'A';
|
||||
}
|
||||
if(upper_str[i] >= 'a' && upper_str[i] <= 'z') upper_str[i] = upper_str[i] - 'a' + 'A';
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(commands_exact) / sizeof(command_handler_t); i++) {
|
||||
@@ -624,8 +578,7 @@ void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output) {
|
||||
const char* option_str = upper_str + 1;
|
||||
char option[32] = {0};
|
||||
size_t copy_len = strlen(option_str);
|
||||
if (copy_len >= sizeof(option))
|
||||
copy_len = sizeof(option) - 1;
|
||||
if (copy_len >= sizeof(option)) copy_len = sizeof(option) - 1;
|
||||
memcpy(option, option_str, copy_len);
|
||||
option[copy_len] = '\0';
|
||||
saveToFile(mod->enc, option);
|
||||
@@ -638,86 +591,67 @@ void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output) {
|
||||
cmd = upper_str;
|
||||
cmd[equals_pos - upper_str] = 0;
|
||||
arg = equals_pos + 1;
|
||||
|
||||
process_pattern_commands(cmd, arg, output, mod);
|
||||
}
|
||||
|
||||
uint8_t cmd_reached = 0;
|
||||
|
||||
if (cmd_len > 1 && str[1] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[1] = 0;
|
||||
arg = str + 2;
|
||||
|
||||
if (process_command_table(commands_eq2,
|
||||
sizeof(commands_eq2) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq2, sizeof(commands_eq2) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_len > 2 && str[2] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[2] = 0;
|
||||
arg = str + 3;
|
||||
|
||||
if (process_command_table(commands_eq3,
|
||||
sizeof(commands_eq3) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq3, sizeof(commands_eq3) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_len > 3 && str[3] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[3] = 0;
|
||||
arg = str + 4;
|
||||
|
||||
if (process_command_table(commands_eq4,
|
||||
sizeof(commands_eq4) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq4, sizeof(commands_eq4) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_len > 4 && str[4] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[4] = 0;
|
||||
arg = str + 5;
|
||||
|
||||
if (process_command_table(commands_eq5,
|
||||
sizeof(commands_eq5) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq5, sizeof(commands_eq5) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_len > 5 && str[5] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[5] = 0;
|
||||
arg = str + 6;
|
||||
|
||||
if (process_command_table(commands_eq6,
|
||||
sizeof(commands_eq6) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq6, sizeof(commands_eq6) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_len > 6 && str[6] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[6] = 0;
|
||||
arg = str + 7;
|
||||
|
||||
if (process_command_table(commands_eq7,
|
||||
sizeof(commands_eq7) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq7, sizeof(commands_eq7) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_len > 7 && str[7] == '=') {
|
||||
cmd = upper_str;
|
||||
cmd[7] = 0;
|
||||
arg = str + 8;
|
||||
|
||||
if (process_command_table(commands_eq8,
|
||||
sizeof(commands_eq8) / sizeof(command_handler_t),
|
||||
cmd, arg, output, mod)) {
|
||||
}
|
||||
process_command_table(commands_eq8, sizeof(commands_eq8) / sizeof(command_handler_t), cmd, arg, output, mod);
|
||||
cmd_reached = 1;
|
||||
}
|
||||
|
||||
if (cmd_output != NULL) strcpy(cmd_output, output);
|
||||
if (cmd_output != NULL && cmd_reached) strcpy(cmd_output, output);
|
||||
if (cmd_reached) strcpy(cmd_output, "?\0");
|
||||
}
|
||||
29
src/lib.c
29
src/lib.c
@@ -32,16 +32,11 @@ uint16_t crc16_ccitt(char* data, uint16_t len) {
|
||||
|
||||
uint16_t get_block_grom_group(RDSGroup *group, uint8_t block) {
|
||||
switch (block) {
|
||||
case 0:
|
||||
return group->a;
|
||||
case 1:
|
||||
return group->b;
|
||||
case 2:
|
||||
return group->c;
|
||||
case 3:
|
||||
return group->d;
|
||||
default:
|
||||
return 0;
|
||||
case 0: return group->a;
|
||||
case 1: return group->b;
|
||||
case 2: return group->c;
|
||||
case 3: return group->d;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +54,7 @@ void add_checkwords(RDSGroup *group, uint8_t *bits)
|
||||
|
||||
for (uint8_t i = 0; i < GROUP_LENGTH; i++) {
|
||||
offset_word = offset_words[i];
|
||||
if (i == 2 && group->is_type_b) {
|
||||
offset_word = offset_words[4];
|
||||
}
|
||||
if (i == 2 && group->is_type_b) offset_word = offset_words[4];
|
||||
|
||||
uint16_t block = get_block_grom_group(group, i);
|
||||
|
||||
@@ -107,9 +100,7 @@ uint8_t add_rds_af_oda(RDSAFsODA *af_list, float freq) {
|
||||
af_list->afs[af_list->num_entries + 0] = AF_CODE_LFMF_FOLLOWS;
|
||||
af_list->afs[af_list->num_entries + 1] = af;
|
||||
af_list->num_entries += 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else return 1;
|
||||
|
||||
af_list->num_afs++;
|
||||
|
||||
@@ -138,16 +129,14 @@ uint8_t add_rds_af(RDSAFs *af_list, float freq) {
|
||||
af_list->afs[af_list->num_entries + 0] = AF_CODE_LFMF_FOLLOWS;
|
||||
af_list->afs[af_list->num_entries + 1] = af;
|
||||
af_list->num_entries += 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else return 1;
|
||||
|
||||
af_list->num_afs++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *convert_to_rds_charset(char *str) {
|
||||
char *convert_to_rdscharset(char *str) {
|
||||
static char new_str[255];
|
||||
uint8_t i = 0;
|
||||
|
||||
|
||||
@@ -9,4 +9,4 @@ uint16_t get_block_grom_group(RDSGroup *group, uint8_t block);
|
||||
extern void add_checkwords(RDSGroup *group, uint8_t *bits);
|
||||
extern uint8_t add_rds_af_oda(RDSAFsODA *af_list, float freq);
|
||||
extern uint8_t add_rds_af(RDSAFs *af_list, float freq);
|
||||
extern char *convert_to_rds_charset(char *str);
|
||||
extern char *convert_to_rdscharset(char *str);
|
||||
@@ -3,53 +3,75 @@
|
||||
static float waveform[2][FILTER_SIZE];
|
||||
|
||||
void Modulator_saveToFile(RDSModulatorParameters *emp, const char *option) {
|
||||
char encoderPath[256];
|
||||
snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsModulator", getenv("HOME"));
|
||||
char modulatorPath[128];
|
||||
snprintf(modulatorPath, sizeof(modulatorPath), "%s/.rdsModulator", getenv("HOME"));
|
||||
FILE *file;
|
||||
|
||||
RDSModulatorParameters tempEncoder;
|
||||
file = fopen(encoderPath, "rb");
|
||||
RDSModulatorParameters tempMod;
|
||||
RDSModulatorParametersFile tempFile;
|
||||
file = fopen(modulatorPath, "rb");
|
||||
if (file != NULL) {
|
||||
fread(&tempEncoder, sizeof(RDSModulatorParameters), 1, file);
|
||||
fread(&tempFile, sizeof(RDSModulatorParametersFile), 1, file);
|
||||
fclose(file);
|
||||
} else {
|
||||
memcpy(&tempEncoder, emp, sizeof(RDSModulatorParameters));
|
||||
memset(&tempFile, 0, sizeof(RDSModulatorParametersFile));
|
||||
tempFile.check = 160;
|
||||
memcpy(&tempFile.params, emp, sizeof(RDSModulatorParameters));
|
||||
tempFile.crc = crc16_ccitt((char*)&tempFile, sizeof(RDSModulatorParametersFile) - sizeof(uint16_t));
|
||||
}
|
||||
memcpy(&tempMod, &tempFile.params, sizeof(RDSModulatorParameters));
|
||||
|
||||
if (strcmp(option, "LEVEL") == 0) {
|
||||
tempEncoder.level = emp->level;
|
||||
tempMod.level = emp->level;
|
||||
} else if (strcmp(option, "RDSGEN") == 0) {
|
||||
tempEncoder.rdsgen = emp->rdsgen;
|
||||
tempMod.rdsgen = emp->rdsgen;
|
||||
} else if (strcmp(option, "ALL") == 0) {
|
||||
tempEncoder.level = emp->level;
|
||||
tempEncoder.rdsgen = emp->rdsgen;
|
||||
tempMod.level = emp->level;
|
||||
tempMod.rdsgen = emp->rdsgen;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&tempFile.params, &tempMod, sizeof(RDSModulatorParameters));
|
||||
tempFile.check = 160;
|
||||
tempFile.crc = crc16_ccitt((char*)&tempFile, sizeof(RDSModulatorParametersFile) - sizeof(uint16_t));
|
||||
|
||||
file = fopen(encoderPath, "wb");
|
||||
file = fopen(modulatorPath, "wb");
|
||||
if (file == NULL) {
|
||||
perror("Error opening file");
|
||||
return;
|
||||
}
|
||||
fwrite(&tempEncoder, sizeof(RDSModulatorParameters), 1, file);
|
||||
fwrite(&tempFile, sizeof(RDSModulatorParameters), 1, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void Modulator_loadFromFile(RDSModulatorParameters *emp) {
|
||||
char encoderPath[256];
|
||||
snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsModulator", getenv("HOME"));
|
||||
FILE *file = fopen(encoderPath, "rb");
|
||||
char modulatorPath[128];
|
||||
snprintf(modulatorPath, sizeof(modulatorPath), "%s/.rdsModulator", getenv("HOME"));
|
||||
FILE *file = fopen(modulatorPath, "rb");
|
||||
if (file == NULL) {
|
||||
perror("Error opening file");
|
||||
return;
|
||||
}
|
||||
fread(emp, sizeof(RDSModulatorParameters), 1, file);
|
||||
RDSModulatorParametersFile tempFile;
|
||||
fread(&tempFile, sizeof(RDSModulatorParametersFile), 1, file);
|
||||
if (tempFile.check != 160) {
|
||||
fprintf(stderr, "[RDSMODULATOR-FILE] Invalid file format\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
uint16_t calculated_crc = crc16_ccitt((char*)&tempFile, sizeof(RDSModulatorParametersFile) - sizeof(uint16_t));
|
||||
if (calculated_crc != tempFile.crc) {
|
||||
fprintf(stderr, "[RDSMODULATOR-FILE] CRC mismatch! Data may be corrupted\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
memcpy(emp, &tempFile.params, sizeof(RDSModulatorParameters));
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
int modulatorsaved() {
|
||||
char encoderPath[256];
|
||||
char encoderPath[128];
|
||||
snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsModulator", getenv("HOME"));
|
||||
FILE *file = fopen(encoderPath, "rb");
|
||||
if (file) {
|
||||
@@ -121,15 +143,6 @@ float get_rds_sample(RDSModulator* rdsMod, uint8_t stream) {
|
||||
rdsMod->data[stream].sample_buffer[rdsMod->data[stream].out_sample_index++] = 0;
|
||||
if (rdsMod->data[stream].out_sample_index == SAMPLE_BUFFER_SIZE) rdsMod->data[stream].out_sample_index = 0;
|
||||
|
||||
uint8_t tooutput = 1;
|
||||
if (rdsMod->params.rdsgen == 0) {
|
||||
tooutput = 0;
|
||||
} else {
|
||||
if(rdsMod->params.rdsgen == 1) {
|
||||
if (stream == 1) {
|
||||
tooutput = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t tooutput = rdsMod->params.rdsgen > stream ? 1 : 0;
|
||||
return sample*rdsMod->params.level*tooutput;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,13 @@ typedef struct
|
||||
uint8_t rdsgen : 2;
|
||||
} RDSModulatorParameters;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t check;
|
||||
RDSModulatorParameters params;
|
||||
uint16_t crc;
|
||||
} RDSModulatorParametersFile;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t symbol_shift: 7;
|
||||
|
||||
333
src/rds.c
333
src/rds.c
@@ -5,7 +5,7 @@
|
||||
#include <time.h>
|
||||
|
||||
void saveToFile(RDSEncoder *emp, const char *option) {
|
||||
char encoderPath[256];
|
||||
char encoderPath[128];
|
||||
snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsEncoder", getenv("HOME"));
|
||||
FILE *file;
|
||||
|
||||
@@ -53,7 +53,7 @@ void saveToFile(RDSEncoder *emp, const char *option) {
|
||||
void loadFromFile(RDSEncoder *enc) {
|
||||
RDSEncoderFile rdsEncoderfile;
|
||||
|
||||
char encoderPath[256];
|
||||
char encoderPath[128];
|
||||
snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsEncoder", getenv("HOME"));
|
||||
FILE *file = fopen(encoderPath, "rb");
|
||||
if (file == NULL) {
|
||||
@@ -69,7 +69,6 @@ void loadFromFile(RDSEncoder *enc) {
|
||||
}
|
||||
|
||||
uint16_t calculated_crc = crc16_ccitt((char*)&rdsEncoderfile, sizeof(RDSEncoderFile) - sizeof(uint16_t));
|
||||
|
||||
if (calculated_crc != rdsEncoderfile.crc) {
|
||||
fprintf(stderr, "[RDSENCODER-FILE] CRC mismatch! Data may be corrupted\n");
|
||||
return;
|
||||
@@ -84,7 +83,7 @@ void loadFromFile(RDSEncoder *enc) {
|
||||
}
|
||||
|
||||
int rdssaved() {
|
||||
char encoderPath[256];
|
||||
char encoderPath[128];
|
||||
snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsEncoder", getenv("HOME"));
|
||||
FILE *file = fopen(encoderPath, "rb");
|
||||
if (file) {
|
||||
@@ -99,40 +98,32 @@ static uint16_t get_next_af(RDSEncoder* enc) {
|
||||
|
||||
if (enc->data[enc->program].af.num_afs) {
|
||||
if (enc->state[enc->program].af_state == 0) {
|
||||
out = (AF_CODE_NUM_AFS_BASE + enc->data[enc->program].af.num_afs) << 8;
|
||||
out |= enc->data[enc->program].af.afs[0];
|
||||
enc->state[enc->program].af_state += 1;
|
||||
out = (AF_CODE_NUM_AFS_BASE + enc->data[enc->program].af.num_afs) << 8 | enc->data[enc->program].af.afs[0];
|
||||
enc->state[enc->program].af_state++;
|
||||
} else {
|
||||
out = enc->data[enc->program].af.afs[enc->state[enc->program].af_state] << 8;
|
||||
if (enc->data[enc->program].af.afs[enc->state[enc->program].af_state + 1]) {
|
||||
out |= enc->data[enc->program].af.afs[enc->state[enc->program].af_state + 1];
|
||||
} else {
|
||||
if (enc->data[enc->program].af.afs[enc->state[enc->program].af_state + 1]) out |= enc->data[enc->program].af.afs[enc->state[enc->program].af_state + 1];
|
||||
else {
|
||||
out |= AF_CODE_FILLER;
|
||||
enc->state[enc->program].af_state += 2;
|
||||
}
|
||||
}
|
||||
if (enc->state[enc->program].af_state >= enc->data[enc->program].af.num_entries) enc->state[enc->program].af_state = 0;
|
||||
} else {
|
||||
out = AF_CODE_NUM_AFS_BASE << 8 | AF_CODE_FILLER;
|
||||
}
|
||||
} else out = AF_CODE_NUM_AFS_BASE << 8 | AF_CODE_FILLER;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static 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 {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@@ -143,28 +134,22 @@ static uint16_t get_next_af_eon(RDSEncoder* enc, uint8_t eon_index) {
|
||||
|
||||
if (enc->data[enc->program].eon[eon_index].af.num_afs) {
|
||||
if (enc->state[enc->program].eon_states[eon_index].af_state == 0) {
|
||||
out = (AF_CODE_NUM_AFS_BASE + enc->data[enc->program].af.num_afs) << 8;
|
||||
out |= enc->data[enc->program].eon[eon_index].af.afs[0];
|
||||
out = (AF_CODE_NUM_AFS_BASE + enc->data[enc->program].af.num_afs) << 8 | enc->data[enc->program].eon[eon_index].af.afs[0];
|
||||
enc->state[enc->program].eon_states[eon_index].af_state += 1;
|
||||
} else {
|
||||
out = enc->data[enc->program].eon[eon_index].af.afs[enc->state[enc->program].eon_states[eon_index].af_state] << 8;
|
||||
if (enc->data[enc->program].eon[eon_index].af.afs[enc->state[enc->program].eon_states[eon_index].af_state + 1]) {
|
||||
out |= enc->data[enc->program].eon[eon_index].af.afs[enc->state[enc->program].eon_states[eon_index].af_state + 1];
|
||||
} else {
|
||||
if (enc->data[enc->program].eon[eon_index].af.afs[enc->state[enc->program].eon_states[eon_index].af_state + 1]) out |= enc->data[enc->program].eon[eon_index].af.afs[enc->state[enc->program].eon_states[eon_index].af_state + 1];
|
||||
else {
|
||||
out |= AF_CODE_FILLER;
|
||||
enc->state[enc->program].eon_states[eon_index].af_state += 2;
|
||||
}
|
||||
}
|
||||
if (enc->state[enc->program].eon_states[eon_index].af_state >= enc->data[enc->program].eon[eon_index].af.num_entries) enc->state[enc->program].eon_states[eon_index].af_state = 0;
|
||||
} else {
|
||||
out = AF_CODE_NUM_AFS_BASE << 8 | AF_CODE_FILLER;
|
||||
}
|
||||
} else out = AF_CODE_NUM_AFS_BASE << 8 | AF_CODE_FILLER;
|
||||
|
||||
return out;
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Group encoding
|
||||
static void get_rds_ps_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
if(enc->state[enc->program].ps_csegment == 0) {
|
||||
if(enc->state[enc->program].ps_update) {
|
||||
@@ -194,35 +179,33 @@ static void get_rds_ps_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
|
||||
static void get_rds_fasttuning_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
group->b |= 15 << 12;
|
||||
|
||||
group->b |= 1 << 11;
|
||||
group->is_type_b = 1;
|
||||
|
||||
group->b |= enc->data[enc->program].ta << 4;
|
||||
if(enc->state[enc->program].fasttuning_state == 0) group->b |= enc->data[enc->program].dpty << 2;
|
||||
group->b |= enc->state[enc->program].fasttuning_state;
|
||||
|
||||
// are blocks b and d the same or not?
|
||||
group->d = group->b;
|
||||
|
||||
enc->state[enc->program].fasttuning_state++;
|
||||
if (enc->state[enc->program].fasttuning_state == 4) enc->state[enc->program].fasttuning_state = 0;
|
||||
|
||||
group->is_type_b = 1;
|
||||
}
|
||||
|
||||
static void get_rds_rt_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
if (enc->state[enc->program].rt_update && enc->data[enc->program].rt1_enabled && !enc->state[enc->program].current_rt) {
|
||||
if (enc->state[enc->program].rt_update && enc->data[enc->program].rt1_enabled && !enc->data[enc->program].current_rt) {
|
||||
memcpy(enc->state[enc->program].rt_text, enc->data[enc->program].rt1, RT_LENGTH);
|
||||
enc->state[enc->program].rt_ab ^= 1;
|
||||
enc->state[enc->program].rt_update = 0;
|
||||
enc->state[enc->program].rt_state = 0;
|
||||
enc->state[enc->program].current_rt = 0;
|
||||
enc->data[enc->program].current_rt = 0;
|
||||
}
|
||||
if(enc->state[enc->program].rt2_update && enc->data[enc->program].rt2_enabled && enc->state[enc->program].current_rt) {
|
||||
if(enc->state[enc->program].rt2_update && enc->data[enc->program].rt2_enabled && enc->data[enc->program].current_rt) {
|
||||
memcpy(enc->state[enc->program].rt_text, enc->data[enc->program].rt2, RT_LENGTH);
|
||||
enc->state[enc->program].rt_ab ^= 1;
|
||||
enc->state[enc->program].rt2_update = 0;
|
||||
enc->state[enc->program].rt_state = 0;
|
||||
enc->state[enc->program].current_rt = 1;
|
||||
enc->data[enc->program].current_rt = 1;
|
||||
}
|
||||
|
||||
uint8_t ab = enc->state[enc->program].rt_ab;
|
||||
@@ -232,9 +215,8 @@ static void get_rds_rt_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
ab = 0;
|
||||
break;
|
||||
case 1:
|
||||
ab = (enc->state[enc->program].current_rt == 0) ? 0 : 1;
|
||||
ab = (enc->data[enc->program].current_rt == 0) ? 0 : 1;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -247,14 +229,13 @@ static void get_rds_rt_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
group->d = enc->state[enc->program].rt_text[enc->state[enc->program].rt_state * 4 + 2] << 8;
|
||||
group->d |= enc->state[enc->program].rt_text[enc->state[enc->program].rt_state * 4 + 3];
|
||||
|
||||
uint8_t segments = (enc->state[enc->program].current_rt == 1) ? enc->state[enc->program].rt2_segments : enc->state[enc->program].rt_segments;
|
||||
uint8_t segments = (enc->data[enc->program].current_rt == 1) ? enc->state[enc->program].rt2_segments : enc->state[enc->program].rt_segments;
|
||||
enc->state[enc->program].rt_state++;
|
||||
if (enc->state[enc->program].rt_state == segments) enc->state[enc->program].rt_state = 0;
|
||||
}
|
||||
static void get_rds_rtp_oda_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
(void)enc;
|
||||
group->b |= 3 << 12;
|
||||
|
||||
group->b |= 11 << 1;
|
||||
group->d = ODA_AID_RTPLUS;
|
||||
}
|
||||
@@ -338,7 +319,7 @@ static void get_rds_ptyn_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
|
||||
group->b |= 10 << 12 | enc->state[enc->program].ptyn_state;
|
||||
group->b |= enc->state[enc->program].ptyn_ab << 4;
|
||||
group->c = enc->state[enc->program].ptyn_text[enc->state[enc->program].ptyn_state * 4 + 0] << 8;
|
||||
group->c = enc->state[enc->program].ptyn_text[enc->state[enc->program].ptyn_state * 4] << 8;
|
||||
group->c |= enc->state[enc->program].ptyn_text[enc->state[enc->program].ptyn_state * 4 + 1];
|
||||
group->d = enc->state[enc->program].ptyn_text[enc->state[enc->program].ptyn_state * 4 + 2] << 8;
|
||||
group->d |= enc->state[enc->program].ptyn_text[enc->state[enc->program].ptyn_state * 4 + 3];
|
||||
@@ -354,7 +335,7 @@ static void get_rds_lps_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
}
|
||||
|
||||
group->b |= 15 << 12 | enc->state[enc->program].lps_state;
|
||||
group->c = enc->state[enc->program].lps_text[enc->state[enc->program].lps_state * 4 ] << 8;
|
||||
group->c = enc->state[enc->program].lps_text[enc->state[enc->program].lps_state * 4] << 8;
|
||||
group->c |= enc->state[enc->program].lps_text[enc->state[enc->program].lps_state * 4 + 1];
|
||||
group->d = enc->state[enc->program].lps_text[enc->state[enc->program].lps_state * 4 + 2] << 8;
|
||||
group->d |= enc->state[enc->program].lps_text[enc->state[enc->program].lps_state * 4 + 3];
|
||||
@@ -408,54 +389,56 @@ static void get_rds_ertplus_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
|
||||
static void get_rds_eon_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
RDSEON eon;
|
||||
get_eon:
|
||||
eon = enc->data[enc->program].eon[enc->state[enc->program].eon_index];
|
||||
group->b |= 14 << 12;
|
||||
group->b |= eon.tp << 4;
|
||||
while(1) {
|
||||
group->b |= 14 << 12;
|
||||
group->b |= eon.tp << 4;
|
||||
|
||||
switch (enc->state[enc->program].eon_state)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
group->c = eon.ps[enc->state[enc->program].eon_state*2] << 8;
|
||||
group->c |= eon.ps[enc->state[enc->program].eon_state*2 + 1];
|
||||
group->b |= enc->state[enc->program].eon_state;
|
||||
break;
|
||||
case 4:
|
||||
group->c = get_next_af_eon(enc, enc->state[enc->program].eon_index);
|
||||
group->b |= enc->state[enc->program].eon_state;
|
||||
break;
|
||||
case 5: // 13
|
||||
group->c = eon.pty << 11;
|
||||
if(eon.tp) group->c |= eon.ta;
|
||||
group->b |= 13;
|
||||
break;
|
||||
case 6: // 15
|
||||
group->c = eon.data;
|
||||
group->b |= 15;
|
||||
break;
|
||||
}
|
||||
|
||||
group->d = eon.pi;
|
||||
|
||||
if(enc->state[enc->program].eon_state == 6) {
|
||||
enc->state[enc->program].eon_index++;
|
||||
|
||||
uint8_t i = 0;
|
||||
while(i < 4 && !enc->data[enc->program].eon[enc->state[enc->program].eon_index].enabled) {
|
||||
enc->state[enc->program].eon_index++;
|
||||
if(enc->state[enc->program].eon_index >= 4) {
|
||||
enc->state[enc->program].eon_index = 0;
|
||||
}
|
||||
i++;
|
||||
switch (enc->state[enc->program].eon_state)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
group->c = eon.ps[enc->state[enc->program].eon_state*2] << 8;
|
||||
group->c |= eon.ps[enc->state[enc->program].eon_state*2+1];
|
||||
group->b |= enc->state[enc->program].eon_state;
|
||||
break;
|
||||
case 4:
|
||||
group->c = get_next_af_eon(enc, enc->state[enc->program].eon_index);
|
||||
group->b |= enc->state[enc->program].eon_state;
|
||||
break;
|
||||
case 5: // 13
|
||||
group->c = eon.pty << 11;
|
||||
if(eon.tp) group->c |= eon.ta;
|
||||
group->b |= 13;
|
||||
break;
|
||||
case 6: // 15
|
||||
group->c = eon.data;
|
||||
group->b |= 15;
|
||||
break;
|
||||
}
|
||||
|
||||
enc->state[enc->program].eon_state = 0;
|
||||
goto get_eon;
|
||||
} else {
|
||||
enc->state[enc->program].eon_state++;
|
||||
group->d = eon.pi;
|
||||
|
||||
if(enc->state[enc->program].eon_state == 6) {
|
||||
enc->state[enc->program].eon_index++;
|
||||
|
||||
uint8_t i = 0;
|
||||
while(i < 4 && !enc->data[enc->program].eon[enc->state[enc->program].eon_index].enabled) {
|
||||
enc->state[enc->program].eon_index++;
|
||||
if(enc->state[enc->program].eon_index == 4) {
|
||||
enc->state[enc->program].eon_index = 0;
|
||||
}
|
||||
eon = enc->data[enc->program].eon[enc->state[enc->program].eon_index];
|
||||
i++;
|
||||
}
|
||||
|
||||
enc->state[enc->program].eon_state = 0;
|
||||
} else {
|
||||
enc->state[enc->program].eon_state++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,15 +449,14 @@ static void get_rds_ert_group(RDSEncoder* enc, RDSGroup *group) {
|
||||
}
|
||||
|
||||
group->b |= 12 << 12 | (enc->state[enc->program].ert_state & 31);
|
||||
group->c = enc->state[enc->program].ert_text[enc->state[enc->program].ert_state * 4 ] << 8;
|
||||
group->c = enc->state[enc->program].ert_text[enc->state[enc->program].ert_state * 4] << 8;
|
||||
group->c |= enc->state[enc->program].ert_text[enc->state[enc->program].ert_state * 4 + 1];
|
||||
group->d = enc->state[enc->program].ert_text[enc->state[enc->program].ert_state * 4 + 2] << 8;
|
||||
group->d = enc->state[enc->program].ert_text[enc->state[enc->program].ert_state * 4 + 2] << 8;
|
||||
group->d |= enc->state[enc->program].ert_text[enc->state[enc->program].ert_state * 4 + 3];
|
||||
|
||||
enc->state[enc->program].ert_state++;
|
||||
if (enc->state[enc->program].ert_state == enc->state[enc->program].ert_segments) enc->state[enc->program].ert_state = 0;
|
||||
}
|
||||
// #endregion
|
||||
|
||||
static uint8_t get_rds_custom_groups(RDSEncoder* enc, RDSGroup *group) {
|
||||
if(enc->state[enc->program].custom_group[0] == 1) {
|
||||
@@ -503,24 +485,21 @@ static uint8_t get_rds_custom_groups2(RDSEncoder* enc, RDSGroup *group) {
|
||||
|
||||
static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp, uint8_t stream) {
|
||||
uint8_t udg_idx;
|
||||
uint8_t idx_seq = (stream == 0) ? 1 : 3;
|
||||
uint8_t idx2_seq = (stream == 0) ? 0 : 2;
|
||||
uint8_t ps_seq_idx = (stream == 0) ? 1 : 3;
|
||||
uint8_t grp_seq_idx = (stream == 0) ? 0 : 2;
|
||||
switch (*grp)
|
||||
{
|
||||
default:
|
||||
case '0':
|
||||
if(enc->state[enc->program].grp_seq_idx[idx_seq] < 4) enc->state[enc->program].grp_seq_idx[idx2_seq]--;
|
||||
else enc->state[enc->program].grp_seq_idx[idx_seq] = 0;
|
||||
if(enc->state[enc->program].grp_seq_idx[ps_seq_idx] < 4) enc->state[enc->program].grp_seq_idx[grp_seq_idx]--;
|
||||
else enc->state[enc->program].grp_seq_idx[ps_seq_idx] = 0;
|
||||
|
||||
enc->state[enc->program].grp_seq_idx[idx_seq]++;
|
||||
enc->state[enc->program].grp_seq_idx[ps_seq_idx]++;
|
||||
get_rds_ps_group(enc, group);
|
||||
goto group_coded;
|
||||
case '1':
|
||||
if(enc->state[enc->program].data_ecc == 0 && enc->data[enc->program].slc_data != 0) {
|
||||
get_rds_slcdata_group(enc, group);
|
||||
} else {
|
||||
get_rds_ecc_group(enc, group);
|
||||
}
|
||||
if(enc->state[enc->program].data_ecc == 0 && enc->data[enc->program].slc_data != 0) get_rds_slcdata_group(enc, group);
|
||||
else get_rds_ecc_group(enc, group);
|
||||
enc->state[enc->program].data_ecc ^= 1;
|
||||
goto group_coded;
|
||||
case '2':
|
||||
@@ -539,6 +518,7 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp,
|
||||
group->d = enc->data[enc->program].udg1[udg_idx][2];
|
||||
enc->state[enc->program].udg_idxs[0]++;
|
||||
if(enc->state[enc->program].udg_idxs[0] == enc->data[enc->program].udg1_len) enc->state[enc->program].udg_idxs[0] = 0;
|
||||
group->is_type_b = (group->a == 0 && IS_TYPE_B(group->b));
|
||||
goto group_coded;
|
||||
case 'Y':
|
||||
udg_idx = enc->state[enc->program].udg_idxs[1];
|
||||
@@ -547,33 +527,24 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp,
|
||||
group->d = enc->data[enc->program].udg2[udg_idx][2];
|
||||
enc->state[enc->program].udg_idxs[1]++;
|
||||
if(enc->state[enc->program].udg_idxs[1] == enc->data[enc->program].udg2_len) enc->state[enc->program].udg_idxs[1] = 0;
|
||||
group->is_type_b = (group->a == 0 && IS_TYPE_B(group->b));
|
||||
goto group_coded;
|
||||
case 'R':
|
||||
if(enc->state[enc->program].rtp_oda == 0) {
|
||||
get_rds_rtplus_group(enc, group);
|
||||
} else {
|
||||
get_rds_rtp_oda_group(enc, group);
|
||||
}
|
||||
if(enc->state[enc->program].rtp_oda == 0) get_rds_rtplus_group(enc, group);
|
||||
else get_rds_rtp_oda_group(enc, group);
|
||||
enc->state[enc->program].rtp_oda ^= 1;
|
||||
goto group_coded;
|
||||
case 'P':
|
||||
if(enc->state[enc->program].ert_oda == 0) {
|
||||
get_rds_ertplus_group(enc, group);
|
||||
} else {
|
||||
get_rds_ertp_oda_group(enc, group);
|
||||
}
|
||||
if(enc->state[enc->program].ert_oda == 0) get_rds_ertplus_group(enc, group);
|
||||
else get_rds_ertp_oda_group(enc, group);
|
||||
|
||||
enc->state[enc->program].ert_oda ^= 1;
|
||||
goto group_coded;
|
||||
case 'S':
|
||||
if(enc->state[enc->program].ert_oda == 0) {
|
||||
get_rds_ert_group(enc, group);
|
||||
} else {
|
||||
get_rds_ert_oda_group(enc, group);
|
||||
}
|
||||
if(enc->state[enc->program].ert_oda == 0) get_rds_ert_group(enc, group);
|
||||
else get_rds_ert_oda_group(enc, group);
|
||||
enc->state[enc->program].ert_oda ^= 1;
|
||||
goto group_coded;
|
||||
// TODO: add uecp
|
||||
// TODO: readd ODA
|
||||
case 'F':
|
||||
get_rds_lps_group(enc, group);
|
||||
goto group_coded;
|
||||
@@ -581,11 +552,8 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp,
|
||||
get_rds_fasttuning_group(enc, group);
|
||||
goto group_coded;
|
||||
case 'U':
|
||||
if(enc->state[enc->program].af_oda == 0) {
|
||||
get_oda_af_group(enc, group);
|
||||
} else {
|
||||
get_oda_af_oda_group(enc, group);
|
||||
}
|
||||
if(enc->state[enc->program].af_oda == 0) get_oda_af_group(enc, group);
|
||||
else get_oda_af_oda_group(enc, group);
|
||||
enc->state[enc->program].af_oda ^= 1;
|
||||
goto group_coded;
|
||||
}
|
||||
@@ -643,27 +611,27 @@ static void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
|
||||
enc->state[enc->program].ta_timeout--;
|
||||
if(enc->state[enc->program].ta_timeout == 0) {
|
||||
enc->data[enc->program].ta = 0;
|
||||
enc->state[enc->program].ta_timeout = enc->state[enc->program].original_ta_timeout;
|
||||
enc->state[enc->program].ta_timeout_state = enc->state[enc->program].ta_timeout;
|
||||
};
|
||||
}
|
||||
|
||||
if(enc->data[enc->program].rt1_enabled && enc->data[enc->program].rt2_enabled && enc->data[enc->program].rt_switching_period != 0) {
|
||||
enc->data[enc->program].rt_switching_period--;
|
||||
if(enc->data[enc->program].rt_switching_period == 0) {
|
||||
enc->state[enc->program].current_rt ^= 1;
|
||||
if (enc->state[enc->program].current_rt == 1) {
|
||||
if(enc->data[enc->program].rt1_enabled && enc->data[enc->program].rt2_enabled && enc->state[enc->program].rt_switching_period_state) {
|
||||
enc->state[enc->program].rt_switching_period_state--;
|
||||
if(enc->state[enc->program].rt_switching_period_state == 0) {
|
||||
enc->data[enc->program].current_rt ^= 1;
|
||||
if (enc->data[enc->program].current_rt == 1) {
|
||||
memcpy(enc->state[enc->program].rt_text, enc->data[enc->program].rt2, RT_LENGTH);
|
||||
} else {
|
||||
memcpy(enc->state[enc->program].rt_text, enc->data[enc->program].rt1, RT_LENGTH);
|
||||
}
|
||||
enc->state[enc->program].rt_state = 0;
|
||||
enc->data[enc->program].rt_switching_period = enc->data[enc->program].orignal_rt_switching_period;
|
||||
enc->state[enc->program].rt_switching_period_state = enc->data[enc->program].rt_switching_period;
|
||||
}
|
||||
}
|
||||
|
||||
if(enc->data[enc->program].rt1_enabled && enc->data[enc->program].rt_text_timeout != 0) {
|
||||
enc->data[enc->program].rt_text_timeout--;
|
||||
if(enc->data[enc->program].rt_text_timeout == 0) {
|
||||
if(enc->data[enc->program].rt1_enabled && enc->data[enc->program].current_rt == 0 && enc->state[enc->program].rt_text_timeout) {
|
||||
enc->state[enc->program].rt_text_timeout_state--;
|
||||
if(enc->state[enc->program].rt_text_timeout_state == 0) {
|
||||
enc->state[enc->program].rt_update = 1;
|
||||
memcpy(enc->state[enc->program].rt_text, enc->data[enc->program].default_rt, RT_LENGTH);
|
||||
}
|
||||
@@ -682,15 +650,15 @@ static void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
|
||||
|
||||
if(stream != 0) {
|
||||
group->a = 0;
|
||||
if(get_rds_custom_groups2(enc, group)) {
|
||||
goto group_coded_rds2;
|
||||
}
|
||||
if(enc->encoder_data.rds2_mode == 0) { // tunneling
|
||||
if(get_rds_custom_groups2(enc, group)) goto group_coded_rds2;
|
||||
|
||||
if(enc->encoder_data.rds2_mode == 0) {
|
||||
group->b = enc->state[enc->program].last_stream0_group[0];
|
||||
group->c = enc->state[enc->program].last_stream0_group[1];
|
||||
group->d = enc->state[enc->program].last_stream0_group[2];
|
||||
group->is_type_b = (group->a == 0 && IS_TYPE_B(group->b));
|
||||
goto group_coded_rds2;
|
||||
} else if(enc->encoder_data.rds2_mode == 1) { // independent tunneling
|
||||
} else if(enc->encoder_data.rds2_mode == 1) {
|
||||
while(good_group == 0) {
|
||||
grp_sqc_idx = enc->state[enc->program].grp_seq_idx[2];
|
||||
if(enc->data[enc->program].grp_sqc_rds2[grp_sqc_idx] == '\0') {
|
||||
@@ -718,9 +686,7 @@ static void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
|
||||
}
|
||||
}
|
||||
|
||||
if(get_rds_custom_groups(enc, group)) {
|
||||
goto group_coded;
|
||||
}
|
||||
if(get_rds_custom_groups(enc, group)) goto group_coded;
|
||||
|
||||
while(good_group == 0) {
|
||||
grp_sqc_idx = enc->state[enc->program].grp_seq_idx[0];
|
||||
@@ -750,15 +716,11 @@ group_coded_rds2:
|
||||
if(group->is_type_b) group->c = enc->data[enc->program].pi;
|
||||
group->b |= enc->data[enc->program].tp << 10;
|
||||
group->b |= enc->data[enc->program].pty << 5;
|
||||
} else if(stream == 0) {
|
||||
goto group_coded;
|
||||
}
|
||||
} else if(stream == 0) goto group_coded;
|
||||
return;
|
||||
|
||||
group_coded:
|
||||
if(stream != 0) {
|
||||
goto group_coded_rds2;
|
||||
}
|
||||
if(stream != 0) goto group_coded_rds2;
|
||||
group->b |= enc->data[enc->program].tp << 10;
|
||||
group->b |= enc->data[enc->program].pty << 5;
|
||||
if(group->is_type_b) group->c = enc->data[enc->program].pi;
|
||||
@@ -799,9 +761,7 @@ void reset_rds_state(RDSEncoder* enc, uint8_t program) {
|
||||
utc = gmtime(&now);
|
||||
tempCoder.state[program].last_minute = utc->tm_min;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
tempCoder.data[program].eon[i].ta = 0;
|
||||
}
|
||||
for(int i = 0; i < 4; i++) tempCoder.data[program].eon[i].ta = 0;
|
||||
|
||||
memcpy(&(enc->state[program]), &(tempCoder.state[program]), sizeof(RDSState));
|
||||
memcpy(&(enc->rtpState[program]), &(tempCoder.rtpState[program]), sizeof(RDSRTPlusState));
|
||||
@@ -851,29 +811,23 @@ void init_rds_encoder(RDSEncoder* enc) {
|
||||
void set_rds_rt1(RDSEncoder* enc, char *rt1) {
|
||||
uint8_t i = 0, len = 0;
|
||||
|
||||
enc->data[enc->program].rt_text_timeout = enc->data[enc->program].original_rt_text_timeout;
|
||||
enc->state[enc->program].rt_text_timeout_state = enc->data[enc->program].rt_text_timeout;
|
||||
|
||||
enc->state[enc->program].rt_update = 1;
|
||||
|
||||
memset(enc->data[enc->program].rt1, ' ', RT_LENGTH);
|
||||
while (*rt1 != 0 && len < RT_LENGTH) enc->data[enc->program].rt1[len++] = *rt1++;
|
||||
|
||||
while (len > 0 && enc->data[enc->program].rt1[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
while (len > 0 && enc->data[enc->program].rt1[len - 1] == ' ') len--;
|
||||
|
||||
if (len < RT_LENGTH) {
|
||||
enc->state[enc->program].rt_segments = 0;
|
||||
|
||||
enc->data[enc->program].rt1[len++] = '\r';
|
||||
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].rt_segments++;
|
||||
}
|
||||
} else {
|
||||
enc->state[enc->program].rt_segments = 16;
|
||||
}
|
||||
} else enc->state[enc->program].rt_segments = 16;
|
||||
}
|
||||
|
||||
void set_rds_rt2(RDSEncoder* enc, char *rt2) {
|
||||
@@ -884,22 +838,16 @@ void set_rds_rt2(RDSEncoder* enc, char *rt2) {
|
||||
memset(enc->data[enc->program].rt2, ' ', RT_LENGTH);
|
||||
while (*rt2 != 0 && len < RT_LENGTH) enc->data[enc->program].rt2[len++] = *rt2++;
|
||||
|
||||
while (len > 0 && enc->data[enc->program].rt2[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
while (len > 0 && enc->data[enc->program].rt2[len - 1] == ' ') len--;
|
||||
|
||||
if (len < RT_LENGTH) {
|
||||
enc->state[enc->program].rt2_segments = 0;
|
||||
|
||||
enc->data[enc->program].rt2[len++] = '\r';
|
||||
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].rt2_segments++;
|
||||
}
|
||||
} else {
|
||||
enc->state[enc->program].rt2_segments = 16;
|
||||
}
|
||||
} else enc->state[enc->program].rt2_segments = 16;
|
||||
}
|
||||
|
||||
void set_rds_ps(RDSEncoder* enc, char *ps) {
|
||||
@@ -936,14 +884,11 @@ void set_rds_lps(RDSEncoder* enc, char *lps) {
|
||||
|
||||
if (len < LPS_LENGTH) {
|
||||
enc->state[enc->program].lps_segments = 0;
|
||||
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].lps_segments++;
|
||||
}
|
||||
} else {
|
||||
enc->state[enc->program].lps_segments = 8;
|
||||
}
|
||||
} else enc->state[enc->program].lps_segments = 8;
|
||||
}
|
||||
|
||||
void set_rds_ert(RDSEncoder* enc, char *ert) {
|
||||
@@ -951,44 +896,38 @@ void set_rds_ert(RDSEncoder* enc, char *ert) {
|
||||
|
||||
enc->state[enc->program].ert_update = 1;
|
||||
|
||||
memset(enc->data[enc->program].ert, ' ', RT_LENGTH);
|
||||
while (*ert != 0 && len < RT_LENGTH) enc->data[enc->program].ert[len++] = *ert++;
|
||||
memset(enc->data[enc->program].ert, ' ', ERT_LENGTH);
|
||||
while (*ert != 0 && len < ERT_LENGTH) enc->data[enc->program].ert[len++] = *ert++;
|
||||
|
||||
while (len > 0 && enc->data[enc->program].ert[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
while (len > 0 && enc->data[enc->program].ert[len - 1] == ' ') len--;
|
||||
|
||||
if (len < RT_LENGTH) {
|
||||
if (len < ERT_LENGTH) {
|
||||
enc->state[enc->program].ert_segments = 0;
|
||||
|
||||
enc->data[enc->program].ert[len++] = '\r';
|
||||
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].ert_segments++;
|
||||
}
|
||||
} else {
|
||||
enc->state[enc->program].ert_segments = 32;
|
||||
}
|
||||
} else enc->state[enc->program].ert_segments = 32;
|
||||
}
|
||||
|
||||
void set_rds_rtplus_flags(RDSEncoder* enc, uint8_t flags) {
|
||||
enc->rtpData[enc->program][0].enabled = (flags==2);
|
||||
enc->rtpData[enc->program][0].running = flags & 1;
|
||||
enc->rtpData[enc->program][0].running = flags & 1;
|
||||
}
|
||||
|
||||
void set_rds_ertplus_flags(RDSEncoder* enc, uint8_t flags) {
|
||||
enc->rtpData[enc->program][1].enabled = (flags==2);
|
||||
enc->rtpData[enc->program][1].running = flags & 1;
|
||||
enc->rtpData[enc->program][1].running = flags & 1;
|
||||
}
|
||||
|
||||
void set_rds_rtplus_tags(RDSEncoder* enc, uint8_t *tags) {
|
||||
enc->rtpData[enc->program][0].type[0] = tags[0] & 0x3f;
|
||||
enc->rtpData[enc->program][0].start[0] = tags[1] & 0x3f;
|
||||
enc->rtpData[enc->program][0].len[0] = tags[2] & 0x3f;
|
||||
enc->rtpData[enc->program][0].type[1] = tags[3] & 0x3f;
|
||||
enc->rtpData[enc->program][0].start[1] = tags[4] & 0x3f;
|
||||
enc->rtpData[enc->program][0].len[1] = tags[5] & 0x1f;
|
||||
enc->rtpData[enc->program][0].type[0] = tags[0] & 0x3f;
|
||||
enc->rtpData[enc->program][0].start[0] = tags[1] & 0x3f;
|
||||
enc->rtpData[enc->program][0].len[0] = tags[2] & 0x3f;
|
||||
enc->rtpData[enc->program][0].type[1] = tags[3] & 0x3f;
|
||||
enc->rtpData[enc->program][0].start[1] = tags[4] & 0x3f;
|
||||
enc->rtpData[enc->program][0].len[1] = tags[5] & 0x1f;
|
||||
|
||||
enc->rtpState[enc->program][0].toggle ^= 1;
|
||||
enc->rtpData[enc->program][0].running = 1;
|
||||
@@ -996,12 +935,12 @@ void set_rds_rtplus_tags(RDSEncoder* enc, uint8_t *tags) {
|
||||
}
|
||||
|
||||
void set_rds_ertplus_tags(RDSEncoder* enc, uint8_t *tags) {
|
||||
enc->rtpData[enc->program][1].type[0] = tags[0] & 0x3f;
|
||||
enc->rtpData[enc->program][1].start[0] = tags[1] & 0x3f;
|
||||
enc->rtpData[enc->program][1].len[0] = tags[2] & 0x3f;
|
||||
enc->rtpData[enc->program][1].type[1] = tags[3] & 0x3f;
|
||||
enc->rtpData[enc->program][1].start[1] = tags[4] & 0x3f;
|
||||
enc->rtpData[enc->program][1].len[1] = tags[5] & 0x1f;
|
||||
enc->rtpData[enc->program][1].type[0] = tags[0] & 0x3f;
|
||||
enc->rtpData[enc->program][1].start[0] = tags[1] & 0x3f;
|
||||
enc->rtpData[enc->program][1].len[0] = tags[2] & 0x3f;
|
||||
enc->rtpData[enc->program][1].type[1] = tags[3] & 0x3f;
|
||||
enc->rtpData[enc->program][1].start[1] = tags[4] & 0x3f;
|
||||
enc->rtpData[enc->program][1].len[1] = tags[5] & 0x1f;
|
||||
|
||||
enc->rtpState[enc->program][1].toggle ^= 1;
|
||||
enc->rtpData[enc->program][1].running = 1;
|
||||
|
||||
10
src/rds.h
10
src/rds.h
@@ -77,9 +77,8 @@ typedef struct {
|
||||
uint8_t rt2_enabled : 1;
|
||||
uint8_t rt_type : 2;
|
||||
uint8_t rt_text_timeout;
|
||||
uint8_t original_rt_text_timeout;
|
||||
uint8_t rt_switching_period;
|
||||
uint8_t orignal_rt_switching_period;
|
||||
uint8_t current_rt : 1;
|
||||
char default_rt[RT_LENGTH];
|
||||
char rt2[RT_LENGTH];
|
||||
|
||||
@@ -125,7 +124,6 @@ typedef struct {
|
||||
uint8_t rt_ab : 1;
|
||||
uint8_t rt_segments : 5;
|
||||
uint8_t rt2_segments : 5;
|
||||
uint8_t current_rt : 1;
|
||||
|
||||
char ert_text[ERT_LENGTH];
|
||||
uint8_t ert_state : 6;
|
||||
@@ -145,6 +143,9 @@ typedef struct {
|
||||
uint16_t custom_group[GROUP_LENGTH];
|
||||
uint16_t custom_group2[GROUP_LENGTH + 1];
|
||||
|
||||
uint8_t rt_switching_period_state;
|
||||
uint8_t rt_text_timeout_state;
|
||||
|
||||
uint8_t rtp_oda : 1;
|
||||
uint8_t ertp_oda : 1;
|
||||
uint8_t ert_oda : 1;
|
||||
@@ -156,8 +157,9 @@ typedef struct {
|
||||
uint8_t fasttuning_state : 3;
|
||||
|
||||
uint8_t last_minute : 6;
|
||||
|
||||
uint8_t ta_timeout : 7;
|
||||
uint8_t original_ta_timeout : 7;
|
||||
uint8_t ta_timeout_state : 7;
|
||||
|
||||
uint8_t eon_index : 3;
|
||||
uint8_t eon_state : 4;
|
||||
|
||||
Reference in New Issue
Block a user