Bfsk modem isolated

This commit is contained in:
2026-03-26 10:44:46 +01:00
parent 4d548a7973
commit cc3ae754ff
14 changed files with 623 additions and 92 deletions

View File

@ -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

View File

@ -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)
}