Simple 2FSK

This commit is contained in:
2026-03-17 17:34:42 +01:00
parent 520d97726f
commit 3cdc0e613a
14 changed files with 4787 additions and 31 deletions

View File

@ -1,4 +1,4 @@
use std::ops::Add;
use std::ops::{Add, Mul};
use oxydsp_flowgraph::{
BlockIO,
@ -59,3 +59,57 @@ where
BlockResult::Ok
}
}
#[derive(BlockIO)]
pub struct Multiplier<Ia, Ib, O>
where
Ia: Mul<Ib, Output = O> + 'static,
Ib: 'static,
O: 'static,
{
#[input]
input_a: In<Ia>,
#[input]
input_b: In<Ib>,
#[output]
output: Out<O>,
}
impl<Ia, Ib, O> Multiplier<Ia, Ib, O>
where
Ia: Mul<Ib, Output = O> + 'static,
Ib: 'static,
O: 'static,
{
pub fn new(input_a: In<Ia>, input_b: In<Ib>) -> (Self, In<O>)
{
let (output, added) = stream();
(
Self {
input_a,
input_b,
output,
},
added,
)
}
}
impl<Ia, Ib, O> Block for Multiplier<Ia, Ib, O>
where
Ia: Mul<Ib, Output = O> + 'static,
Ib: 'static,
O: 'static,
{
fn work(&mut self) -> BlockResult
{
self.output.push_iter(
(&mut self.input_a, &mut self.input_b)
.pop_iter()
.map(|(a, b)| a * b),
);
BlockResult::Ok
}
}

View File

@ -50,7 +50,15 @@ pub struct Nco<T: Float + From<f32> + 'static>
impl<T: Float + From<f32> + 'static> Nco<T>
{
pub fn new(
pub fn new(input: In<DigitalFrequency>) -> (Self, In<Complex<T>>)
{
Self::with(
input,
crate::synthesis::oscillator::Nco::<T>::new(DigitalFrequency(0)),
)
}
pub fn with(
input: In<DigitalFrequency>,
nco: crate::synthesis::oscillator::Nco<T>,
) -> (Self, In<Complex<T>>)

View File

@ -1,2 +1,3 @@
pub mod adapters;
pub mod channels;
pub mod iter;

View File

@ -1 +1,97 @@
use oxydsp_flowgraph::{
BlockIO,
block::{Block, BlockResult},
edge::{In, Out, PopIterable, stream},
};
#[derive(BlockIO)]
pub struct Map<I: 'static, O: 'static, F>
{
#[input]
input: In<I>,
#[output]
output: Out<O>,
map: F,
}
impl<I: 'static, O: 'static, F> Map<I, O, F>
where
F: Fn(I) -> O,
{
pub fn new(input: In<I>, map: F) -> (Self, In<O>)
{
let (output, mapped) = stream();
(Self { input, output, map }, mapped)
}
}
impl<I: 'static, O: 'static, F> Block for Map<I, O, F>
where
F: Fn(I) -> O,
{
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
{
self.output.push_iter(self.input.pop_iter().map(&self.map));
BlockResult::Ok
}
}
#[derive(BlockIO)]
pub struct Repeat<T: 'static>
{
#[input]
input: In<T>,
repetitions: usize,
remaining: usize,
current: Option<T>,
#[output]
output: Out<T>,
}
impl<T: 'static> Repeat<T>
{
pub fn new(input: In<T>, repetitions: usize) -> (Self, In<T>)
{
let (output, repeated) = stream();
(
Self {
input,
repetitions,
remaining: repetitions,
current: None,
output,
},
repeated,
)
}
}
impl<T: Clone + 'static> Block for Repeat<T>
{
fn work(&mut self) -> BlockResult
{
let writer = self.output.write();
let reader = self.input.read();
let len = writer.len().min(reader.len() / self.repetitions + 1);
for _ in 0..len
{
if self.remaining == 0 || self.current.is_none()
{
self.current = Some(reader.pop().unwrap());
self.remaining = self.repetitions;
}
writer
.push(self.current.clone().unwrap())
.unwrap_or_else(|_| panic!());
self.remaining -= 1;
}
BlockResult::Ok
}
}

View File

@ -0,0 +1,95 @@
use std::sync::mpsc::{Receiver, Sender, SyncSender};
use oxydsp_flowgraph::{
BlockIO,
block::{Block, BlockResult},
edge::{In, Out, PopIterable, stream},
};
#[derive(BlockIO)]
pub struct RxSource<Rx, I: 'static>
{
input: Rx,
#[output]
output: Out<I>,
}
#[derive(BlockIO)]
pub struct TxSink<Tx, I: 'static>
{
#[input]
input: In<I>,
output: Tx,
}
impl<Rx, I: 'static> RxSource<Rx, I>
{
pub fn new(input: Rx) -> (Self, In<I>)
{
let (output, source) = stream();
(Self { input, output }, source)
}
}
impl<Tx, I: 'static> TxSink<Tx, I>
{
pub fn new(input: In<I>, output: Tx) -> Self
{
Self { input, output }
}
}
impl<I: 'static> Block for RxSource<Receiver<I>, I>
{
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
{
if self.output.push_iter(self.input.iter())
{
BlockResult::Ok
}
else
{
BlockResult::Terminated
}
}
}
impl<I: 'static> Block for TxSink<Sender<I>, I>
{
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
{
if self
.input
.pop_iter()
.map(|x| self.output.send(x))
.any(|res| res.is_err())
{
BlockResult::Terminated
}
else
{
BlockResult::Ok
}
}
}
impl<I: 'static> Block for TxSink<SyncSender<I>, I>
{
fn work(&mut self) -> oxydsp_flowgraph::block::BlockResult
{
if self
.input
.pop_iter()
.map(|x| self.output.send(x))
.any(|res| res.is_err())
{
BlockResult::Terminated
}
else
{
BlockResult::Ok
}
}
}

View File

@ -51,7 +51,8 @@ impl<T> Nco<T>
pub fn step(&mut self)
{
let _ = self.phase.overflowing_add(self.d_phase);
let (new, _) = self.phase.overflowing_add(self.d_phase);
self.phase = new;
}
}

View File

@ -1,4 +1,4 @@
use std::f64::consts::PI;
use std::{f64::consts::PI, ops::Neg};
use crate::map;
@ -15,7 +15,7 @@ impl DigitalFrequency
{
// Frequnecy wraps arround : Going at 2 pi radians per second
// Is like not oscillating at all
let f = radians_per_sample.rem_euclid(radians_per_sample);
let f = radians_per_sample.rem_euclid(2. * PI);
// Then we map the [0, 2*PI] range into the 0 to usize range
DigitalFrequency(map(f, 0., 2. * PI, 0., usize::MAX as f64).floor() as usize)
@ -36,3 +36,13 @@ impl DigitalFrequency
map(self.0 as f64, 0., usize::MAX as f64, 0., sample_rate)
}
}
impl Neg for DigitalFrequency
{
type Output = Self;
fn neg(self) -> Self::Output
{
DigitalFrequency(usize::MAX - self.0)
}
}