Starting fresh on dummy channel
This commit is contained in:
273
src/main.rs
273
src/main.rs
@ -13,8 +13,17 @@ mod windows;
|
||||
|
||||
use egui_plot::{Legend, Line, Plot};
|
||||
use hound::WavWriter;
|
||||
use rand::{rand_core::le, seq::index::sample, Rng};
|
||||
use std::{cell::{Cell, RefCell}, collections::VecDeque, env::{self, args}, fs::File, io::{stdout, BufWriter, Sink, Write}, ops::DerefMut, sync::Arc, time::Duration};
|
||||
use rand::{Rng, rand_core::le, seq::index::sample};
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::VecDeque,
|
||||
env::{self, args},
|
||||
fs::File,
|
||||
io::{BufWriter, Sink, Write, stdout},
|
||||
ops::DerefMut,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::{join, net::UdpSocket, select, time::timeout};
|
||||
|
||||
use crate::{
|
||||
@ -26,7 +35,8 @@ use crate::{
|
||||
ted::elg::ELGate,
|
||||
units::frequency::hz_to_rad_per_sample,
|
||||
};
|
||||
use eframe::{egui::{self, mutex::{Mutex, RwLock}, panel::Side, CentralPanel, Color32, SidePanel}, glow::SAMPLE_MASK_VALUE};
|
||||
use eframe::egui::{self, CentralPanel, Color32};
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::mpsc::{Receiver, Sender, channel};
|
||||
|
||||
const BAUD_RATE: u32 = 1000;
|
||||
@ -36,108 +46,23 @@ const SAMPLE_RATE: u32 = 48000;
|
||||
const CENTER_FREQ: f32 = 1700.;
|
||||
const DEVIATION: f32 = 500.;
|
||||
|
||||
|
||||
pub trait SampleSender {
|
||||
async fn open_link(&mut self);
|
||||
async fn send_sample(&mut self, sample: f32);
|
||||
async fn close_link(&mut self);
|
||||
}
|
||||
|
||||
pub struct ChannelSampleSender
|
||||
{
|
||||
pub sender: Sender<f32>,
|
||||
pub open: Arc<RwLock<bool>>,
|
||||
struct WavSampleSender {
|
||||
writer: Option<WavWriter<BufWriter<File>>>,
|
||||
}
|
||||
|
||||
impl SampleSender for ChannelSampleSender
|
||||
{
|
||||
async fn open_link(&mut self)
|
||||
{
|
||||
*self.open.write() = true;
|
||||
}
|
||||
|
||||
async fn send_sample(&mut self, sample: f32) {
|
||||
self.sender.send(sample).await.unwrap();
|
||||
}
|
||||
|
||||
async fn close_link(&mut self)
|
||||
{
|
||||
*self.open.write() = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn create_dummy_channel() -> ((Receiver<f32>, ChannelSampleSender), (Receiver<f32>, ChannelSampleSender))
|
||||
{
|
||||
let a_open = Arc::new(RwLock::new(false));
|
||||
let b_open = Arc::new(RwLock::new(false));
|
||||
let a_open_cln = a_open.clone();
|
||||
let b_open_cln = b_open.clone();
|
||||
|
||||
// Up link
|
||||
let (a_up_tx, mut a_up_rx) = channel::<f32>(1024);
|
||||
let (b_up_tx, mut b_up_rx) = channel::<f32>(1024);
|
||||
|
||||
// Down link
|
||||
let (a_down_tx, a_down_rx) = channel::<f32>(1024);
|
||||
let (b_down_tx, b_down_rx) = channel::<f32>(1024);
|
||||
|
||||
tokio::spawn(async move {
|
||||
loop
|
||||
{
|
||||
let sample = select!
|
||||
{
|
||||
Some(x) = a_up_rx.recv() => x,
|
||||
Some(x) = b_up_rx.recv() => x
|
||||
};
|
||||
|
||||
if !(*a_open_cln.read())
|
||||
{
|
||||
a_down_tx.send(sample).await.unwrap();
|
||||
}
|
||||
|
||||
if !(*b_open_cln.read())
|
||||
{
|
||||
b_down_tx.send(sample).await.unwrap();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
(
|
||||
(
|
||||
a_down_rx,
|
||||
ChannelSampleSender
|
||||
{
|
||||
open: a_open,
|
||||
sender: a_up_tx
|
||||
}
|
||||
),
|
||||
(
|
||||
b_down_rx,
|
||||
ChannelSampleSender
|
||||
{
|
||||
open: b_open,
|
||||
sender: b_up_tx
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
struct WavSampleSender
|
||||
{
|
||||
writer: Option<WavWriter<BufWriter<File>>>
|
||||
}
|
||||
|
||||
impl Default for WavSampleSender
|
||||
{
|
||||
impl Default for WavSampleSender {
|
||||
fn default() -> Self {
|
||||
Self { writer: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl SampleSender for WavSampleSender
|
||||
{
|
||||
impl SampleSender for WavSampleSender {
|
||||
async fn open_link(&mut self) {
|
||||
let spec = hound::WavSpec {
|
||||
channels: 1,
|
||||
@ -149,9 +74,12 @@ impl SampleSender for WavSampleSender
|
||||
}
|
||||
|
||||
async fn send_sample(&mut self, sample: f32) {
|
||||
|
||||
let out_sample = (sample * i16::MAX as f32) as i16;
|
||||
self.writer.as_mut().unwrap().write_sample(out_sample).unwrap();
|
||||
let out_sample = (sample * i16::MAX as f32) as i16;
|
||||
self.writer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.write_sample(out_sample)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn close_link(&mut self) {
|
||||
@ -167,7 +95,7 @@ impl Transceiver {
|
||||
mut tx_stream: Receiver<Vec<u8>>,
|
||||
mut rx_stream: Sender<Vec<u8>>,
|
||||
mut sample_sender: T,
|
||||
mut eye_sender: Sender<Vec<f32>>
|
||||
mut eye_sender: Sender<Vec<f32>>,
|
||||
) {
|
||||
let mut resend: Option<Vec<u8>> = None;
|
||||
loop {
|
||||
@ -179,6 +107,8 @@ impl Transceiver {
|
||||
{
|
||||
x = Self::receive(&mut sample_stream, &mut eye_sender) =>
|
||||
{
|
||||
// Flush channel
|
||||
while sample_stream.recv().await.is_some() {};
|
||||
match x
|
||||
{
|
||||
Err(()) => {continue;},
|
||||
@ -188,7 +118,8 @@ impl Transceiver {
|
||||
}
|
||||
Ok(Frame::Data(data)) =>
|
||||
{
|
||||
rx_stream.send(data).await.unwrap();
|
||||
let _ = rx_stream.send(data).await;
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
Self::transmit(Frame::Ack, &mut sample_sender).await;
|
||||
}
|
||||
}
|
||||
@ -214,7 +145,6 @@ impl Transceiver {
|
||||
{
|
||||
if let Some(data) = data_opt
|
||||
{
|
||||
println!("Sending data");
|
||||
Self::transmit(Frame::Data(data.clone()), &mut sample_sender).await;
|
||||
resend = Some(data);
|
||||
}
|
||||
@ -262,7 +192,10 @@ impl Transceiver {
|
||||
samples_sender.close_link().await;
|
||||
}
|
||||
|
||||
async fn receive(sample_stream: &mut Receiver<f32>, eye_sender: &mut Sender<Vec<f32>>) -> Result<Frame, FrameConstructionError> {
|
||||
async fn receive(
|
||||
sample_stream: &mut Receiver<f32>,
|
||||
eye_sender: &mut Sender<Vec<f32>>,
|
||||
) -> Result<Frame, FrameConstructionError> {
|
||||
let mut iq_sampler = IQSampler::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32));
|
||||
|
||||
let samples_per_symbol = (SAMPLE_RATE as f32) / (BAUD_RATE as f32);
|
||||
@ -283,8 +216,10 @@ impl Transceiver {
|
||||
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![Complex32::new(1., 0.); samples_per_symbol as usize / 2]);
|
||||
let mut matched_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));
|
||||
//let mut dc_block = DCBlocker::new(0.999);
|
||||
let mut dc_block = DCBlocker::new(1.);
|
||||
@ -292,7 +227,7 @@ impl Transceiver {
|
||||
let loop_i = 0.0;
|
||||
let loop_p = 0.1;
|
||||
let mut loop_ir = vec![Complex32::new(loop_i, 0.); samples_per_symbol as usize];
|
||||
loop_ir.push(Complex32::new(loop_p, 0.));
|
||||
loop_ir.push(Complex32::new(loop_p, 0.));
|
||||
let mut elg = ELGate::new(samples_per_symbol, FIRFilter::new(&loop_ir));
|
||||
|
||||
// Frame reconstruction
|
||||
@ -302,11 +237,10 @@ impl Transceiver {
|
||||
while let Some(sample) = sample_stream.recv().await {
|
||||
let iq = iq_sampler.sample(sample);
|
||||
let matched =
|
||||
matched_lowpass.next_real(
|
||||
dc_block.next_real(
|
||||
pos_correllator.next(iq).mag() - neg_correllator.next(iq).mag(),
|
||||
)
|
||||
);
|
||||
matched_lowpass
|
||||
.next_real(dc_block.next_real(
|
||||
pos_correllator.next(iq).mag() - neg_correllator.next(iq).mag(),
|
||||
));
|
||||
if let Some((bit_sample, eye)) = elg.next_eye(matched) {
|
||||
let _ = eye_sender.send(eye).await;
|
||||
last_byte >>= 1;
|
||||
@ -315,7 +249,8 @@ impl Transceiver {
|
||||
//last_byte |= ((bit_sample < 0.) as u8);
|
||||
bit_count = bit_count.map(|x| x + 1);
|
||||
|
||||
if let None = bit_count && last_byte == 0xD8
|
||||
if let None = bit_count
|
||||
&& last_byte == 0xD8
|
||||
{
|
||||
// Potential frame starts
|
||||
last_byte = 0;
|
||||
@ -362,7 +297,7 @@ pub struct FrameConstructor {
|
||||
frame: Vec<u8>,
|
||||
frame_countdown: Option<u16>,
|
||||
checksum: u8,
|
||||
started: bool
|
||||
started: bool,
|
||||
}
|
||||
|
||||
impl FrameConstructor {
|
||||
@ -371,7 +306,7 @@ impl FrameConstructor {
|
||||
frame: Vec::new(),
|
||||
frame_countdown: None,
|
||||
checksum: 0u8,
|
||||
started: false
|
||||
started: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,12 +317,12 @@ impl FrameConstructor {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if self.frame.is_empty() && byte == 0xC4 && !self.started{
|
||||
if self.frame.is_empty() && byte == 0xC4 && !self.started {
|
||||
self.started = true;
|
||||
return Ok(Some(Frame::Ack));
|
||||
}
|
||||
|
||||
if self.frame.is_empty() && byte == 0x4C && !self.started{
|
||||
if self.frame.is_empty() && byte == 0x4C && !self.started {
|
||||
self.started = true;
|
||||
return Ok(None);
|
||||
}
|
||||
@ -465,7 +400,7 @@ impl Frame {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
//Transceiver::transmit(Frame::Data("Skibditoilet".repeat(100).bytes().collect::<Vec<_>>()), &mut WavSampleSender{}).await;
|
||||
Transceiver::transmit(Frame::Ack, &mut WavSampleSender::default()).await;
|
||||
//Transceiver::transmit(Frame::Ack, &mut WavSampleSender::default()).await;
|
||||
//return;
|
||||
|
||||
let native_options = eframe::NativeOptions::default();
|
||||
@ -488,132 +423,26 @@ impl SampleSender for DummySampleSender {
|
||||
|
||||
struct EguiApp {
|
||||
eye_receiver_a: Receiver<Vec<f32>>,
|
||||
eye_receiver_b: Receiver<Vec<f32>>,
|
||||
eyes_a: VecDeque<Vec<f32>>,
|
||||
eyes_b: VecDeque<Vec<f32>>,
|
||||
up_a_tx: Sender<Vec<u8>>
|
||||
}
|
||||
impl EguiApp {
|
||||
fn new(_cc: &eframe::CreationContext<'_>) -> Self {
|
||||
let (eye_a_tx, mut eye_a_rx) = channel::<Vec<f32>>(1024);
|
||||
let (eye_b_tx, mut eye_b_rx) = channel::<Vec<f32>>(1024);
|
||||
|
||||
let (eye_a_red_tx, eye_a_red_rx) = channel::<Vec<f32>>(1024);
|
||||
let (eye_b_red_tx, eye_b_red_rx) = channel::<Vec<f32>>(1024);
|
||||
let ctx = _cc.egui_ctx.clone();
|
||||
tokio::spawn(async move
|
||||
{
|
||||
loop
|
||||
{
|
||||
let _ = select!
|
||||
{
|
||||
Some(eye) = eye_a_rx.recv() => {eye_a_red_tx.send(eye).await.unwrap()}
|
||||
Some(eye) = eye_b_rx.recv() => {eye_b_red_tx.send(eye).await.unwrap()}
|
||||
};
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let ((sample_down_a, sample_up_a), (sample_down_b, sample_up_b)) = create_dummy_channel();
|
||||
let (up_a_tx, up_a_rx) = channel::<Vec<u8>>(1024);
|
||||
let (down_a_tx, down_a_rx) = channel::<Vec<u8>>(1024);
|
||||
|
||||
let (up_b_tx, up_b_rx) = channel::<Vec<u8>>(1024);
|
||||
let (down_b_tx, down_b_rx) = channel::<Vec<u8>>(1024);
|
||||
|
||||
tokio::spawn(Transceiver::start(sample_down_a, up_a_rx, down_a_tx, sample_up_a, eye_a_tx));
|
||||
tokio::spawn(Transceiver::start(sample_down_b, up_b_rx, down_b_tx, sample_up_b, eye_b_tx));
|
||||
|
||||
// tokio::spawn(async move {
|
||||
// loop
|
||||
// {
|
||||
// let bytes = receive_rx.recv().await.unwrap();
|
||||
// let str = String::from_utf8(bytes).unwrap();
|
||||
// println!("{}", str);
|
||||
//
|
||||
// }
|
||||
// });
|
||||
//
|
||||
|
||||
|
||||
Self {
|
||||
eye_receiver_a: eye_a_red_rx,
|
||||
eye_receiver_b: eye_b_red_rx,
|
||||
eyes_a: VecDeque::with_capacity(100),
|
||||
eyes_b: VecDeque::with_capacity(100),
|
||||
|
||||
up_a_tx,
|
||||
}
|
||||
EguiApp {}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for EguiApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default()
|
||||
.show(ctx, |ui| {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
let max_eyes = 100;
|
||||
|
||||
while let Ok(eye) = self.eye_receiver_a.try_recv() {
|
||||
self.eyes_a.push_back(eye);
|
||||
}
|
||||
|
||||
while let Ok(eye) = self.eye_receiver_b.try_recv() {
|
||||
self.eyes_b.push_back(eye);
|
||||
}
|
||||
|
||||
while self.eyes_a.len() > max_eyes {
|
||||
self.eyes_a.pop_front();
|
||||
}
|
||||
|
||||
while self.eyes_b.len() > max_eyes {
|
||||
self.eyes_b.pop_front();
|
||||
}
|
||||
|
||||
ui.columns(2, |uis| {
|
||||
Plot::new("EyeA")
|
||||
.legend(Legend::default())
|
||||
.show(&mut uis[0], |plot_ui| {
|
||||
//plot_ui.set_auto_bounds(Vec2b { x: false, y: false });
|
||||
for eye in self.eyes_a.iter() {
|
||||
let line = Line::new(
|
||||
"EyeA",
|
||||
eye.iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| [i as f64, *x as f64])
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.color(Color32::LIGHT_GREEN);
|
||||
plot_ui.line(line);
|
||||
}
|
||||
});
|
||||
|
||||
if uis[0].button("Start").clicked()
|
||||
{
|
||||
let snd = self.up_a_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
let _ = snd.send("Skibditoilet".repeat(100).as_bytes().to_vec()).await;
|
||||
});
|
||||
}
|
||||
|
||||
Plot::new("EyeB")
|
||||
.legend(Legend::default())
|
||||
.show(&mut uis[1], |plot_ui| {
|
||||
//plot_ui.set_auto_bounds(Vec2b { x: false, y: false });
|
||||
for eye in self.eyes_b.iter() {
|
||||
let line = Line::new(
|
||||
"EyeB",
|
||||
eye.iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| [i as f64, *x as f64])
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.color(Color32::LIGHT_GREEN);
|
||||
plot_ui.line(line);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user