diff --git a/src/modulator.c b/src/modulator.c index 1cf1ec5..ec1f056 100644 --- a/src/modulator.c +++ b/src/modulator.c @@ -88,8 +88,7 @@ void init_rds_modulator(RDSModulator* rdsMod, RDSEncoder* enc) { rdsMod->enc = enc; - if(STREAMS > 0) rdsMod->data[1].symbol_shift = FILTER_SIZE / 2; - + if(STREAMS > 0) rdsMod->data[1].symbol_shift = M_PI; if(modulatorsaved()) { Modulator_loadFromFile(&rdsMod->params); } else { @@ -112,7 +111,7 @@ float get_rds_sample(RDSModulator* rdsMod, uint8_t stream) { rdsMod->data[stream].cur_output = rdsMod->data[stream].prev_output ^ rdsMod->data[stream].cur_bit; } - float sample = sinf(M_2PI * (rdsMod->data[stream].phase - rdsMod->data[stream].symbol_shift)); + float sample = sinf(M_2PI * rdsMod->data[stream].phase + rdsMod->data[stream].symbol_shift); if(rdsMod->data[stream].cur_output == 0) sample = -sample; // do bpsk uint8_t tooutput = rdsMod->params.rdsgen > stream ? 1 : 0; diff --git a/src/rds.c b/src/rds.c index 9399632..2c37384 100644 --- a/src/rds.c +++ b/src/rds.c @@ -10,34 +10,35 @@ void saveToFile(RDSEncoder *enc, const char *option) { RDSEncoder tempEncoder; FILE *file = fopen(encoderPath, "rb"); - if (file != NULL) { + if (file) { fread(&tempEncoder, sizeof(RDSEncoder), 1, file); fclose(file); } else memcpy(&tempEncoder, enc, sizeof(RDSEncoder)); - if(strcmp(option, "PROGRAM") == 0) { - memcpy(&(tempEncoder.data[enc->program]), &(enc->data[enc->program]), sizeof(RDSData)); - memcpy(&(tempEncoder.rtpData[enc->program]), &(enc->rtpData[enc->program]), sizeof(RDSRTPlusData)*2); - tempEncoder.program = enc->program; + if (strcmp(option, "PROGRAM") == 0) { + memcpy(&tempEncoder.data[enc->program], &enc->data[enc->program], sizeof(RDSData)); + memcpy(&tempEncoder.rtpData[enc->program], &enc->rtpData[enc->program], sizeof(RDSRTPlusData) * 2); } else if (strcmp(option, "ALL") == 0) { - memcpy(&tempEncoder.data, &enc->data, sizeof(RDSData)*PROGRAMS); - memcpy(&tempEncoder.rtpData, &enc->rtpData, sizeof(RDSRTPlusData)*PROGRAMS*2); + memcpy(tempEncoder.data, enc->data, sizeof(RDSData) * PROGRAMS); + memcpy(tempEncoder.rtpData, enc->rtpData, sizeof(RDSRTPlusData) * PROGRAMS * 2); memcpy(&tempEncoder.encoder_data, &enc->encoder_data, sizeof(RDSEncoderData)); - tempEncoder.program = enc->program; } else return; + tempEncoder.program = enc->program; - RDSEncoderFile rdsEncoderfile; - rdsEncoderfile.file_starter = 225; - rdsEncoderfile.file_middle = 160; - rdsEncoderfile.file_ender = 95; - memcpy(&(rdsEncoderfile.data[enc->program]), &(tempEncoder.data[enc->program]), sizeof(RDSData)); - memcpy(&(rdsEncoderfile.rtpData[enc->program]), &(tempEncoder.rtpData[enc->program]), sizeof(RDSRTPlusData)*2); - memcpy(&(rdsEncoderfile.encoder_data), &(tempEncoder.encoder_data), sizeof(RDSEncoderData)); - rdsEncoderfile.program = tempEncoder.program; - rdsEncoderfile.crc = crc16_ccitt((char*)&rdsEncoderfile, offsetof(RDSEncoderFile, crc)); + RDSEncoderFile rdsEncoderfile = { + .file_starter = 225, + .file_middle = 160, + .file_ender = 95, + .program = tempEncoder.program, + }; + memcpy(&rdsEncoderfile.data[enc->program], &tempEncoder.data[enc->program], sizeof(RDSData)); + memcpy(&rdsEncoderfile.rtpData[enc->program], &tempEncoder.rtpData[enc->program], sizeof(RDSRTPlusData) * 2); + memcpy(&rdsEncoderfile.encoder_data, &tempEncoder.encoder_data, sizeof(RDSEncoderData)); + + rdsEncoderfile.crc = crc16_ccitt((char *)&rdsEncoderfile, offsetof(RDSEncoderFile, crc)); file = fopen(encoderPath, "wb"); - if (file == NULL) { + if (!file) { perror("Error opening file"); return; } @@ -51,20 +52,19 @@ void loadFromFile(RDSEncoder *enc) { RDSEncoderFile rdsEncoderfile; FILE *file = fopen(encoderPath, "rb"); - if (file == NULL) { + if (!file) { perror("Error opening file"); return; } - fread(&rdsEncoderfile, sizeof(RDSEncoderFile), 1, file); + fread(&rdsEncoderfile, sizeof(rdsEncoderfile), 1, file); fclose(file); - + if (rdsEncoderfile.file_starter != 225 || rdsEncoderfile.file_ender != 95 || rdsEncoderfile.file_middle != 160) { fprintf(stderr, "[RDSENCODER-FILE] Invalid file format\n"); return; } - uint16_t calculated_crc = crc16_ccitt((char*)&rdsEncoderfile, offsetof(RDSEncoderFile, crc)); - if (calculated_crc != rdsEncoderfile.crc) { + if (crc16_ccitt((char*)&rdsEncoderfile, offsetof(RDSEncoderFile, crc)) != rdsEncoderfile.crc) { fprintf(stderr, "[RDSENCODER-FILE] CRC mismatch! Data may be corrupted\n"); return; } @@ -77,15 +77,13 @@ void loadFromFile(RDSEncoder *enc) { enc->program = rdsEncoderfile.program; } -int rdssaved() { +int isFileSaved() { char encoderPath[128]; snprintf(encoderPath, sizeof(encoderPath), "%s/.rdsEncoder", getenv("HOME")); FILE *file = fopen(encoderPath, "rb"); - if (file) { - fclose(file); - return 1; - } - return 0; + if(!file) return 0; + fclose(file); + return 1; } static uint16_t get_next_af(RDSEncoder* enc) { @@ -160,11 +158,8 @@ static void get_rds_ps_group(RDSEncoder* enc, RDSGroup *group) { if(enc->state[enc->program].ps_csegment == 0) group->b |= enc->data[enc->program].dpty << 2; group->b |= enc->state[enc->program].ps_csegment; group->c = get_next_af(enc); - if(enc->data[enc->program].ta && enc->state[enc->program].tps_text[0] != '\0') { - group->d = enc->state[enc->program].tps_text[enc->state[enc->program].ps_csegment * 2] << 8 | enc->state[enc->program].tps_text[enc->state[enc->program].ps_csegment * 2 + 1]; - } else { - group->d = enc->state[enc->program].ps_text[enc->state[enc->program].ps_csegment * 2] << 8 | enc->state[enc->program].ps_text[enc->state[enc->program].ps_csegment * 2 + 1]; - } + if(enc->data[enc->program].ta && enc->state[enc->program].tps_text[0] != '\0') group->d = enc->state[enc->program].tps_text[enc->state[enc->program].ps_csegment * 2] << 8 | enc->state[enc->program].tps_text[enc->state[enc->program].ps_csegment * 2 + 1]; + else group->d = enc->state[enc->program].ps_text[enc->state[enc->program].ps_csegment * 2] << 8 | enc->state[enc->program].ps_text[enc->state[enc->program].ps_csegment * 2 + 1]; enc->state[enc->program].ps_csegment++; if (enc->state[enc->program].ps_csegment == 4) enc->state[enc->program].ps_csegment = 0; @@ -297,7 +292,6 @@ static void get_rds_ct_group(RDSEncoder* enc, RDSGroup *group) { group->d = (utc->tm_hour & 0xf) << 12 | utc->tm_min << 6; local_time = localtime(&now); - offset = local_time->__tm_gmtoff / (30 * 60); if (offset < 0) group->d |= 1 << 5; group->d |= abs(offset); @@ -806,7 +800,7 @@ void set_rds_defaults(RDSEncoder* enc, uint8_t program) { void init_rds_encoder(RDSEncoder* enc) { for(int i = 0; i < PROGRAMS; i++) set_rds_defaults(enc, i); - if (rdssaved()) loadFromFile(enc); + if (isFileSaved()) loadFromFile(enc); else saveToFile(enc, "ALL"); for(int i = 0; i < PROGRAMS; i++) reset_rds_state(enc, i); diff --git a/src/rds.h b/src/rds.h index 5473f51..429d7f5 100644 --- a/src/rds.h +++ b/src/rds.h @@ -11,8 +11,6 @@ #define GROUP_LENGTH 4 #define BITS_PER_GROUP (GROUP_LENGTH * (BLOCK_SIZE + POLY_DEG)) #define RDS_SAMPLE_RATE 4750 -#define FILTER_SIZE 4 // RDS_SAMPLE_RATE/1187.5, or the inverse i dont remember - #define STREAMS 2 #define RT_LENGTH 64 @@ -238,7 +236,7 @@ typedef struct void saveToFile(RDSEncoder *emp, const char *option); void loadFromFile(RDSEncoder *emp); -int rdssaved(); +int isFileSaved(); void reset_rds_state(RDSEncoder* enc, uint8_t program); void set_rds_defaults(RDSEncoder* enc, uint8_t program); diff --git a/src/rds95.c b/src/rds95.c index d72a69b..7a09484 100644 --- a/src/rds95.c +++ b/src/rds95.c @@ -42,9 +42,11 @@ static void show_help(char *name) { "\n" "Usage: %s [options]\n" "\n" - " -C,--ctl FIFO control pipe\n" + "\t-C,--ctl\tFIFO control pipe\n" + "\t-d,--device\tPulseAudio device to use (default: %s)\n" "\n", - name + name, + RDS_DEVICE ); } @@ -52,6 +54,7 @@ int main(int argc, char **argv) { show_version(); char control_pipe[51] = "\0"; + char rds_device_name[32] = RDS_DEVICE; pa_simple *rds_device = NULL; pa_sample_spec format; @@ -60,13 +63,12 @@ int main(int argc, char **argv) { pthread_attr_t attr; pthread_t control_pipe_thread; - const char *short_opt = "C:h"; + const char *short_opt = "C:d:"; struct option long_opt[] = { {"ctl", required_argument, NULL, 'C'}, - - {"help", no_argument, NULL, 'h'}, + {"device", required_argument, NULL, 'd'}, { 0, 0, 0, 0 } }; @@ -76,8 +78,10 @@ int main(int argc, char **argv) { case 'C': memcpy(control_pipe, optarg, 50); break; - - case 'h': + case 'd': + memcpy(rds_device_name, optarg, 31); + rds_device_name[31] = '\0'; + break; default: show_help(argv[0]); return 1; @@ -90,18 +94,18 @@ int main(int argc, char **argv) { signal(SIGTERM, stop); format.format = PA_SAMPLE_FLOAT32NE; - format.channels = 2; + format.channels = STREAMS; format.rate = RDS_SAMPLE_RATE; buffer.prebuf = 0; - buffer.tlength = NUM_MPX_FRAMES*2; - buffer.maxlength = NUM_MPX_FRAMES*2; + buffer.tlength = NUM_MPX_FRAMES*STREAMS; + buffer.maxlength = NUM_MPX_FRAMES*STREAMS; rds_device = pa_simple_new( NULL, "rds95", PA_STREAM_PLAYBACK, - RDS_DEVICE, + rds_device_name, "RDS Generator", &format, NULL, @@ -138,12 +142,11 @@ int main(int argc, char **argv) { int pulse_error; - float rds_buffer[NUM_MPX_FRAMES*2]; + float rds_buffer[NUM_MPX_FRAMES*STREAMS]; while(!stop_rds) { - for (uint16_t i = 0; i < NUM_MPX_FRAMES*2; i += 2) { - rds_buffer[i] = get_rds_sample(&rdsModulator, 0); - rds_buffer[i+1] = get_rds_sample(&rdsModulator, 1); + for (uint16_t i = 0; i < NUM_MPX_FRAMES*STREAMS; i += STREAMS) { + for(uint8_t j = 0; j < STREAMS; j++) rds_buffer[i + j] = get_rds_sample(&rdsModulator, j); } if (pa_simple_write(rds_device, rds_buffer, sizeof(rds_buffer), &pulse_error) != 0) {