From f76e946c7f478b4ddddba340bd7a329953b2e103 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Fri, 28 Mar 2025 20:26:49 +0100 Subject: [PATCH] some memory optimizations and add data for ERT --- .vscode/.server-controller-port.log | 2 +- doc.md | 49 ++++++++++++++++++++++- src/ascii_cmd.c | 2 +- src/modulator.h | 2 - src/rds.c | 62 ++++++++++++++--------------- src/rds.h | 53 ++++++++++++------------ 6 files changed, 107 insertions(+), 63 deletions(-) diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index b593016..e6b7302 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1742919666758, + "time": 1743187937799, "version": "0.0.3" } \ No newline at end of file diff --git a/doc.md b/doc.md index 7f05319..56d4564 100644 --- a/doc.md +++ b/doc.md @@ -111,4 +111,51 @@ Sends a custom group to the next group available: `G=F100FFFFFFFF` or `G=0000200 Enables RT 1: `RT1EN=1` -TODO: Rest of commands +### RT2EN + +Enables RT 2: `RT1EN=2` + +### RTPER + +RT Switching period, in minutes: `RTPER=5` + +### LEVEL + +Sets the RDS output level: `LEVEL=255` + +### RESET + +Resets the internal state of the encoder: `RESET` + +### PTYNEN + +Enables PTYN: `PTYNEN=1` + +### GRPSEQ + +Sets the group sequence for stream0, available groups: + +- 0: 4 PSs +- 1: ECC +- 2: RT +- A: PTYN +- E: EON +- X: UDG1 +- Y: UDG2 +- R: RT+ +- 3: ODA +- F: LPS + +`GRPSEQ=002222` + +### RDSGEN + +Sets the rds generator level: + +- 0: No streams +- 1: Stream 0 only +- 2: Stream 0 and 1 + +`RDSGEN=1` + +TODO: Rest of the cmds \ No newline at end of file diff --git a/src/ascii_cmd.c b/src/ascii_cmd.c index b3363a2..2d20175 100644 --- a/src/ascii_cmd.c +++ b/src/ascii_cmd.c @@ -432,7 +432,6 @@ static const command_handler_t commands_eq6[] = { {"RT2EN", handle_rt2en, 5}, {"RTPER", handle_rtper, 5}, {"LEVEL", handle_level, 5}, - {"RESET", handle_reset, 5}, }; static const command_handler_t commands_eq7[] = { @@ -451,6 +450,7 @@ static const command_handler_t commands_eq8[] = { static const command_handler_t commands_exact[] = { {"INIT", handle_init, 4}, {"VER", handle_ver, 3}, + {"RESET", handle_reset, 5}, // TODO: handle help, status }; diff --git a/src/modulator.h b/src/modulator.h index bf626c0..246f1fe 100644 --- a/src/modulator.h +++ b/src/modulator.h @@ -3,8 +3,6 @@ #include "rds.h" #include "waveforms.h" -#define STREAMS 2 - typedef struct { float level; diff --git a/src/rds.c b/src/rds.c index 1ea0108..635b607 100644 --- a/src/rds.c +++ b/src/rds.c @@ -84,8 +84,8 @@ void saveToFile(RDSEncoder *emp, const char *option) { } else if (strcmp(option, "ALL") == 0) { memcpy(&(tempEncoder.data[emp->program]), &(emp->data[emp->program]), sizeof(RDSData)); memcpy(&(tempEncoder.rtpData[emp->program]), &(emp->rtpData[emp->program]), sizeof(RDSRTPlusData)); - memcpy(&(tempEncoder.odas[emp->program]), &(emp->odas[emp->program]), sizeof(RDSODA)*MAX_ODAS); - memcpy(&(tempEncoder.oda_state[emp->program]), &(emp->oda_state[emp->program]), sizeof(RDSODAState)); + memcpy(&(tempEncoder.odas[emp->program]), &(emp->odas[emp->program]), sizeof(RDSODA)*MAX_ODAS*STREAMS); + memcpy(&(tempEncoder.oda_state[emp->program]), &(emp->oda_state[emp->program]), sizeof(RDSODAState)*STREAMS); memcpy(&(tempEncoder.encoder_data), &(emp->encoder_data), sizeof(RDSEncoderData)); tempEncoder.program = emp->program; } else { @@ -98,8 +98,8 @@ void saveToFile(RDSEncoder *emp, const char *option) { rdsEncoderfile.file_ender = 95; memcpy(&(rdsEncoderfile.data[emp->program]), &(tempEncoder.data[emp->program]), sizeof(RDSData)); memcpy(&(rdsEncoderfile.rtpData[emp->program]), &(tempEncoder.rtpData[emp->program]), sizeof(RDSRTPlusData)); - memcpy(&(rdsEncoderfile.odas[emp->program]), &(tempEncoder.odas[emp->program]), sizeof(RDSODA)*MAX_ODAS); - memcpy(&(rdsEncoderfile.oda_state[emp->program]), &(tempEncoder.oda_state[emp->program]), sizeof(RDSODAState)); + memcpy(&(rdsEncoderfile.odas[emp->program]), &(tempEncoder.odas[emp->program]), sizeof(RDSODA)*MAX_ODAS*STREAMS); + memcpy(&(rdsEncoderfile.oda_state[emp->program]), &(tempEncoder.oda_state[emp->program]), sizeof(RDSODAState)*STREAMS); memcpy(&(rdsEncoderfile.encoder_data), &(tempEncoder.encoder_data), sizeof(RDSEncoderData)); rdsEncoderfile.program = tempEncoder.program; @@ -133,8 +133,8 @@ void loadFromFile(RDSEncoder *enc) { for (int i = 0; i < PROGRAMS; i++) { memcpy(&(enc->data[i]), &(rdsEncoderfile.data[i]), sizeof(RDSData)); memcpy(&(enc->rtpData[i]), &(rdsEncoderfile.rtpData[i]), sizeof(RDSRTPlusData)); - memcpy(&(enc->odas[i]), &(rdsEncoderfile.odas[i]), sizeof(RDSODA) * MAX_ODAS); - memcpy(&(enc->oda_state[i]), &(rdsEncoderfile.oda_state[i]), sizeof(RDSODAState)); + memcpy(&(enc->odas[i]), &(rdsEncoderfile.odas[i]), sizeof(RDSODA) * MAX_ODAS * STREAMS); + memcpy(&(enc->oda_state[i]), &(rdsEncoderfile.oda_state[i]), sizeof(RDSODAState) * STREAMS); } memcpy(&(enc->encoder_data), &(rdsEncoderfile.encoder_data), sizeof(RDSEncoderData)); enc->program = rdsEncoderfile.program; @@ -151,12 +151,12 @@ int rdssaved() { return 0; } -// static void register_oda(RDSEncoder* enc, uint8_t group, uint16_t aid, uint16_t scb) { +// static void register_oda(RDSEncoder* enc, uint8_t stream, uint8_t group, uint16_t aid, uint16_t data) { // if (enc->oda_state[enc->program].count >= MAX_ODAS) return; -// enc->odas[enc->program][enc->oda_state[enc->program].count].group = group; -// enc->odas[enc->program][enc->oda_state[enc->program].count].aid = aid; -// enc->odas[enc->program][enc->oda_state[enc->program].count].scb = scb; +// enc->odas[enc->program][stream][enc->oda_state[enc->program].count].group = group; +// enc->odas[enc->program][stream][enc->oda_state[enc->program].count].aid = aid; +// enc->odas[enc->program][stream][enc->oda_state[enc->program].count].data = data; // enc->oda_state[enc->program].count++; // } @@ -211,7 +211,7 @@ static void get_rds_ps_group(RDSEncoder* enc, uint16_t *blocks) { } enc->state[enc->program].ps_csegment++; - if (enc->state[enc->program].ps_csegment >= 4) enc->state[enc->program].ps_csegment = 0; + if (enc->state[enc->program].ps_csegment == 3) enc->state[enc->program].ps_csegment = 0; } static void get_rds_rt_group(RDSEncoder* enc, uint16_t *blocks) { @@ -252,23 +252,23 @@ static void get_rds_rt_group(RDSEncoder* enc, uint16_t *blocks) { blocks[3] = enc->state[enc->program].rt_text[enc->state[enc->program].rt_state * 4 + 2] << 8; blocks[3] |= enc->state[enc->program].rt_text[enc->state[enc->program].rt_state * 4 + 3]; - enc->state[enc->program].rt_state++; uint8_t segments = (enc->state[enc->program].current_rt == 1) ? enc->state[enc->program].rt2_segments : enc->state[enc->program].rt_segments; - if (enc->state[enc->program].rt_state >= segments) enc->state[enc->program].rt_state = 0; + if (enc->state[enc->program].rt_state == segments) enc->state[enc->program].rt_state = 0; + enc->state[enc->program].rt_state++; } -static void get_rds_oda_group(RDSEncoder* enc, uint16_t *blocks) { - RDSODA this_oda = enc->odas[enc->program][enc->oda_state[enc->program].current]; +static void get_rds_oda_group(RDSEncoder* enc, uint16_t *blocks, uint8_t stream) { + RDSODA this_oda = enc->odas[enc->program][stream][enc->oda_state[enc->program][stream].current]; blocks[1] |= 3 << 12; blocks[1] |= GET_GROUP_TYPE(this_oda.group) << 1; blocks[1] |= GET_GROUP_VER(this_oda.group); - blocks[2] = this_oda.scb; + blocks[2] = this_oda.data; blocks[3] = this_oda.aid; - enc->oda_state[enc->program].current++; - if (enc->oda_state[enc->program].current >= enc->oda_state[enc->program].count) enc->oda_state[enc->program].current = 0; + if (enc->oda_state[enc->program][stream].current == enc->oda_state[enc->program][stream].count) enc->oda_state[enc->program][stream].current = 0; + enc->oda_state[enc->program][stream].current++; } static void get_rds_rtp_oda_group(RDSEncoder* enc, uint16_t *blocks) { @@ -482,7 +482,7 @@ static void get_rds_sequence_group(RDSEncoder* enc, uint16_t *blocks, char* grp, goto group_coded; // TODO: add uecp case '3': - get_rds_oda_group(enc, blocks); + get_rds_oda_group(enc, blocks, stream); goto group_coded; case 'F': get_rds_lps_group(enc, blocks); @@ -492,7 +492,7 @@ group_coded: return; } -static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) { +static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp, uint8_t stream) { uint8_t good_group = 0; if(*grp == '0') good_group = 1; if(*grp == '1' && enc->data[enc->program].ecc != 0) good_group = 1; @@ -509,7 +509,7 @@ static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) { if(*grp == 'X' && enc->data[enc->program].udg1_len != 0) good_group = 1; if(*grp == 'Y' && enc->data[enc->program].udg2_len != 0) good_group = 1; if(*grp == 'R' && enc->rtpData[enc->program].enabled) good_group = 1; - if(*grp == '3' && enc->oda_state[enc->program].count != 0) good_group = 1; + if(*grp == '3' && enc->oda_state[enc->program][stream].count != 0) good_group = 1; if(*grp == 'F' && enc->data[enc->program].lps[0] != '\0') good_group = 1; return good_group; } @@ -586,7 +586,7 @@ static void get_rds_group(RDSEncoder* enc, uint16_t *blocks, uint8_t stream) { } grp = enc->data[enc->program].grp_sqc_rds2[grp_sqc_idx]; - good_group = check_rds_good_group(enc, &grp); + good_group = check_rds_good_group(enc, &grp, stream); if(!good_group) cant_find_group++; else cant_find_group = 0; @@ -617,7 +617,7 @@ static void get_rds_group(RDSEncoder* enc, uint16_t *blocks, uint8_t stream) { } grp = enc->data[enc->program].grp_sqc[grp_sqc_idx]; - good_group = check_rds_good_group(enc, &grp); + good_group = check_rds_good_group(enc, &grp, stream); if(!good_group) cant_find_group++; else cant_find_group = 0; @@ -702,8 +702,8 @@ void reset_rds_state(RDSEncoder* enc, uint8_t program) { void set_rds_defaults(RDSEncoder* enc, uint8_t program) { memset(&(enc->data[program]), 0, sizeof(RDSData)); - memset(&(enc->oda_state[program]), 0, sizeof(RDSODAState)); - memset(&(enc->odas[program]), 0, sizeof(RDSODA)*MAX_ODAS); + memset(&(enc->oda_state[program]), 0, sizeof(RDSODAState)*STREAMS); + memset(&(enc->odas[program]), 0, sizeof(RDSODA)*MAX_ODAS*STREAMS); memset(&(enc->rtpData[program]), 0, sizeof(RDSRTPlusData)); memset(&(enc->encoder_data), 0, sizeof(RDSEncoderData)); @@ -764,10 +764,10 @@ void set_rds_rt1(RDSEncoder* enc, char *rt1) { while (i < len) { i += 4; - enc->state[enc->program].rt_segments++; + if (i != 4) enc->state[enc->program].rt_segments++; } } else { - enc->state[enc->program].rt_segments = 16; + enc->state[enc->program].rt_segments = 15; } } @@ -790,10 +790,10 @@ void set_rds_rt2(RDSEncoder* enc, char *rt2) { while (i < len) { i += 4; - enc->state[enc->program].rt2_segments++; + if (i != 4) enc->state[enc->program].rt2_segments++; } } else { - enc->state[enc->program].rt2_segments = 16; + enc->state[enc->program].rt2_segments = 15; } } @@ -834,10 +834,10 @@ void set_rds_lps(RDSEncoder* enc, char *lps) { while (i < len) { i += 4; - enc->state[enc->program].lps_segments++; + if (i != 4) enc->state[enc->program].lps_segments++; } } else { - enc->state[enc->program].lps_segments = 8; + enc->state[enc->program].lps_segments = 7; } } diff --git a/src/rds.h b/src/rds.h index fb9dfaa..7e2356b 100644 --- a/src/rds.h +++ b/src/rds.h @@ -15,7 +15,10 @@ #define FILTER_SIZE 64 #define SAMPLE_BUFFER_SIZE (SAMPLES_PER_BIT + FILTER_SIZE) +#define STREAMS 2 + #define RT_LENGTH 64 +#define ERT_LENGTH 128 #define PS_LENGTH 8 #define PTYN_LENGTH 8 #define LPS_LENGTH 32 @@ -48,19 +51,6 @@ typedef struct { char ps[8]; RDSAFs af; } RDSEON; -typedef struct -{ - uint8_t days : 7; // let's say that here it will be stored by bits, so 0b1000000 is monday and so on - uint8_t pty: 5; - uint16_t execution_hours[12]; - uint16_t execution_minutes[12]; - char command[35]; -} RDSSchedulerItem; -typedef struct -{ - uint8_t enabled : 1; - RDSSchedulerItem items[49]; -} RDSScheduler; typedef struct { uint16_t pi; @@ -83,11 +73,18 @@ 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; char default_rt[RT_LENGTH]; char rt2[RT_LENGTH]; + uint8_t ert_enabled : 1; + uint8_t ert_switching_period; + uint8_t orignal_ert_switching_period; + char ert[ERT_LENGTH]; + char ert2[ERT_LENGTH]; + uint8_t ptyn_enabled : 1; char ptyn[PTYN_LENGTH]; @@ -114,26 +111,29 @@ typedef struct { uint8_t tps_update : 1; char ps_text[PS_LENGTH]; char tps_text[PS_LENGTH]; - uint8_t ps_csegment : 4; + uint8_t ps_csegment : 2; char rt_text[RT_LENGTH]; - uint8_t rt_state : 5; + uint8_t rt_state : 4; uint8_t rt_update : 1; uint8_t rt2_update : 1; uint8_t rt_ab : 1; - uint8_t rt_segments : 5; - uint8_t rt2_segments : 5; + uint8_t rt_segments : 4; + uint8_t rt2_segments : 4; uint8_t current_rt : 1; + char ert_text[ERT_LENGTH]; + // uint8_t ert_state + char ptyn_text[PTYN_LENGTH]; uint8_t ptyn_state : 1; uint8_t ptyn_update : 1; uint8_t ptyn_ab : 1; char lps_text[LPS_LENGTH]; - uint8_t lps_state : 5; + uint8_t lps_state : 3; uint8_t lps_update : 1; - uint8_t lps_segments : 5; + uint8_t lps_segments : 3; uint16_t custom_group[GROUP_LENGTH]; uint16_t custom_group2[GROUP_LENGTH + 1]; @@ -155,11 +155,11 @@ typedef struct { typedef struct { uint8_t group; uint16_t aid; - uint16_t scb; + uint16_t data; } RDSODA; typedef struct { - uint8_t current : 4; - uint8_t count : 4; + uint8_t current : 3; + uint8_t count : 3; } RDSODAState; typedef struct { @@ -189,7 +189,6 @@ typedef struct { RDSEncoderASCIIData ascii_data; RDSEncoderUECPData uecp_data; uint16_t special_features; - RDSScheduler schedule; uint8_t rds2_mode : 1; // uint8_t rds2_buffer[16384]; } RDSEncoderData; @@ -197,8 +196,8 @@ typedef struct { RDSEncoderData encoder_data; RDSData data[PROGRAMS]; RDSState state[PROGRAMS]; - RDSODA odas[PROGRAMS][MAX_ODAS]; - RDSODAState oda_state[PROGRAMS]; + RDSODA odas[PROGRAMS][STREAMS][MAX_ODAS]; + RDSODAState oda_state[PROGRAMS][STREAMS]; RDSRTPlusData rtpData[PROGRAMS]; RDSRTPlusState rtpState[PROGRAMS]; uint8_t program : 3; @@ -207,9 +206,9 @@ typedef struct { uint8_t file_starter; // Always is 225 first polish radio programme am frequency RDSData data[PROGRAMS]; RDSRTPlusData rtpData[PROGRAMS]; - RDSODA odas[PROGRAMS][MAX_ODAS]; + RDSODA odas[PROGRAMS][STREAMS][MAX_ODAS]; uint8_t file_middle; // Always is 160, average of both - RDSODAState oda_state[PROGRAMS]; + RDSODAState oda_state[PROGRAMS][STREAMS]; RDSEncoderData encoder_data; uint8_t program : 3; uint8_t file_ender; // Always is 95 my freq