Bfsk modem isolated
This commit is contained in:
@ -34,6 +34,8 @@ use crate::CARRIER;
|
||||
use crate::DEVIATION;
|
||||
use crate::SAMPLE_PER_SYMBOL;
|
||||
use crate::SAMPLE_RATE;
|
||||
use crate::gaussian;
|
||||
use crate::transmitter::root_raised_cosine;
|
||||
|
||||
pub enum PacketBuilderBitState
|
||||
{
|
||||
@ -171,11 +173,37 @@ impl RadioReceiver
|
||||
let (arg_extract, arg) = Scan::new(iq, Complex::zero(), |state, sample| {
|
||||
let angle: Complex<f32> = sample / *state;
|
||||
*state = sample;
|
||||
angle.arg() * 14.
|
||||
angle.arg()
|
||||
/ DigitalFrequency::from_time_frequency(DEVIATION, SAMPLE_RATE as f64).as_rad()
|
||||
as f32
|
||||
});
|
||||
|
||||
let mut elg_loop = Fir(vec![1. / 20.; 30]);
|
||||
*elg_loop.0.last_mut().unwrap() = 1.;
|
||||
// gaussian fir
|
||||
let fir = Fir((0..SAMPLE_PER_SYMBOL)
|
||||
.map(|x| gaussian(0.3, x as f32 / SAMPLE_PER_SYMBOL as f32))
|
||||
.collect())
|
||||
.normalized();
|
||||
|
||||
// RRC fir
|
||||
let rrc_symbol_count = 4;
|
||||
let rrc_fir_length = SAMPLE_PER_SYMBOL * rrc_symbol_count;
|
||||
let fir = Fir((0..rrc_fir_length)
|
||||
.map(|x| {
|
||||
let centered = oxydsp_dsp::map(
|
||||
x as f32,
|
||||
0.,
|
||||
rrc_fir_length as f32,
|
||||
-(rrc_symbol_count as f32) * 0.5,
|
||||
rrc_symbol_count as f32 * 0.5,
|
||||
);
|
||||
root_raised_cosine(centered, 1., 1.)
|
||||
})
|
||||
.collect())
|
||||
.normalized();
|
||||
|
||||
let (matched_filter, arg) = FirFilter::new(arg, fir);
|
||||
let mut elg_loop = Fir(vec![1. / 30.; 30]);
|
||||
*elg_loop.0.last_mut().unwrap() = 0.3;
|
||||
let symbol_tag = tags.allocate_tag("early late gate symbol");
|
||||
let (elg, arg) = EarlyLateGate::new(arg, elg_loop, SAMPLE_PER_SYMBOL, symbol_tag.clone());
|
||||
|
||||
@ -238,6 +266,7 @@ impl RadioReceiver
|
||||
packet_map,
|
||||
arg_extract,
|
||||
//sig_lowpass,
|
||||
matched_filter,
|
||||
elg,
|
||||
eye_sender,
|
||||
null_sink
|
||||
|
||||
@ -6,6 +6,7 @@ use oxydsp_dsp::blocks::filtering::fir::FirFilter;
|
||||
use oxydsp_dsp::blocks::math::basic::Multiplier;
|
||||
use oxydsp_dsp::blocks::synthesis::Nco;
|
||||
use oxydsp_dsp::blocks::synthesis::OscillatorSource;
|
||||
use oxydsp_dsp::blocks::utilities::adapters::FlatMap;
|
||||
use oxydsp_dsp::blocks::utilities::adapters::Map;
|
||||
use oxydsp_dsp::blocks::utilities::adapters::Repeat;
|
||||
use oxydsp_dsp::blocks::utilities::adapters::Scan;
|
||||
@ -21,6 +22,7 @@ use oxydsp_flowgraph::graph::FlowGraph;
|
||||
use oxydsp_flowgraph::io::In;
|
||||
use oxydsp_flowgraph::io::Out;
|
||||
use rand::random;
|
||||
use std::f32::consts::PI;
|
||||
use std::iter::FusedIterator;
|
||||
use std::net::UdpSocket;
|
||||
use std::ops::BitXor;
|
||||
@ -81,11 +83,27 @@ impl Transmitter
|
||||
});
|
||||
|
||||
// gaussian fir
|
||||
let fir = Fir((0..SAMPLE_PER_SYMBOL)
|
||||
.map(|x| gaussian(0.3, x as f32 / SAMPLE_PER_SYMBOL as f32))
|
||||
.collect());
|
||||
// let fir = Fir((0..SAMPLE_PER_SYMBOL)
|
||||
// .map(|x| gaussian(0.3, x as f32 / SAMPLE_PER_SYMBOL as f32))
|
||||
// .collect());
|
||||
//.normalized();
|
||||
|
||||
// RRC fir
|
||||
let rrc_symbol_count = 4;
|
||||
let rrc_fir_length = SAMPLE_PER_SYMBOL * rrc_symbol_count;
|
||||
let fir = Fir((0..rrc_fir_length)
|
||||
.map(|x| {
|
||||
let centered = oxydsp_dsp::map(
|
||||
x as f32,
|
||||
0.,
|
||||
rrc_fir_length as f32,
|
||||
-(rrc_symbol_count as f32) * 0.5,
|
||||
rrc_symbol_count as f32 * 0.5,
|
||||
);
|
||||
root_raised_cosine(centered, 1., 1.)
|
||||
})
|
||||
.collect());
|
||||
|
||||
let (bit_filter, bits) = FirFilter::new(bits, fir);
|
||||
let (to_freq, freq) = Map::new(bits, move |x| {
|
||||
DigitalFrequency::from_time_frequency(DEVIATION * x as f64, SAMPLE_RATE as f64)
|
||||
@ -95,25 +113,27 @@ impl Transmitter
|
||||
let (frontend, passband) = Multiplier::new(baseband, lo);
|
||||
let (audio_tx, audio_rx) = mpsc::channel::<Complex<f32>>();
|
||||
|
||||
let reverb_length = 20;
|
||||
let reverb_length = 200;
|
||||
let (reverb, passband) = FirFilter::new(
|
||||
passband,
|
||||
Fir((0..reverb_length)
|
||||
.map(|x| (-15. * (x as f32) / (reverb_length as f32)).exp())
|
||||
.map(|x| (-5. * (x as f32) / (reverb_length as f32)).exp())
|
||||
.collect())
|
||||
.normalized(),
|
||||
);
|
||||
|
||||
let (awgn, passband) = Map::new(passband, |x| {
|
||||
x + Complex::<f32>::new(2. * (random::<f32>() - 0.5), 2. * (random::<f32>() - 0.5))
|
||||
* 0.3
|
||||
});
|
||||
|
||||
let (udp_map, passband) = Scan::new(
|
||||
passband,
|
||||
UdpSocket::bind("127.0.0.1:25566").unwrap(),
|
||||
UdpSocket::bind("0.0.0.0:0").unwrap(),
|
||||
|sckt, sample| {
|
||||
std::thread::sleep(Duration::from_micros(20));
|
||||
sckt.send_to(
|
||||
&(sample.re + ((random::<f32>() * 2.) - 1.) * 0.0).to_le_bytes(),
|
||||
"127.0.0.1:25565",
|
||||
)
|
||||
.unwrap();
|
||||
std::thread::sleep(Duration::from_micros(12));
|
||||
sckt.send_to(&(sample.re).to_le_bytes(), "127.0.0.1:25565")
|
||||
.unwrap();
|
||||
sample
|
||||
},
|
||||
);
|
||||
@ -130,6 +150,7 @@ impl Transmitter
|
||||
base_oscillator,
|
||||
local_oscillator,
|
||||
frontend,
|
||||
awgn,
|
||||
tx_sink,
|
||||
];
|
||||
|
||||
@ -178,3 +199,30 @@ impl Transmitter
|
||||
let _ = self.packet_sender.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_raised_cosine(t: f32, beta: f32, ts: f32) -> f32
|
||||
{
|
||||
let eps = 1e-8;
|
||||
|
||||
if t.abs() < eps
|
||||
{
|
||||
// t = 0 special case
|
||||
return (1.0 / ts.sqrt()) * (1.0 + beta * (4.0 / PI - 1.0));
|
||||
}
|
||||
|
||||
if beta > 0.0 && (t.abs() - ts / (4.0 * beta)).abs() < eps
|
||||
{
|
||||
// t = ±T / (4β) special case
|
||||
let term1 = (1.0 + 2.0 / PI) * (PI / (4.0 * beta)).sin();
|
||||
let term2 = (1.0 - 2.0 / PI) * (PI / (4.0 * beta)).cos();
|
||||
return (beta / (ts.sqrt() * 2.0_f32.sqrt())) * (term1 + term2);
|
||||
}
|
||||
|
||||
// General case
|
||||
let numerator = (PI * t * (1.0 - beta) / ts).sin()
|
||||
+ 4.0 * beta * t / ts * (PI * t * (1.0 + beta) / ts).cos();
|
||||
|
||||
let denominator = PI * t * (1.0 - (4.0 * beta * t / ts).powi(2)) / ts;
|
||||
|
||||
(1.0 / ts.sqrt()) * (numerator / denominator)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user