mirror of
https://github.com/jfdelnero/rf-tools.git
synced 2024-11-21 11:21:47 -05:00
wip : RDS support.
This commit is contained in:
parent
94f026bfaf
commit
ff13d3d307
@ -128,6 +128,8 @@
|
||||
|
||||
#include "modulator.h"
|
||||
|
||||
#include "rds.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "fir_filters/FIR_Audio_Filter_Filter.h"
|
||||
@ -238,6 +240,7 @@ int main(int argc, char* argv[])
|
||||
double audio_sample_final;
|
||||
double audio_sample_r_car;
|
||||
double pilot_sample;
|
||||
double rds_sample,rds_mod_sample;
|
||||
double balance_sample;
|
||||
double fm_mod;
|
||||
|
||||
@ -259,6 +262,9 @@ int main(int argc, char* argv[])
|
||||
|
||||
wave_gen audiow_stereo38KHz_gen;
|
||||
wave_gen stereo_pilot_gen;
|
||||
wave_gen rds_carrier_57KHz_gen;
|
||||
|
||||
rds_stat rdsstat;
|
||||
|
||||
uint16_t iq_wave_buf[ BUFFER_SAMPLES_SIZE * (IQ_SAMPLE_RATE/SUBCARRIERS_SAMPLE_RATE)];
|
||||
int16_t mod_wave_buf[(BUFFER_SAMPLES_SIZE*2)/4];
|
||||
@ -347,12 +353,12 @@ int main(int argc, char* argv[])
|
||||
// Left and Right audio freq (used if no .mod music file)
|
||||
audio_l_gen.phase = 0;
|
||||
audio_l_gen.Frequency = 700;
|
||||
audio_l_gen.Amplitude = 22.5;
|
||||
audio_l_gen.Amplitude = 21.25;
|
||||
audio_l_gen.sample_rate = SUBCARRIERS_SAMPLE_RATE;
|
||||
|
||||
audio_r_gen.phase = 0;
|
||||
audio_r_gen.Frequency = 1000;
|
||||
audio_r_gen.Amplitude = 22.5;
|
||||
audio_r_gen.Amplitude = 21.25;
|
||||
audio_r_gen.sample_rate = SUBCARRIERS_SAMPLE_RATE;
|
||||
|
||||
// Left <> Right balance LFO (used if no .mod music file)
|
||||
@ -373,6 +379,14 @@ int main(int argc, char* argv[])
|
||||
audiow_stereo38KHz_gen.Amplitude = 1;
|
||||
audiow_stereo38KHz_gen.sample_rate = SUBCARRIERS_SAMPLE_RATE;
|
||||
|
||||
// 57KHz RDS carrier
|
||||
rds_carrier_57KHz_gen.phase = 0;
|
||||
rds_carrier_57KHz_gen.Frequency = 57000;
|
||||
rds_carrier_57KHz_gen.Amplitude = 1;
|
||||
rds_carrier_57KHz_gen.sample_rate = SUBCARRIERS_SAMPLE_RATE;
|
||||
|
||||
init_rds_encoder(&rdsstat,SUBCARRIERS_SAMPLE_RATE);
|
||||
|
||||
// IQ Modulator
|
||||
iqgen.phase = 0;
|
||||
iqgen.Frequency = IF_FREQ;
|
||||
@ -456,14 +470,22 @@ int main(int argc, char* argv[])
|
||||
FIR_Audio_Filter_Filter_put(&leftminusright_audio_filter, leftminusright_audio);
|
||||
leftminusright_audio = FIR_Audio_Filter_Filter_get(&leftminusright_audio_filter);
|
||||
|
||||
// Keep the 18KHz pilot and the 38KHz clock in phase :
|
||||
// Keep the 19KHz pilot and the 38KHz clock in phase :
|
||||
audiow_stereo38KHz_gen.phase = (stereo_pilot_gen.phase * 2) + PI/2;
|
||||
|
||||
rds_carrier_57KHz_gen.phase = (stereo_pilot_gen.phase * 3) + PI/2;
|
||||
|
||||
rds_mod_sample = get_rds_bit_state(&rdsstat,stereo_pilot_gen.phase);
|
||||
|
||||
// 38KHz DSB-SC (Double-sideband suppressed-carrier) modulation
|
||||
audio_sample_r_car = f_get_next_sample(&audiow_stereo38KHz_gen); // Get the 38KHz carrier
|
||||
audio_sample_r_car = (audio_sample_r_car * leftminusright_audio ); // And multiply it with the left - right sample.
|
||||
|
||||
// 18KHz pilot
|
||||
// 57KHz DSB-SC (Double-sideband suppressed-carrier) modulation
|
||||
rds_sample = f_get_next_sample(&rds_carrier_57KHz_gen); // Get the 57KHz carrier
|
||||
rds_sample = ( rds_sample * rds_mod_sample ); // And multiply it with the rds sample.
|
||||
|
||||
// 19KHz pilot
|
||||
pilot_sample = f_get_next_sample(&stereo_pilot_gen);
|
||||
}
|
||||
else
|
||||
@ -471,11 +493,12 @@ int main(int argc, char* argv[])
|
||||
// Mono : No pilot nor 38KHz modulation...
|
||||
audio_sample_r_car = 0;
|
||||
pilot_sample = 0;
|
||||
rds_sample = 0;
|
||||
}
|
||||
|
||||
// Mix all signals sources :
|
||||
// 45% 45% 10%
|
||||
audio_sample_final = ((leftplusright_audio) + audio_sample_r_car + pilot_sample);
|
||||
// 42.5% 42.5% 10% 5%
|
||||
audio_sample_final = ((leftplusright_audio) + audio_sample_r_car + pilot_sample + rds_sample);
|
||||
|
||||
// Main carrier frequency modulation : +/- 75KHz
|
||||
fm_mod = ((audio_sample_final / (double)(100.0)) * (double)(75000));
|
||||
@ -485,7 +508,7 @@ int main(int argc, char* argv[])
|
||||
//FM_Baseband_Filter_put(&fmband_filter, fm_mod );
|
||||
//fm_mod = FM_Baseband_Filter_get(&fmband_filter);
|
||||
|
||||
subcarriers_dbg_wave_buf[j] = fm_mod;
|
||||
subcarriers_dbg_wave_buf[j] = fm_mod/4;
|
||||
subcarriers_float_wave_buf[j] = fm_mod;
|
||||
}
|
||||
|
||||
|
119
src/broadcast_fm/rds.c
Normal file
119
src/broadcast_fm/rds.c
Normal file
@ -0,0 +1,119 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
|
||||
//----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------//
|
||||
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
|
||||
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
|
||||
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//----------------------------------------------------- http://hxc2001.free.fr --//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// File : rds.c
|
||||
// Contains: rds engine
|
||||
//
|
||||
// This file is part of rf-tools.
|
||||
//
|
||||
// Written by: Jean-François DEL NERO
|
||||
//
|
||||
// Copyright (C) 2022 Jean-François DEL NERO
|
||||
//
|
||||
// You are free to do what you want with this code.
|
||||
// A credit is always appreciated if you use it into your product :)
|
||||
//
|
||||
// Change History (most recent first):
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "modulator.h"
|
||||
#include "rds.h"
|
||||
|
||||
void init_rds_encoder(rds_stat * stat,int sample_rate)
|
||||
{
|
||||
memset(stat,0,sizeof(rds_stat));
|
||||
stat->bit_rate = RDS_BIT_RATE;
|
||||
stat->old_pilot_phase = 0;
|
||||
stat->sample_rate = sample_rate;
|
||||
}
|
||||
|
||||
int rds_differential_encoder(rds_stat * stat)
|
||||
{
|
||||
stat->current_diff_dat_state = ((stat->ser_data_in & 1) ^ stat->current_diff_dat_state);
|
||||
|
||||
return stat->current_diff_dat_state;
|
||||
}
|
||||
|
||||
double get_rds_bit_state(rds_stat * stat, double pilot_phase)
|
||||
{
|
||||
double sample;
|
||||
double phase_diff;
|
||||
|
||||
if(pilot_phase < stat->old_pilot_phase)
|
||||
phase_diff = (2*PI + pilot_phase) - stat->old_pilot_phase;
|
||||
else
|
||||
phase_diff = pilot_phase - stat->old_pilot_phase;
|
||||
|
||||
if( phase_diff >= ((2*PI) / 3) )
|
||||
{
|
||||
// New 57KHz tick clock
|
||||
stat->old_pilot_phase = pilot_phase;//+= ((2*PI) / 3);
|
||||
|
||||
if(stat->old_pilot_phase >= (2*PI))
|
||||
stat->old_pilot_phase = 0;
|
||||
|
||||
stat->cycles_count++;
|
||||
if(stat->cycles_count >= 16*2)
|
||||
{
|
||||
stat->test++;
|
||||
|
||||
stat->ser_data_in = rand()&1;
|
||||
|
||||
rds_differential_encoder(stat);
|
||||
|
||||
stat->current_data_state = (stat->current_diff_dat_state & 0x1);
|
||||
|
||||
stat->cycles_count = 0;
|
||||
}
|
||||
|
||||
// Delayed signal
|
||||
if(stat->cycles_count == 8*2)
|
||||
{
|
||||
stat->current_data_state = stat->current_diff_dat_state ^ 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define FREQ_FILTER (1187.5*1.0)
|
||||
|
||||
if(stat->current_data_state)
|
||||
{
|
||||
// Must go to 0.
|
||||
if( !((stat->phase >= ((2*PI) - ((2.0 * PI * (FREQ_FILTER*2))/ (double)stat->sample_rate) ) ) || // >=// 2PI - step
|
||||
(stat->phase < (((2.0 * PI * (FREQ_FILTER*2))/ (double)stat->sample_rate) ) ) ) // < // step
|
||||
)
|
||||
{
|
||||
stat->phase += ( (2.0 * PI * (FREQ_FILTER*2) ) / (double)stat->sample_rate );
|
||||
if(stat->phase >= 2.0 * PI)
|
||||
stat->phase -= (2.0 * PI);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must go to PI.
|
||||
if( !((stat->phase >= ((PI) - ((2.0 * PI * (FREQ_FILTER*2))/ (double)stat->sample_rate) ) ) && // > PI - step
|
||||
(stat->phase < ((PI) + ((2.0 * PI * (FREQ_FILTER*2))/ (double)stat->sample_rate) ) )) // < PI + step
|
||||
)
|
||||
{
|
||||
stat->phase += ( (2.0 * PI * (FREQ_FILTER*2) ) / (double)stat->sample_rate );
|
||||
if(stat->phase >= 2.0 * PI)
|
||||
stat->phase -= (2.0 * PI);
|
||||
}
|
||||
}
|
||||
|
||||
sample = ( cos( stat->phase ) * 3.0 );
|
||||
|
||||
return sample;
|
||||
}
|
46
src/broadcast_fm/rds.h
Normal file
46
src/broadcast_fm/rds.h
Normal file
@ -0,0 +1,46 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
|
||||
//----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------//
|
||||
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
|
||||
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
|
||||
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//----------------------------------------------------- http://hxc2001.free.fr --//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// File : rds.h
|
||||
// Contains: rds engine
|
||||
//
|
||||
// This file is part of rf-tools.
|
||||
//
|
||||
// Written by: Jean-François DEL NERO
|
||||
//
|
||||
// Copyright (C) 2022 Jean-François DEL NERO
|
||||
//
|
||||
// You are free to do what you want with this code.
|
||||
// A credit is always appreciated if you use it into your product :)
|
||||
//
|
||||
// Change History (most recent first):
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define RDS_BIT_RATE 1187.5
|
||||
|
||||
typedef struct _rds_stat
|
||||
{
|
||||
int sample_rate;
|
||||
float bit_rate;
|
||||
|
||||
double old_pilot_phase;
|
||||
double phase;
|
||||
|
||||
int current_data_state;
|
||||
int current_diff_dat_state;
|
||||
int ser_data_in;
|
||||
|
||||
int test;
|
||||
int cycles_count;
|
||||
}rds_stat;
|
||||
|
||||
void init_rds_encoder(rds_stat * stat,int sample_rate);
|
||||
double get_rds_bit_state(rds_stat * stat, double pilot_phase);
|
Loading…
Reference in New Issue
Block a user