The RDS encoder and modulator is now working ! :)

This commit is contained in:
Jean-François DEL NERO 2022-11-27 00:48:39 +01:00
parent ce0cb6448f
commit 3b959d2776
6 changed files with 174 additions and 16 deletions

View File

@ -28,7 +28,7 @@ EXEC=broadcast_fm rf_jammer
all: $(EXEC)
broadcast_fm: broadcast_fm.o rds.o wave.o modulator.o FIR_Audio_Filter_Filter.o FM_Baseband_Filter.o AudioPreemphasis_Filter.o hxcmod.o rand_gen.o
broadcast_fm: broadcast_fm.o rds.o rds_stream_dump.o wave.o modulator.o FIR_Audio_Filter_Filter.o FM_Baseband_Filter.o AudioPreemphasis_Filter.o hxcmod.o rand_gen.o
$(CC) -o $@ $^ $(LDFLAGS)
rf_jammer: rf_jammer.o wave.o modulator.o rand_gen.o
@ -43,6 +43,9 @@ rf_jammer.o: ../src/rf_jammer/rf_jammer.c
rds.o: ../src/broadcast_fm/rds.c
$(CC) -o $@ -c $< $(CFLAGS)
rds_stream_dump.o: ../src/broadcast_fm/rds_stream_dump.c
$(CC) -o $@ -c $< $(CFLAGS)
utils.o: ../src/common/utils.c
$(CC) -o $@ -c $< $(CFLAGS)

View File

@ -96,7 +96,7 @@
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Current software design :
//
// Mod player / Left Audio -> Preemphasis (FIR) -> \ / -> Left + Right -> 15KHz low pass (FIR) -------------------------------|
// Mod player / Left Audio -> Preemphasis (FIR) -> \ / -> Left + Right -> 15KHz low pass (FIR) >------------------------------|
// Sound \/ |
// generator /\ |
// \ Right Audio -> Preemphasis (FIR) -> / \ -> Left - Right -> 15KHz low pass (FIR) |
@ -108,7 +108,17 @@
// | 38KHz Osc |
// | (|) (These oscillators |
// | (|) must be kept in phase) |
// 19KHz Pilot Osc ------------------|
// | 19KHz Pilot Osc >-----------------+
// | (|) |
// | (|) (57KHz DSB-SC modulated)|
// | 57KHz Osc-->|MUL|>-----------------+
// | ^
// ____ v_____ |
// | | |
// | RDS |>----
// | Generator |
// |___________|
//
//
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -31,6 +31,24 @@
#include "modulator.h"
#include "rds.h"
#include "rds_stream_dump.h"
const uint16_t crc_group_xor[]=
{
0xFC, // A
0x198, // B
0x168, // C
0x1B4, // D
0x350 // C'
};
const uint16_t rds_codes[]=
{
0xF849,
0x0CE8,
0xF849,
0x0000 // Char code.
};
void init_rds_encoder(rds_stat * stat,int sample_rate)
{
@ -38,6 +56,7 @@ void init_rds_encoder(rds_stat * stat,int sample_rate)
stat->bit_rate = RDS_BIT_RATE;
stat->old_pilot_phase = 0;
stat->sample_rate = sample_rate;
strcpy(stat->station_name,"- RDS - - RDS - - RDS - - RDS - --TEST----TEST----TEST----TEST----TEST----TEST--\n");
}
int rds_differential_encoder(rds_stat * stat)
@ -47,30 +66,147 @@ int rds_differential_encoder(rds_stat * stat)
return stat->current_diff_dat_state;
}
uint32_t rds_crc (uint16_t data)
{
int i;
uint16_t crc = 0;
int crc_msb;
for(i=0; i<16; i++)
{
crc_msb = (crc >> (10-1)) & 1;
crc <<= 1;
if( crc_msb ^ (data >> 15 ) )
{
crc ^= 0x1B9;
}
data <<= 1;
}
return crc & 0x3FF;
}
uint32_t encode_rds_bloc(uint16_t data, int group)
{
uint32_t word;
word = ((uint32_t)data)<<10;
word |= (rds_crc (data) ^ crc_group_xor[group]);
//printf("rds(%d): dat:0x%.4X grp:0x%.4X 0x%.4X\n",group,data,word&0x3FF,word);
return word;
}
int get_next_rds_bit(rds_stat * stat)
{
int dat;
uint16_t rdsc;
#ifdef USE_RDS_STREAM_BIT
if(!rds_stream_dump[stat->current_rds_code_index])
{
stat->current_rds_code_index = 0;
dat = rds_stream_dump[stat->current_rds_code_index];
}
else
dat = rds_stream_dump[stat->current_rds_code_index];
stat->current_rds_code_index++;
return dat;
#endif
stat->current_bloc_index--;
if(stat->current_bloc_index<0)
{
// prepare next bloc
#ifdef USE_RDS_STREAM
rdsc = rds_dump[stat->current_rds_code_index];
stat->current_bloc = encode_rds_bloc(rdsc, stat->current_rds_code_index&3 );
stat->current_rds_code_index++;
if(stat->current_rds_code_index >= 327*4 )
{
stat->current_rds_code_index = 0;
}
#else
rdsc = rds_codes[stat->current_rds_code_index];
if(rdsc)
{
if( stat->current_rds_code_index == 1)
{
stat->current_bloc = encode_rds_bloc(rdsc | (stat->station_name_index>>1),stat->current_rds_code_index );
stat->current_rds_code_index++;
}
else
{
stat->current_bloc = encode_rds_bloc(rdsc,stat->current_rds_code_index);
stat->current_rds_code_index++;
}
}
else
{
rdsc = stat->station_name[stat->station_name_index++];
rdsc <<= 8;
rdsc |= stat->station_name[stat->station_name_index++];
stat->current_bloc = encode_rds_bloc(rdsc,stat->current_rds_code_index);
if(!stat->station_name[stat->station_name_index])
{
stat->station_name_index = 0;
}
stat->current_rds_code_index = 0;
}
#endif
stat->current_bloc_index = 25;
}
if( (stat->current_bloc >> (stat->current_bloc_index)) & 0x1 )
{
dat = 1;
}
else
{
dat = 0;
}
//printf("%d",dat);
return dat;
}
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;
phase_diff = ( 2.0 * PI - stat->old_pilot_phase) + pilot_phase;
else
phase_diff = pilot_phase - stat->old_pilot_phase;
if( phase_diff >= ((2*PI) / 3) )
if( phase_diff >= ( ( 2.0 * PI ) / 3.0 ) ) // 19KHz period / 3 -> 57KHz
{
// New 57KHz tick clock
stat->old_pilot_phase = pilot_phase;//+= ((2*PI) / 3);
stat->old_pilot_phase += ( ( 2.0 * PI ) / 3.0 );
if(stat->old_pilot_phase >= (2*PI))
stat->old_pilot_phase = 0;
if(stat->old_pilot_phase >= ( 2.0 * PI ))
stat->old_pilot_phase -= ( 2.0 * PI );
stat->cycles_count++;
if(stat->cycles_count >= 16*2)
if(stat->cycles_count >= 48)
{
stat->test++;
stat->ser_data_in = rand()&1;
stat->ser_data_in = get_next_rds_bit(stat);
rds_differential_encoder(stat);
@ -80,13 +216,13 @@ double get_rds_bit_state(rds_stat * stat, double pilot_phase)
}
// Delayed signal
if(stat->cycles_count == 8*2)
if(stat->cycles_count == 24)
{
stat->current_data_state = stat->current_diff_dat_state ^ 1;
}
}
#define FREQ_FILTER (1187.5*1.0)
#define FREQ_FILTER (1187.5*0.50)
if(stat->current_data_state)
{
@ -113,7 +249,7 @@ double get_rds_bit_state(rds_stat * stat, double pilot_phase)
}
}
sample = ( cos( stat->phase ) * 3.0 );
sample = ( cos( stat->phase ) * ( 5.0 ) );
return sample;
}

View File

@ -40,6 +40,15 @@ typedef struct _rds_stat
int test;
int cycles_count;
char station_name[256+1];
int station_name_index;
uint32_t current_bloc;
int current_bloc_index;
int current_rds_code_index;
}rds_stat;
void init_rds_encoder(rds_stat * stat,int sample_rate);

View File

@ -76,10 +76,10 @@ double f_get_next_sample(wave_gen * wg)
wg->phase += ( (2.0 * PI * wg->Frequency) / (double)wg->sample_rate );
if(wg->phase > (2.0 * PI) )
if(wg->phase >= (2.0 * PI) )
wg->phase -= (2.0 * PI);
if(wg->phase < (-2.0 * PI) )
if(wg->phase <= (-2.0 * PI) )
wg->phase += (2.0 * PI);
return sample;

View File

@ -30,7 +30,7 @@
#if defined(M_PI)
#define PI M_PI
#else
#define PI 3.1415926535897932384626433832795
#define PI ((double)(3.1415926535897932384626433832795))
#endif
typedef struct iq_wave_gen_