diff --git a/src/main.rs b/src/main.rs index d19a30e..f3c24ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,13 @@ use std::{ f32::consts::PI, fs::File, i16, - io::{self, stdout, Read, Write}, + io::{self, Read, Write, stdout}, 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,16 +36,23 @@ use cpal::{ use fft::DFTAlgorithm; use nco::Nco; -use eframe::{egui::{self, debug_text::print, decode_animated_image_uri, Color32, Context, Vec2b}, glow::TOP_LEVEL_ARRAY_STRIDE}; -use egui_plot::{self, AxisHints, Bar, BarChart, HLine, Legend, Line, LineStyle, Plot, PlotPoints, VLine}; +use eframe::{ + egui::{self, Color32, Context, Vec2b, debug_text::print, decode_animated_image_uri}, + glow::TOP_LEVEL_ARRAY_STRIDE, +}; +use egui_plot::{ + self, AxisHints, Bar, BarChart, HLine, 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, - fft::{dft::NaiveDFT, FFT}, + fft::{FFT, dft::NaiveDFT}, filtering::{ - dc_block::DCBlocker, fir::FIRFilter, impulse_response::design::{self, frequency_response, ir_from_transfer_function} + dc_block::DCBlocker, + fir::FIRFilter, + impulse_response::design::{self, frequency_response, ir_from_transfer_function}, }, iq::IQSampler, units::frequency::{self, hz_to_rad_per_sample}, @@ -133,8 +142,7 @@ fn main() { } // Early late gate -struct ELGate -{ +struct ELGate { samples_per_symbol: f32, buffer: VecDeque, // Store baseband, matched filtered samples, @@ -144,35 +152,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<(f32, Vec)> - { - self.buffer.push_front(sample); + pub fn next_eye(&mut self, sample: f32) -> Option<(f32, 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]; @@ -183,8 +189,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(); } @@ -193,9 +198,7 @@ impl ELGate self.next_sample = self.samples_per_symbol - self.loop_filter.next_real(error); Some((sample, Vec::from(self.buffer.clone()))) - } - else - { + } else { None } } @@ -255,13 +258,10 @@ 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); let mut dc_blocker = DCBlocker::new(0.999); - + // Timing recovery let mut preamble_count = 0; let mut bit_index = 0; @@ -273,49 +273,40 @@ fn demodulator( let neg_energy = matched_filter_neg.next(iq); let pos_energy = matched_filter_pos.next(iq); - let matched = matched_filter.next_real(dc_blocker.next_real(pos_energy.mag() - neg_energy.mag())); + let matched = + matched_filter.next_real(dc_blocker.next_real(pos_energy.mag() - neg_energy.mag())); - if let Some((elg_sample, eye)) = elg.next_eye(matched) - { + if let Some((elg_sample, eye)) = elg.next_eye(matched) { let _ = eye_sender.send(eye); ctx.request_repaint(); //last >>= 1; //last |= (!bit as u8) << 7; let bit = elg_sample > 0.; - if elg_sample*elg_sample > 0.005 - { + if elg_sample * elg_sample > 0.005 { last >>= 1; last |= (bit as u8) << 7; //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 { print!(" -- EOT"); println!(); preamble_count = 0; bit_index = 0; last = 0; - } - else - { + } else { print!("{}", last as char); bit_index = 0; let _ = stdout().flush(); } } - } - else if last == 0xD8 - { + } else if last == 0xD8 { preamble_count += 1; - if preamble_count == 2 - { + if preamble_count == 2 { println!("Incoming: "); } } @@ -357,9 +348,8 @@ impl eframe::App for EguiApp { while self.eyes.len() > max_eyes { self.eyes.pop_front(); } - - let axis_hints = AxisHints::new_x() - .min_thickness(2.); + + let axis_hints = AxisHints::new_x().min_thickness(2.); Plot::new("Eye") .legend(Legend::default()) @@ -490,23 +480,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); @@ -518,37 +514,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();