Switched to gfsk
This commit is contained in:
96
src/main.rs
96
src/main.rs
@ -108,71 +108,51 @@ impl SampleSender for WavSampleSender {
|
||||
}
|
||||
|
||||
struct FSKReceiver {
|
||||
pos_correllator: FIRFilter,
|
||||
neg_correllator: FIRFilter,
|
||||
eye_sender: Sender<Vec<f32>>,
|
||||
matched_lowpass: FIRFilter,
|
||||
phase_lowpass: FIRFilter,
|
||||
elg: ELGate,
|
||||
dc_block: DCBlocker,
|
||||
last_byte: u8,
|
||||
frame_constructor: FrameConstructor,
|
||||
bit_count: Option<u32>,
|
||||
last_sample: Complex32,
|
||||
}
|
||||
|
||||
impl FSKReceiver {
|
||||
fn new(eye_sender: Sender<Vec<f32>>) -> Self {
|
||||
let samples_per_symbol = (SAMPLE_RATE as f32) / (BAUD_RATE as f32);
|
||||
|
||||
let correllator_length = samples_per_symbol as usize;
|
||||
let mut pos_nco = Nco::new(hz_to_rad_per_sample(DEVIATION, SAMPLE_RATE as f32));
|
||||
let mut neg_nco = Nco::new(hz_to_rad_per_sample(-DEVIATION, SAMPLE_RATE as f32));
|
||||
let pos_ir = (0..correllator_length).map(|i| {
|
||||
pos_nco.step();
|
||||
pos_nco.cexp() * windows::blackmann(i as f32 / correllator_length as f32)
|
||||
});
|
||||
let neg_ir = (0..correllator_length).map(|i| {
|
||||
neg_nco.step();
|
||||
neg_nco.cexp() * windows::blackmann(i as f32 / correllator_length as f32)
|
||||
});
|
||||
let mut pos_correllator = FIRFilter::new(&pos_ir.collect::<Vec<_>>());
|
||||
let mut neg_correllator = FIRFilter::new(&neg_ir.collect::<Vec<_>>());
|
||||
pos_correllator.normalize_freq(hz_to_rad_per_sample(DEVIATION, SAMPLE_RATE as f32));
|
||||
neg_correllator.normalize_freq(hz_to_rad_per_sample(-DEVIATION, SAMPLE_RATE as f32));
|
||||
|
||||
let mut matched_lowpass = FIRFilter::new(&vec![
|
||||
let mut phase_lowpass = FIRFilter::new(&vec![
|
||||
Complex32::new(1., 0.);
|
||||
samples_per_symbol as usize / 2
|
||||
]);
|
||||
matched_lowpass.normalize_freq(hz_to_rad_per_sample(DEVIATION, SAMPLE_RATE as f32));
|
||||
phase_lowpass.normalize_dc();
|
||||
//let mut dc_block = DCBlocker::new(0.999);
|
||||
let mut dc_block = DCBlocker::new(1.);
|
||||
//let mut dc_block = DCBlocker::new(1.);
|
||||
|
||||
let loop_i = 0.03;
|
||||
let loop_p = 0.1;
|
||||
let mut loop_ir = vec![Complex32::new(loop_i, 0.); samples_per_symbol as usize / 2];
|
||||
loop_ir.push(Complex32::new(loop_p, 0.));
|
||||
let mut elg = ELGate::new(samples_per_symbol, FIRFilter::new(&loop_ir));
|
||||
let elg = ELGate::new(samples_per_symbol, FIRFilter::new(&loop_ir));
|
||||
Self {
|
||||
//iq_sampler: IQSampler::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32)),
|
||||
pos_correllator,
|
||||
neg_correllator,
|
||||
matched_lowpass,
|
||||
dc_block,
|
||||
phase_lowpass,
|
||||
elg,
|
||||
last_byte: 0x00u8,
|
||||
frame_constructor: FrameConstructor::new(),
|
||||
bit_count: None,
|
||||
eye_sender,
|
||||
last_sample: Complex32::new(1., 0.),
|
||||
}
|
||||
}
|
||||
|
||||
async fn receive(&mut self, iq: Complex32) -> Result<Option<Frame>, FrameConstructionError> {
|
||||
// Frame reconstruction
|
||||
let matched =
|
||||
self.matched_lowpass.next_real(self.dc_block.next_real(
|
||||
self.pos_correllator.next(iq).mag() - self.neg_correllator.next(iq).mag(),
|
||||
));
|
||||
if let Some((bit_sample, eye)) = self.elg.next_eye(matched) {
|
||||
let dphi = self
|
||||
.phase_lowpass
|
||||
.next_real((self.last_sample.conj() * iq).arg());
|
||||
self.last_sample = iq;
|
||||
if let Some((bit_sample, eye)) = self.elg.next_eye(dphi) {
|
||||
let _ = self.eye_sender.send(eye).await;
|
||||
self.last_byte >>= 1;
|
||||
self.last_byte |= ((bit_sample > 0.) as u8) << 7;
|
||||
@ -321,19 +301,47 @@ impl Transceiver {
|
||||
|
||||
pub async fn transmit(frame: Frame, samples_sender: &mut Sender<Vec<f32>>) {
|
||||
let bytes = frame.bytes();
|
||||
let mut bit_stream = bytes.iter().flat_map(|x| byte_to_bits(*x));
|
||||
let modulator = BFSKMod::new(
|
||||
(SAMPLE_RATE as f32 / BAUD_RATE as f32).round() as u32,
|
||||
hz_to_rad_per_sample(DEVIATION, SAMPLE_RATE as f32),
|
||||
&mut bit_stream,
|
||||
);
|
||||
let data = bytes
|
||||
.iter()
|
||||
.flat_map(|x| byte_to_bits(*x))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let up_lo = Nco::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32));
|
||||
let mut samples = vec![];
|
||||
for (m, up) in modulator.zip(up_lo) {
|
||||
let sample = m * up;
|
||||
samples.push(sample.re);
|
||||
let sample_per_symbols = SAMPLE_RATE / BAUD_RATE;
|
||||
let bitstream = (0..(bytes.len() * 8 * sample_per_symbols as usize)).map(|i| {
|
||||
if data[i / sample_per_symbols as usize] {
|
||||
1.
|
||||
} else {
|
||||
-1.
|
||||
}
|
||||
});
|
||||
|
||||
// Synthesise impulse response
|
||||
let mut impulse_response =
|
||||
vec![Complex32::zero(); sample_per_symbols as usize].into_boxed_slice();
|
||||
for (i, x) in impulse_response.iter_mut().enumerate() {
|
||||
*x = Complex32::new(
|
||||
windows::gaussian(0.3, i as f32 / sample_per_symbols as f32),
|
||||
0.,
|
||||
);
|
||||
}
|
||||
|
||||
let mut gaussian_filter = FIRFilter::new(&impulse_response);
|
||||
gaussian_filter.normalize_dc();
|
||||
let filtered_bitstream = bitstream.map(|x| gaussian_filter.next_real(x));
|
||||
|
||||
let mut nco = Nco::new(0.);
|
||||
let mut lo = Nco::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32));
|
||||
|
||||
// Generate passband
|
||||
let samples = filtered_bitstream
|
||||
.map(|f| {
|
||||
nco.set_frequency(hz_to_rad_per_sample(f * DEVIATION, SAMPLE_RATE as f32));
|
||||
nco.step_n(1);
|
||||
lo.step_n(1);
|
||||
(nco.cexp() * lo.cexp()).re
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let len = samples.len();
|
||||
samples_sender.send(samples).await.unwrap();
|
||||
tokio::time::sleep(Duration::from_secs_f32(len as f32 / SAMPLE_RATE as f32)).await;
|
||||
|
||||
@ -10,18 +10,20 @@ pub fn bartlett(t: f32) -> f32 {
|
||||
if t < 0.5 { 2. * t } else { 2. - 2. * t }
|
||||
}
|
||||
|
||||
pub fn hann(t: f32) -> f32
|
||||
{
|
||||
pub fn hann(t: f32) -> f32 {
|
||||
0.5 - 0.5 * (2. * PI * t).cos()
|
||||
}
|
||||
|
||||
pub fn hamming(t: f32) -> f32
|
||||
{
|
||||
pub fn hamming(t: f32) -> f32 {
|
||||
0.54 - 0.46 * (2. * PI * t).cos()
|
||||
}
|
||||
|
||||
pub fn blackmann(t: f32) -> f32
|
||||
{
|
||||
pub fn blackmann(t: f32) -> f32 {
|
||||
let x = 2. * PI * t;
|
||||
0.45 - 0.5 * x.cos() + 0.08 * (2. * x).cos()
|
||||
}
|
||||
|
||||
pub fn gaussian(sigma: f32, t: f32) -> f32 {
|
||||
let sq = (t - 0.5) / sigma;
|
||||
(-sq * sq).exp()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user