This commit is contained in:
KubaPro010 2025-08-06 13:14:24 +02:00
parent 5df55ed946
commit cf8dfdee1c
6 changed files with 46 additions and 34 deletions

View File

@ -152,6 +152,11 @@ ResultAndArg poll_control_pipe(int log) {
printf("Wrong PTY identifier! The PTY range is 0 - 31.\n"); printf("Wrong PTY identifier! The PTY range is 0 - 31.\n");
} }
resarg.res = CONTROL_PIPE_PTY_SET; resarg.res = CONTROL_PIPE_PTY_SET;
} else if(fifo[0] == 'E' && fifo[1] == 'C' && fifo[2] == 'C') {
arg[3] = 0;
set_rds_ecc((uint16_t) strtol(arg, NULL, 16));
if(log==1) printf("ECC set to: \"%s\"\n", arg);
resarg.res = CONTROL_PIPE_GENERIC_SET;
} else if(fifo[0] == 'P' && fifo[1] == 'W' && fifo[2] == 'R') { } else if(fifo[0] == 'P' && fifo[1] == 'W' && fifo[2] == 'R') {
int power_level = atoi(arg); int power_level = atoi(arg);
resarg.arg_int = power_level; resarg.arg_int = power_level;

View File

@ -48,10 +48,7 @@ float carrier_38[] = {0.0, 0.8660254037844386, 0.8660254037844388, 1.22464679914
float carrier_19[] = {0.0, 0.5, 0.8660254037844386, 1.0, 0.8660254037844388, 0.5, 1.2246467991473532e-16, -0.5, -0.8660254037844384, -1.0, -0.8660254037844386, -0.5}; float carrier_19[] = {0.0, 0.5, 0.8660254037844386, 1.0, 0.8660254037844388, 0.5, 1.2246467991473532e-16, -0.5, -0.8660254037844384, -1.0, -0.8660254037844386, -0.5};
float carrier_3125[] = {0.0, 0.7586133425663026, 0.9885355334735083, 0.5295297022607088, -0.29851481100169425, -0.918519035014914, -0.898390981891979, -0.2521582503964708}; // sine wave
int phase_38 = 0; int phase_38 = 0;
int phase_3125 = 0;
int phase_19 = 0; int phase_19 = 0;
float downsample_factor; float downsample_factor;
@ -349,21 +346,14 @@ int fm_mpx_get_samples(float *mpx_buffer, fm_mpx_data *data) {
// Generate the stereo mpx // Generate the stereo mpx
if(channels == 2 && !data->dstereo) { if(channels == 2 && !data->dstereo) {
if(1) { // 4.5 and 0.9 are the volumes, thats because we dont have 75000 khz of deviation, instead we have 7500 khz, so that needs to be louder by 10 times than normal
// 4.5 and 0.9 are the volumes, thats because we dont have 75000 khz of deviation, instead we have 7500 khz, so that needs to be louder by 10 times than normal mpx_buffer[i] += 4.5*(out_left+out_right) + // Stereo sum signal
mpx_buffer[i] += 4.5*(out_left+out_right) + // Stereo sum signal 4.5 * carrier_38[phase_38] * (out_left-out_right) + // Stereo difference signal
4.5 * carrier_38[phase_38] * (out_left-out_right) + // Stereo difference signal 0.9*carrier_19[phase_19]; // Stereo pilot tone
0.9*carrier_19[phase_19]; // Stereo pilot tone phase_19++;
phase_19++; phase_38++;
phase_38++; if(phase_19 >= 12) phase_19 = 0;
if(phase_19 >= 12) phase_19 = 0; if(phase_38 >= 6) phase_38 = 0;
if(phase_38 >= 6) phase_38 = 0;
} else { // polar stereo (https://forums.stereotool.com/viewtopic.php?t=6233, https://personal.utdallas.edu/~dlm/3350%20comm%20sys/ITU%20std%20on%20FM%20--%20R-REC-BS.450-3-200111-I!!PDF-E.pdf)
mpx_buffer[i] += 4.5*(out_left+out_right) + // Stereo sum signal (L+R)
4.5 * carrier_3125[phase_3125] * (out_left-out_right); // Stereo difference signal
phase_3125++;
if(phase_3125 >= 8) phase_3125 = 0;
}
} else if(channels == 1 || data->dstereo) } else if(channels == 1 || data->dstereo)
{ {
if(data->generate_multiplex) { if(data->generate_multiplex) {

View File

@ -43,30 +43,31 @@ typedef struct tx_data {
uint32_t carrier_freq; uint32_t carrier_freq;
char *audio_file; char *audio_file;
uint16_t pi; uint16_t pi;
uint16_t ecc;
char *ps; char *ps;
char *rt; char *rt;
char *control_pipe; char *control_pipe;
int pty; uint8_t pty;
int af_array[100]; int af_array[100];
int raw; uint8_t raw;
int drds; uint8_t drds;
double preemp; float preemp;
int power; int power;
int rawSampleRate; int rawSampleRate;
int rawChannels; int rawChannels;
int deviation; int deviation;
int ta; uint8_t ta;
int tp; uint8_t tp;
float cutoff_freq; float cutoff_freq;
float audio_gain; float audio_gain;
float compressor_decay; float compressor_decay;
float compressor_attack; float compressor_attack;
float compressor_max_gain_recip; float compressor_max_gain_recip;
int enablecompressor; uint8_t enablecompressor;
int rds_ct_enabled; uint8_t rds_ct_enabled;
float rds_volume; float rds_volume;
int disablestereo; uint8_t disablestereo;
int log; uint8_t log;
float limiter_threshold; float limiter_threshold;
} tx_data; } tx_data;
@ -111,6 +112,7 @@ int tx(tx_data *data) {
// Initialize the RDS modulator // Initialize the RDS modulator
char myps[9] = {0}; char myps[9] = {0};
set_rds_pi(data->pi); set_rds_pi(data->pi);
set_rds_ecc(data->ecc);
set_rds_ps(data->ps); set_rds_ps(data->ps);
set_rds_rt(data->rt); set_rds_rt(data->rt);
set_rds_pty(data->pty); set_rds_pty(data->pty);
@ -129,7 +131,7 @@ int tx(tx_data *data) {
if(drds == 1) { if(drds == 1) {
printf("RDS Disabled (you can enable with control fifo with the RDS command)\n"); printf("RDS Disabled (you can enable with control fifo with the RDS command)\n");
} else { } else {
printf("PI: %04X, PS: \"%s\".\n", data->pi, data->ps); printf("PI: %04X, ECC: %02X, PS: \"%s\".\n", data->pi, data->ecc, data->ps);
printf("RT: \"%s\"\n", data->rt); printf("RT: \"%s\"\n", data->rt);
if(data->af_array[0]) { if(data->af_array[0]) {
@ -226,6 +228,7 @@ int main(int argc, char **argv) {
.carrier_freq = 100000000, .carrier_freq = 100000000,
.audio_file = NULL, .audio_file = NULL,
.pi = 0x00ff, .pi = 0x00ff,
.ecc = 0x0,
.ps = "Pi-FmSa", .ps = "Pi-FmSa",
.rt = "Broadcasting on a Raspberry Pi: Simply Advanced", .rt = "Broadcasting on a Raspberry Pi: Simply Advanced",
.control_pipe = NULL, .control_pipe = NULL,
@ -275,6 +278,9 @@ int main(int argc, char **argv) {
} else if(strcmp("-pi", arg)==0 && param != NULL) { } else if(strcmp("-pi", arg)==0 && param != NULL) {
i++; i++;
data.pi = atoi(param); data.pi = atoi(param);
} else if(strcmp("-ecc", arg)==0 && param != NULL) {
i++;
data.ecc = atoi(param);
} else if(strcmp("-ps", arg)==0 && param != NULL) { } else if(strcmp("-ps", arg)==0 && param != NULL) {
i++; i++;
data.ps = param; data.ps = param;
@ -393,7 +399,7 @@ int main(int argc, char **argv) {
} }
else { else {
fatal("Unrecognised argument: %s.\n" fatal("Unrecognised argument: %s.\n"
"Syntax: pi_fm_rds [-freq freq] [-audio file] [-pi pi_code]\n" "Syntax: pi_fm_rds [-freq freq] [-audio file] [-pi pi_code] [-ecc ecc_code]\n"
" [-ps ps_text] [-rt rt_text] [-ctl control_pipe] [-pty program_type] [-raw play raw audio from stdin] [-disablerds] [-af alt freq] [-preemphasis us] [-rawchannels when using the raw option you can change this] [-rawsamplerate same business] [-deviation the deviation, default is 75000] [-tp] [-ta]\n", arg); " [-ps ps_text] [-rt rt_text] [-ctl control_pipe] [-pty program_type] [-raw play raw audio from stdin] [-disablerds] [-af alt freq] [-preemphasis us] [-rawchannels when using the raw option you can change this] [-rawsamplerate same business] [-deviation the deviation, default is 75000] [-tp] [-ta]\n", arg);
} }
} }

View File

@ -30,6 +30,7 @@ float carrier_57[] = {0.0, 1.0, 1.2246467991473532e-16, -1.0}; // sine wave at 5
struct { struct {
uint16_t pi; uint16_t pi;
uint16_t ecc;
int ta; int ta;
int pty; int pty;
int tp; int tp;
@ -145,16 +146,21 @@ void get_rds_group(int *buffer, int stereo, int ct_clock_enabled) { //ptyn?
blocks[3] = rds_params.ps[ps_state*2] << 8 | rds_params.ps[ps_state*2+1]; blocks[3] = rds_params.ps[ps_state*2] << 8 | rds_params.ps[ps_state*2+1];
ps_state++; ps_state++;
if(ps_state >= 4) ps_state = 0; if(ps_state >= 4) ps_state = 0;
} else { // Type 2A groups } else if(state < 8) { // Type 2A groups
blocks[1] = 0x2000 | rds_params.tp << 10 | rds_params.pty << 5 | rds_params.ab << 4 | rt_state; blocks[1] = 0x2000 | rds_params.tp << 10 | rds_params.pty << 5 | rds_params.ab << 4 | rt_state;
blocks[2] = rds_params.rt[rt_state*4+0] << 8 | rds_params.rt[rt_state*4+1]; blocks[2] = rds_params.rt[rt_state*4+0] << 8 | rds_params.rt[rt_state*4+1];
blocks[3] = rds_params.rt[rt_state*4+2] << 8 | rds_params.rt[rt_state*4+3]; blocks[3] = rds_params.rt[rt_state*4+2] << 8 | rds_params.rt[rt_state*4+3];
rt_state++; rt_state++;
if(rt_state >= 16) rt_state = 0; if(rt_state >= 16) rt_state = 0;
} else {
blocks[1] = 0x1000 | rds_params.tp << 10 | rds_params.pty << 5;
blocks[2] = rds_params.ecc; // Things like LIC would require the first 1-3 bits set, but ecc has just 0s there
// block 3 unused
} }
state++; state++;
if(state >= 8) state = 0; if(state >= 8 && rds_params.ecc == 0) state = 0;
if(state >= 9 && rds_params.ecc != 0) state = 0;
} }
// Calculate the checkword for each block and emit the bits // Calculate the checkword for each block and emit the bits
@ -287,3 +293,7 @@ void set_rds_ms(int ms) {
void set_rds_ab(int ab) { void set_rds_ab(int ab) {
rds_params.ab = ab; rds_params.ab = ab;
} }
void set_rds_ecc(uint16_t ecc) {
rds_params.ecc = ecc;
}

View File

@ -49,6 +49,6 @@ extern void set_rds_af(int *af_array);
extern void set_rds_tp(int tp); extern void set_rds_tp(int tp);
extern void set_rds_ms(int ms); extern void set_rds_ms(int ms);
extern void set_rds_ab(int ab); extern void set_rds_ab(int ab);
extern void set_rds_ecc(uint16_t ecc);
#endif /* RDS_H */ #endif /* RDS_H */

View File

@ -10,9 +10,10 @@ extern "C"
int main() { int main() {
set_rds_pi(0xff); set_rds_pi(0xff);
set_rds_ps("TEST"); set_rds_ps("TEST");
set_rds_ecc(0xFF);
int af_array[] = {3, 2, 1, 0}; int af_array[] = {3, 2, 1, 0};
set_rds_af(af_array); set_rds_af(af_array);
for(int i = 0; i < 32; i++) { for(int i = 0; i < 10; i++) {
int buffer[BITS_PER_GROUP]; int buffer[BITS_PER_GROUP];
get_rds_group(buffer, 0, 0); get_rds_group(buffer, 0, 0);
for(int j = 0; j < BITS_PER_GROUP; j++) { for(int j = 0; j < BITS_PER_GROUP; j++) {