mirror of
https://github.com/jfdelnero/rf-tools.git
synced 2024-11-22 03:36:38 -05:00
The RDS encoder and modulator is now working ! :)
This commit is contained in:
parent
ce0cb6448f
commit
3b959d2776
@ -28,7 +28,7 @@ EXEC=broadcast_fm rf_jammer
|
|||||||
|
|
||||||
all: $(EXEC)
|
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)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
rf_jammer: rf_jammer.o wave.o modulator.o rand_gen.o
|
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
|
rds.o: ../src/broadcast_fm/rds.c
|
||||||
$(CC) -o $@ -c $< $(CFLAGS)
|
$(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
|
utils.o: ../src/common/utils.c
|
||||||
$(CC) -o $@ -c $< $(CFLAGS)
|
$(CC) -o $@ -c $< $(CFLAGS)
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
// Current software design :
|
// 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 \/ |
|
// Sound \/ |
|
||||||
// generator /\ |
|
// generator /\ |
|
||||||
// \ Right Audio -> Preemphasis (FIR) -> / \ -> Left - Right -> 15KHz low pass (FIR) |
|
// \ Right Audio -> Preemphasis (FIR) -> / \ -> Left - Right -> 15KHz low pass (FIR) |
|
||||||
@ -108,7 +108,17 @@
|
|||||||
// | 38KHz Osc |
|
// | 38KHz Osc |
|
||||||
// | (|) (These oscillators |
|
// | (|) (These oscillators |
|
||||||
// | (|) must be kept in phase) |
|
// | (|) must be kept in phase) |
|
||||||
// 19KHz Pilot Osc ------------------|
|
// | 19KHz Pilot Osc >-----------------+
|
||||||
|
// | (|) |
|
||||||
|
// | (|) (57KHz DSB-SC modulated)|
|
||||||
|
// | 57KHz Osc-->|MUL|>-----------------+
|
||||||
|
// | ^
|
||||||
|
// ____ v_____ |
|
||||||
|
// | | |
|
||||||
|
// | RDS |>----
|
||||||
|
// | Generator |
|
||||||
|
// |___________|
|
||||||
|
//
|
||||||
//
|
//
|
||||||
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -31,6 +31,24 @@
|
|||||||
|
|
||||||
#include "modulator.h"
|
#include "modulator.h"
|
||||||
#include "rds.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)
|
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->bit_rate = RDS_BIT_RATE;
|
||||||
stat->old_pilot_phase = 0;
|
stat->old_pilot_phase = 0;
|
||||||
stat->sample_rate = sample_rate;
|
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)
|
int rds_differential_encoder(rds_stat * stat)
|
||||||
@ -47,30 +66,147 @@ int rds_differential_encoder(rds_stat * stat)
|
|||||||
return stat->current_diff_dat_state;
|
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 get_rds_bit_state(rds_stat * stat, double pilot_phase)
|
||||||
{
|
{
|
||||||
double sample;
|
double sample;
|
||||||
double phase_diff;
|
double phase_diff;
|
||||||
|
|
||||||
if(pilot_phase < stat->old_pilot_phase)
|
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
|
else
|
||||||
phase_diff = pilot_phase - stat->old_pilot_phase;
|
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
|
// 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))
|
if(stat->old_pilot_phase >= ( 2.0 * PI ))
|
||||||
stat->old_pilot_phase = 0;
|
stat->old_pilot_phase -= ( 2.0 * PI );
|
||||||
|
|
||||||
stat->cycles_count++;
|
stat->cycles_count++;
|
||||||
if(stat->cycles_count >= 16*2)
|
if(stat->cycles_count >= 48)
|
||||||
{
|
{
|
||||||
stat->test++;
|
stat->test++;
|
||||||
|
|
||||||
stat->ser_data_in = rand()&1;
|
stat->ser_data_in = get_next_rds_bit(stat);
|
||||||
|
|
||||||
rds_differential_encoder(stat);
|
rds_differential_encoder(stat);
|
||||||
|
|
||||||
@ -80,13 +216,13 @@ double get_rds_bit_state(rds_stat * stat, double pilot_phase)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delayed signal
|
// Delayed signal
|
||||||
if(stat->cycles_count == 8*2)
|
if(stat->cycles_count == 24)
|
||||||
{
|
{
|
||||||
stat->current_data_state = stat->current_diff_dat_state ^ 1;
|
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)
|
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;
|
return sample;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,15 @@ typedef struct _rds_stat
|
|||||||
|
|
||||||
int test;
|
int test;
|
||||||
int cycles_count;
|
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;
|
}rds_stat;
|
||||||
|
|
||||||
void init_rds_encoder(rds_stat * stat,int sample_rate);
|
void init_rds_encoder(rds_stat * stat,int sample_rate);
|
||||||
|
@ -76,10 +76,10 @@ double f_get_next_sample(wave_gen * wg)
|
|||||||
|
|
||||||
wg->phase += ( (2.0 * PI * wg->Frequency) / (double)wg->sample_rate );
|
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);
|
wg->phase -= (2.0 * PI);
|
||||||
|
|
||||||
if(wg->phase < (-2.0 * PI) )
|
if(wg->phase <= (-2.0 * PI) )
|
||||||
wg->phase += (2.0 * PI);
|
wg->phase += (2.0 * PI);
|
||||||
|
|
||||||
return sample;
|
return sample;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#if defined(M_PI)
|
#if defined(M_PI)
|
||||||
#define PI M_PI
|
#define PI M_PI
|
||||||
#else
|
#else
|
||||||
#define PI 3.1415926535897932384626433832795
|
#define PI ((double)(3.1415926535897932384626433832795))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct iq_wave_gen_
|
typedef struct iq_wave_gen_
|
||||||
|
Loading…
Reference in New Issue
Block a user