diff --git a/.vscode/.server-controller-port.log b/.vscode/.server-controller-port.log index 2d950a0..9ecfc10 100644 --- a/.vscode/.server-controller-port.log +++ b/.vscode/.server-controller-port.log @@ -1,5 +1,5 @@ { "port": 13452, - "time": 1742112482618, + "time": 1742119572632, "version": "0.0.3" } \ No newline at end of file diff --git a/src/ascii_cmd.c b/src/ascii_cmd.c index e56d03a..67ef72d 100644 --- a/src/ascii_cmd.c +++ b/src/ascii_cmd.c @@ -18,9 +18,6 @@ static void handle_ptyn(unsigned char *arg, RDSModulator* mod) { } static void handle_afch(unsigned char *arg, RDSModulator* mod) { - if (arg[0] == 'A' || arg[0] == 'B') { - return; - } if(arg[0] == '\0') { memset(&(mod->enc->data[mod->enc->program].af), 0, sizeof(mod->enc->data[mod->enc->program].af)); return; diff --git a/src/rds.c b/src/rds.c index 3932855..ddaca20 100644 --- a/src/rds.c +++ b/src/rds.c @@ -72,6 +72,8 @@ void saveToFile(RDSEncoder *emp, const char *option) { memcpy(tempEncoder.rtpData[emp->program].len, emp->rtpData[emp->program].len, sizeof(emp->rtpData[emp->program].len)); memcpy(tempEncoder.rtpData[emp->program].start, emp->rtpData[emp->program].start, sizeof(emp->rtpData[emp->program].start)); memcpy(tempEncoder.rtpData[emp->program].type, emp->rtpData[emp->program].type, sizeof(emp->rtpData[emp->program].type)); + 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)); tempEncoder.rtpData[emp->program].toggle = emp->rtpData[emp->program].toggle; } else if (strcmp(option, "UDG1") == 0) { memcpy(tempEncoder.data[emp->program].udg1, emp->data[emp->program].udg1, sizeof(emp->data[emp->program].udg1)); @@ -82,6 +84,8 @@ void saveToFile(RDSEncoder *emp, const char *option) { } else if(strcmp(option, "RTPRUN") == 0) { tempEncoder.rtpData[emp->program].running = emp->rtpData[emp->program].running; tempEncoder.rtpData[emp->program].enabled = emp->rtpData[emp->program].enabled; + 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)); } else if(strcmp(option, "PTYNEN") == 0) { tempEncoder.data[emp->program].ptyn_enabled = emp->data[emp->program].ptyn_enabled; } else if(strcmp(option, "ECCEN") == 0) { @@ -92,15 +96,18 @@ void saveToFile(RDSEncoder *emp, const char *option) { tempEncoder.data[emp->program].pin[0] = emp->data[emp->program].pin[0]; } else if(strcmp(option, "PROGRAM") == 0) { tempEncoder.program = emp->program; + } else if(strcmp(option, "EON") == 0) { + memcpy(&(tempEncoder.data[emp->program].eon), &(emp->data[emp->program].eon), sizeof(RDSEONs)*4); } 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)); - tempEncoder.program = emp->program; + 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.encoder_data[emp->program]), &(emp->encoder_data[emp->program]), sizeof(RDSODAState)); + tempEncoder.program = emp->program; } memcpy(&(tempEncoder.state[emp->program]), &(emp->state[emp->program]), sizeof(RDSState)); - 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); file = fopen(encoderPath, "wb"); if (file == NULL) { @@ -479,12 +486,17 @@ void set_rds_defaults(RDSEncoder* enc, uint8_t program) { memset(&(enc->oda_state[program]), 0, sizeof(RDSODAState)); memset(&(enc->odas[program]), 0, sizeof(RDSODA)*MAX_ODAS); memset(&(enc->rtpData[program]), 0, sizeof(RDSRTPlusData)); + memset(&(enc->encoder_data[program]), 0, sizeof(RDSEncoderData)); + + enc->encoder_data[program].uecp_encoder_addr[0] = 0; + enc->encoder_data[program].uecp_encoder_addr[1] = 0; 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].tp = 1; enc->data[program].pi = 0xFFFF; strcpy((char *)enc->data[program].ps, "* RDS * "); enc->data[program].rt1_enabled = 1; diff --git a/src/rds.h b/src/rds.h index 90dec8a..534469d 100644 --- a/src/rds.h +++ b/src/rds.h @@ -36,7 +36,7 @@ #pragma pack(1) typedef struct { - uint8_t num_entries; + uint8_t num_entries : 6; uint8_t num_afs : 5; uint8_t afs[MAX_AFS]; } RDSAFs; @@ -50,6 +50,33 @@ typedef struct { RDSAFs af; } RDSEONs; typedef struct { + unsigned char text[255]; + uint8_t destination : 4; +} RDSMessage; +typedef struct { + RDSMessage messages[100]; + uint8_t dps2msg : 7; + uint8_t dps2msg_auto : 1; + uint8_t rt2msg : 7; + uint8_t rt2msg_auto : 1; +} RDSMessages; +typedef struct +{ + unsigned char command[35]; + 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]; +} RDSSchedulerItem; +typedef struct +{ + RDSSchedulerItem items[49]; + uint8_t enabled : 1; +} RDSScheduler; +typedef struct { + uint8_t dsn; + uint8_t psn; + uint16_t pi; uint8_t ecclic_enabled : 1; @@ -65,9 +92,30 @@ typedef struct { unsigned char ps[PS_LENGTH]; unsigned char tps[PS_LENGTH]; + uint8_t eqtext1 : 1; + uint8_t dps1_enabled : 1; + uint8_t dps2_enabled : 1; + unsigned char dps1[255]; + unsigned char dps2[255]; + uint8_t dps1_mode : 2; + uint8_t dps2_mode : 2; + uint8_t dps1_numberofrepeats : 7; + uint8_t dps1_numberofrepeats_clear : 1; + uint8_t dps2_numberofrepeats; + uint8_t dps_label_period; + uint8_t dps_restart : 1; + uint8_t dps_speed : 1; + uint8_t static_ps_period; + uint8_t shortrt : 1; uint8_t rt1_enabled : 1; + uint8_t rt2_enabled : 1; + uint8_t rt_type : 2; + uint8_t rt_text_timeout; + uint8_t rt_switching_period; + unsigned char default_rt[RT_LENGTH]; unsigned char rt1[RT_LENGTH]; + unsigned char rt2[RT_LENGTH]; uint8_t ptyn_enabled : 1; unsigned char ptyn[PTYN_LENGTH]; @@ -89,6 +137,8 @@ typedef struct { uint16_t udg2[8][3]; RDSEONs eon[4]; + RDSMessages messages; + RDSScheduler schedule; } RDSData; typedef struct { uint8_t ecc_or_lic : 1; @@ -99,6 +149,9 @@ typedef struct { unsigned char tps_text[PS_LENGTH]; uint8_t ps_csegment : 4; + unsigned char dps1_text[255]; + unsigned char dps1_nexttext[127]; + unsigned char rt_text[RT_LENGTH]; uint8_t rt_state : 5; uint8_t rt_update : 1; @@ -143,6 +196,15 @@ typedef struct { } RDSRTPlusData; typedef struct { + uint8_t uecp_enabled : 1; + uint8_t encoder_addr[2]; + uint16_t site_addr[2]; + uint8_t selected_encoder_addr; + uint16_t selected_site_addr : 10 +} RDSEncoderData; +typedef struct +{ + RDSEncoderData encoder_data[PROGRAMS]; RDSData data[PROGRAMS]; RDSState state[PROGRAMS]; RDSODA odas[PROGRAMS][MAX_ODAS]; diff --git a/supported_cmds.txt b/supported_cmds.txt index 26aece3..d46290e 100644 --- a/supported_cmds.txt +++ b/supported_cmds.txt @@ -58,7 +58,7 @@ RDSGEN - STATUS, ?? (TIME) - VER -- ADR +- ADR *ADR - CC - DSN* ECCEN @@ -75,7 +75,94 @@ RTP RTPRUN SHORTRT - SEL -- SITE +- SITE *SITE UDG1 UDG2 - UECP + +Magic RDS 4 Pages for PIRA32: +- Device Setup: + - Communication: + - Port Speed (will not be added) + - UECP (TODO:): + - General Enable + - Address List + - Site List + - Analog Control: + - RDS Output + - Subcarrier: + - Refrence (will not be added) + - Phase (will not be added) + - Date and Time (will not be added) + - Special: + - Reset (will not be added) + - Store ALL + - Initialize + - No Header off (TODO: find out what this means) + - Text messages: TODO: + - Internal Scheduler TODO: +- RDS Content: + - Program: + - PS + - PI + - TP + - MS + - PTY + - PTYN + - Radiotext: + - RT1: + - Text + - Default RT (save to memory) + - Default RT Timeout (TODO: DTTMOUT) + - RT2 (TODO:): + - Text + - Source (TODO: RT2MSG) + - Setup: + - RT1 Enabled + - RT2 Enabled (TODO:) + - Radiotext Type Bit (TODO: RTTYPE) + - Dynamic PS (TODO:): + - DPS1 Text + - DPS1 Setup: + - DPS1 Enabled (Default: 0) + - DPS1 Mode (Default: 1) + - DPS1 Number of repeats (Default: 0, options: CLEAR) + - DPS2: + - DPS2 Text + - DPS2 Source (Default: 0, manual) + - DPS Setup: + - DPS2 Enabled (Default: 0) + - DPS2 Mode (Default: 2) + - DPS2 Number of repeats (Default: 0) + - Common settings: + - Static PS period (Default: 16) + - DPS String Period (LABPER, Default: 0) + - Scrolling Speed (modes 0-3 Default: low) + - Restart DPS on change (options: Only if it's running, Always | first is Default) + - Alternative Frequency: + - AF Method (TODO: AF=A, AF=B) + ; A: + (list of freqs from 87,6 to 107,9) + Sets mode via `AF=A` and sets the af via AFCH + ; B: + entry for tuned freq + same programme AF + regional variant AF + Sets the AF to A then sets AFCH to tf and pairs, sends these? `*AF=1` `AFCH=` `*AF=2` `AF=B` (no clue) + - EON (TODO:): + - Other Network X: + - Enabled + - PI + - PS + - TP + - PTY + - AF Freqs (Mode A only) + - System: + - Group sequence + - Misc: + - DI + - ECC, LIC + - CT + - RT1=DPS1 (TODO: EQTEXT1) + - TPS + - TA Timeout (will not be added), TA external control (will not be added) \ No newline at end of file