diff --git a/src/modulator.c b/src/modulator.c index a76977f..d6e76e1 100644 --- a/src/modulator.c +++ b/src/modulator.c @@ -78,13 +78,13 @@ void init_rds_modulator(RDSModulator* rdsMod, RDSEncoder* enc) { } } -float get_rds_sample(RDSModulator* rdsMod) { +float get_rds_sample(RDSModulator* rdsMod, bool rds2) { uint16_t idx; float *cur_waveform; float sample; if (rdsMod->sample_count == SAMPLES_PER_BIT) { if (rdsMod->bit_pos == BITS_PER_GROUP) { - get_rds_bits(rdsMod->enc, rdsMod->bit_buffer); + get_rds_bits(rdsMod->enc, rdsMod->bit_buffer, rds2); rdsMod->bit_pos = 0; } diff --git a/src/modulator.h b/src/modulator.h index 7d129ee..11edd59 100644 --- a/src/modulator.h +++ b/src/modulator.h @@ -29,4 +29,4 @@ void Modulator_saveToFile(RDSModulatorParameters *emp, const char *option); void Modulator_loadFromFile(RDSModulatorParameters *emp); int modulatorsaved(); void init_rds_modulator(RDSModulator* rdsMod, RDSEncoder* enc); -float get_rds_sample(RDSModulator* rdsMod); +float get_rds_sample(RDSModulator* rdsMod, bool rds2); diff --git a/src/rds.c b/src/rds.c index ee5c819..a7af64d 100644 --- a/src/rds.c +++ b/src/rds.c @@ -112,7 +112,7 @@ void saveToFile(RDSEncoder *emp, const char *option) { 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.encoder_data[emp->program]), &(emp->encoder_data[emp->program]), sizeof(RDSODAState)); + memcpy(&(tempEncoder.encoder_data), &(emp->encoder_data), sizeof(RDSEncoderData)); tempEncoder.program = emp->program; } @@ -124,7 +124,7 @@ void saveToFile(RDSEncoder *emp, const char *option) { 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.encoder_data[emp->program]), &(tempEncoder.encoder_data[emp->program]), sizeof(RDSODAState)); + memcpy(&(rdsEncoderfile.encoder_data), &(tempEncoder.encoder_data), sizeof(RDSEncoderData)); rdsEncoderfile.program = tempEncoder.program; file = fopen(encoderPath, "wb"); @@ -159,8 +159,8 @@ void loadFromFile(RDSEncoder *enc) { 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->encoder_data[i]), &(rdsEncoderfile.encoder_data[i]), sizeof(RDSODAState)); } + memcpy(&(enc->encoder_data), &(rdsEncoderfile.encoder_data), sizeof(RDSODAState)); enc->program = rdsEncoderfile.program; } @@ -546,8 +546,13 @@ static uint8_t get_rds_custom_groups(RDSEncoder* enc, uint16_t *blocks) { return 0; } -static void get_rds_group(RDSEncoder* enc, uint16_t *blocks) { +static void get_rds_group(RDSEncoder* enc, uint16_t *blocks, bool rds2) { blocks[0] = enc->data[enc->program].pi; + if(rds2 && !enc->encoder_data.rds2_mode) blocks[0] = 0; // tunneling + else if(rds2 && enc->encoder_data.rds2_mode) { + // TODO: add rds2 only stuff + return; + } blocks[1] = 0; blocks[2] = 0; blocks[3] = 0; @@ -726,9 +731,9 @@ group_coded: } } -void get_rds_bits(RDSEncoder* enc, uint8_t *bits) { +void get_rds_bits(RDSEncoder* enc, uint8_t *bits, bool rds2) { static uint16_t out_blocks[GROUP_LENGTH]; - get_rds_group(enc, out_blocks); + get_rds_group(enc, out_blocks, rds2); add_checkwords(out_blocks, bits); } @@ -775,10 +780,10 @@ 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)); + memset(&(enc->encoder_data), 0, sizeof(RDSEncoderData)); - enc->encoder_data[program].encoder_addr[0] = 255; - enc->encoder_data[program].encoder_addr[1] = 255; + enc->encoder_data.encoder_addr[0] = 255; + enc->encoder_data.encoder_addr[1] = 255; enc->data[program].ct = 1; enc->data[program].di = 1; diff --git a/src/rds.h b/src/rds.h index bc95ecd..f63c38d 100644 --- a/src/rds.h +++ b/src/rds.h @@ -241,10 +241,11 @@ typedef struct { uint16_t special_features; RDSScheduler schedule; RDSMessages messages; + uint8_t rds2_mode : 1; // uint8_t rds2_buffer[16384]; } RDSEncoderData; typedef struct { - RDSEncoderData encoder_data[PROGRAMS]; + RDSEncoderData encoder_data; RDSData data[PROGRAMS]; RDSState state[PROGRAMS]; RDSODA odas[PROGRAMS][MAX_ODAS]; @@ -260,7 +261,7 @@ typedef struct { RDSODA odas[PROGRAMS][MAX_ODAS]; uint8_t file_middle; // Always is 160, average of both RDSODAState oda_state[PROGRAMS]; - RDSEncoderData encoder_data[PROGRAMS]; + RDSEncoderData encoder_data; uint8_t program : 3; uint8_t file_ender; // Always is 95 my freq } RDSEncoderFile; @@ -332,7 +333,7 @@ int rdssaved(); void reset_rds_state(RDSEncoder* enc, uint8_t program); 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 get_rds_bits(RDSEncoder* enc, uint8_t *bits, bool rds2); void set_rds_rt1(RDSEncoder* enc, char *rt1); void set_rds_rt2(RDSEncoder* enc, char *rt2); void set_rds_dps1(RDSEncoder* enc, char *dps1); diff --git a/src/rds95.c b/src/rds95.c index e5d97c4..a8014a0 100644 --- a/src/rds95.c +++ b/src/rds95.c @@ -11,6 +11,9 @@ #include "lib.h" #include "ascii_cmd.h" +#define RDS_DEVICE "RDS" +#define RDS2_DEVICE "RDS2" + #define NUM_MPX_FRAMES 512 static uint8_t stop_rds; @@ -53,7 +56,11 @@ int main(int argc, char **argv) { char control_pipe[51] = "\0"; pa_simple *device; + #ifdef RDS2_DEVICE + pa_simple *rds2_device; + #endif pa_sample_spec format; + pa_buffer_attr buffer; pthread_attr_t attr; pthread_t control_pipe_thread; @@ -91,21 +98,42 @@ int main(int argc, char **argv) { format.channels = 1; format.rate = RDS_SAMPLE_RATE; + buffer.prebuf = 0; + buffer.tlength = 8192; + buffer.maxlength = 8192; + device = pa_simple_new( - NULL, // Default PulseAudio server - "rds95", // Application name - PA_STREAM_PLAYBACK, // Direction (playback) - "RDS", // Default device - "RDS Generator", // Stream description - &format, // Sample format - NULL, // Default channel map - NULL, // Default buffering attributes - NULL // Error variable + NULL, + "rds95", + PA_STREAM_PLAYBACK, + RDS_DEVICE, + "RDS Generator", + &format, + NULL, + &buffer, + NULL ); if (device == NULL) { fprintf(stderr, "Error: cannot open sound device.\n"); goto exit; } + #ifdef RDS2_DEVICE + rds2_device = pa_simple_new( + NULL, + "rds95", + PA_STREAM_PLAYBACK, + RDS2_DEVICE, + "RDS2 Generator", + &format, + NULL, + &buffer, + NULL + ); + if(rds2_device == NULL) { + fprintf(stderr, "Error: cannot open sound device.\n"); + goto exit; + } + #endif RDSEncoder rdsEncoder; RDSModulator rdsModulator; @@ -132,17 +160,29 @@ int main(int argc, char **argv) { int pulse_error; - static float mpx_buffer[NUM_MPX_FRAMES]; + float rds1_buffer[NUM_MPX_FRAMES]; + #ifdef RDS2_DEVICE + float rds2_buffer[NUM_MPX_FRAMES]; + #endif while(!stop_rds) { for (uint16_t i = 0; i < NUM_MPX_FRAMES; i++) { - mpx_buffer[i] = get_rds_sample(&rdsModulator); + rds1_buffer[i] = get_rds_sample(&rdsModulator, false); + #ifdef RDS2_DEVICE + rds2_buffer[i] = get_rds_sample(&rdsModulator, true); + #endif } - if (pa_simple_write(device, mpx_buffer, sizeof(mpx_buffer), &pulse_error) != 0) { + if (pa_simple_write(device, rds1_buffer, sizeof(rds1_buffer), &pulse_error) != 0) { fprintf(stderr, "Error: could not play audio. (%s : %d)\n", pa_strerror(pulse_error), pulse_error); break; } + #ifdef RDS2_DEVICE + if (pa_simple_write(rds2_device, rds2_buffer, sizeof(rds2_buffer), &pulse_error) != 0) { + fprintf(stderr, "Error: could not play audio. (%s : %d)\n", pa_strerror(pulse_error), pulse_error); + break; + } + #endif } exit: @@ -153,6 +193,9 @@ exit: pthread_attr_destroy(&attr); pa_simple_free(device); + #ifdef RDS2_DEVICE + pa_simple_free(rds2_device); + #endif return 0; } \ No newline at end of file