diff --git a/src/main.rs b/src/main.rs index 7629344..09324d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,9 @@ use std::{ ops::{Add, Div, Mul, Sub}, os::unix::thread, sync::{ - atomic::{AtomicU32, Ordering}, mpsc::{self, channel, sync_channel, Receiver, Sender, TryRecvError}, Arc + Arc, + atomic::{AtomicU32, Ordering}, + mpsc::{self, Receiver, Sender, TryRecvError, channel, sync_channel}, }, time::Duration, }; @@ -34,10 +36,10 @@ use cpal::{ use fft::DFTAlgorithm; use nco::Nco; -use eframe::egui::{self, debug_text::print, decode_animated_image_uri, Color32, Context, Vec2b}; +use eframe::egui::{self, Color32, Context, Vec2b, debug_text::print, decode_animated_image_uri}; use egui_plot::{self, Bar, BarChart, Legend, Line, LineStyle, Plot, PlotPoints, VLine}; use plotters::style::Color; -use rand::{seq::index::sample, Rng}; +use rand::{Rng, seq::index::sample}; use crate::{ bfsk::BFSKDem, @@ -57,7 +59,7 @@ where { ((input - in_min.clone()) / (in_max - in_min)) * (out_max - out_min.clone()) + out_min } -const BAUD_RATE: u32 = 1000; +const BAUD_RATE: u32 = 1200; fn main() { modulate(); @@ -134,8 +136,7 @@ fn main() { } // Early late gate -struct ELGate -{ +struct ELGate { samples_per_symbol: f32, buffer: VecDeque, // Store baseband, matched filtered samples, @@ -145,35 +146,33 @@ struct ELGate current_position: f32, } -impl ELGate -{ - pub fn new(samples_per_symbol: f32, loop_filter: FIRFilter) -> Self - { - Self - { +impl ELGate { + pub fn new(samples_per_symbol: f32, loop_filter: FIRFilter) -> Self { + Self { samples_per_symbol, loop_filter, buffer: VecDeque::with_capacity(2 * samples_per_symbol.ceil() as usize), delta: 0.5, next_sample: samples_per_symbol, - current_position: 0. + current_position: 0., } } - pub fn next(&mut self, sample: f32) -> Option - { + pub fn next(&mut self, sample: f32) -> Option { Some(self.next_eye(sample)?.0) // Ignore eye } - pub fn next_eye(&mut self, sample: f32) -> Option<(bool, Vec)> - { - self.buffer.push_front(sample); + pub fn next_eye(&mut self, sample: f32) -> Option<(bool, Vec)> { + self.buffer.push_front(sample); self.current_position += 1.; - if self.current_position >= self.next_sample - { + if self.current_position >= self.next_sample { // Sample center, early late - let early_id = (self.samples_per_symbol / 2. + self.samples_per_symbol * self.delta).floor().min(self.buffer.len() as f32 - 1.) as usize; - let late_id = (self.samples_per_symbol / 2. - self.samples_per_symbol * self.delta).floor().max(0.) as usize; + let early_id = (self.samples_per_symbol / 2. + self.samples_per_symbol * self.delta) + .floor() + .min(self.buffer.len() as f32 - 1.) as usize; + let late_id = (self.samples_per_symbol / 2. - self.samples_per_symbol * self.delta) + .floor() + .max(0.) as usize; let sample_id = (self.samples_per_symbol / 2.) as usize; let early_sample = self.buffer[early_id]; @@ -184,8 +183,7 @@ impl ELGate // Remove until only current sample is in buffer (the next sample might need data from // current sample if error advances sample position) - while self.buffer.len() > self.samples_per_symbol as usize - { + while self.buffer.len() > self.samples_per_symbol as usize { let _ = self.buffer.pop_back(); } @@ -194,9 +192,7 @@ impl ELGate self.next_sample = self.samples_per_symbol - self.loop_filter.next_real(error); Some((sample > 0., Vec::from(self.buffer.clone()))) - } - else - { + } else { None } } @@ -256,11 +252,8 @@ fn demodulator( let mut loop_filter = FIRFilter::new(&loop_filter_ir); //loop_filter.normalize_sum(); - let mut elg = ELGate::new( - sample_per_symbol as f32, - loop_filter - ); - + let mut elg = ELGate::new(sample_per_symbol as f32, loop_filter); + // Timing recovery let mut preamble_count = 0; let mut bit_index = 0; @@ -274,33 +267,26 @@ fn demodulator( let matched = matched_filter.next_real(pos_energy.mag() - neg_energy.mag()); - if let Some((bit, eye)) = elg.next_eye(matched) - { + if let Some((bit, eye)) = elg.next_eye(matched) { let _ = eye_sender.send(eye); ctx.request_repaint(); last <<= 1; last |= bit as u8; - if preamble_count >= 2 - { + if preamble_count >= 2 { bit_index += 1; - if bit_index == 8 - { - if last == 4 - { + if bit_index == 8 { + if last == 4 { println!(); preamble_count = 0; - } - else - { + } else { print!("{}", last as char); bit_index = 0; } } } - if last == 0xD8 - { + if last == 0xD8 { preamble_count += 1; } } @@ -467,23 +453,29 @@ fn modulate() { let device = host.default_output_device().unwrap(); let mut supported_configs_range = device.supported_output_configs().unwrap(); let supported_config = supported_configs_range - .find(|config| config.sample_format() == cpal::SampleFormat::F32 - && config.min_sample_rate().0 <= 48000 - && config.max_sample_rate().0 >= 48000) + .find(|config| { + config.sample_format() == cpal::SampleFormat::F32 + && config.min_sample_rate().0 <= 48000 + && config.max_sample_rate().0 >= 48000 + }) .expect("Device does not support 48kHz f32 output"); - let config = supported_config.with_sample_rate(cpal::SampleRate(48_000)).config(); + let config = supported_config + .with_sample_rate(cpal::SampleRate(48_000)) + .config(); - - loop - { + loop { let mut buffer = String::new(); let stdin = io::stdin(); // We get `Stdin` here. stdin.read_line(&mut buffer).unwrap(); + for c in buffer.bytes() { + print!("{}", c as char); + } + println!(); + // Construct payload - let mut bitstream = - std::iter::repeat_n(0b01010101u8, 32) - .chain(std::iter::repeat_n(0b11011000, 1)) + let mut bitstream = std::iter::repeat_n(0b01010101u8, 64) + .chain(std::iter::repeat_n(0xD8, 2)) .chain(buffer.bytes()) .chain(std::iter::repeat_n(4u8, 32)) .flat_map(byte_to_bits); @@ -495,37 +487,37 @@ fn modulate() { ); let mut lo = Nco::new(units::frequency::hz_to_rad_per_sample( - frequency, - sample_rate as f32, + frequency, + sample_rate as f32, )); // To send - let stream = modulator.zip(lo) + let stream = modulator + .zip(lo) .map(|(s, up)| (s * up).re) .collect::>(); let sample_clock = Arc::new(AtomicU32::new(0)); let (tx, rx) = channel::<()>(); - let stream = device.build_output_stream( - &config, - move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { - for d in data.iter_mut() - { - if sample_clock.load(Ordering::Relaxed) as usize == stream.len() - { - tx.send(()).unwrap(); - break; + let stream = device + .build_output_stream( + &config, + move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { + for d in data.iter_mut() { + if sample_clock.load(Ordering::Relaxed) as usize == stream.len() { + tx.send(()).unwrap(); + break; + } + *d = stream[sample_clock.fetch_add(1, Ordering::Relaxed) as usize] } - *d = stream[sample_clock.fetch_add(1, Ordering::Relaxed) as usize] - } - - }, - move |err| { - eprintln!("Stream error: {}", err); - }, - None - ).unwrap(); + }, + move |err| { + eprintln!("Stream error: {}", err); + }, + None, + ) + .unwrap(); stream.play().unwrap(); let _ = rx.recv();