Radio ptt enable

This commit is contained in:
2025-10-29 11:28:53 +01:00
parent e7448a2e65
commit f4a9078dd2
3 changed files with 41 additions and 17 deletions

View File

@ -3,7 +3,7 @@ echo "running as $1"
cargo b --release
sudo setcap cap_net_admin+eip target/release/rdsp
./target/release/rdsp 0 &
./target/release/rdsp 0 > /dev/ttyACM0 &
sleep .5
sudo ip a a $1/24 dev radio0
sudo ip -6 addr flush radio0

View File

@ -145,10 +145,10 @@ impl FSKReceiver {
let elg = ELGate::new(samples_per_symbol, FIRFilter::new(&loop_ir));
// Baseband filter
let bbf_length = estimate_fir_length(500., SAMPLE_RATE as f32).floor() as usize;
let bbf_length = estimate_fir_length(100., SAMPLE_RATE as f32).floor() as usize;
let mut frequency_response = vec![Complex32::zero(); bbf_length].into_boxed_slice();
let cutoff_bin = map(
hz_to_rad_per_sample(DEVIATION + 100., SAMPLE_RATE as f32),
hz_to_rad_per_sample(DEVIATION + 300., SAMPLE_RATE as f32),
0.,
2. * PI,
0.,
@ -181,9 +181,10 @@ impl FSKReceiver {
async fn receive(&mut self, iq: Complex32) -> Result<Option<Frame>, FrameConstructionError> {
// Frame reconstruction
let filtered_bb = self.baseband_filter.next(iq);
let dphi = self
.phase_lowpass
.next_real((self.last_sample * filtered_bb.conj()).arg());
// let dphi = self
// .phase_lowpass
// .next_real((self.last_sample * filtered_bb.conj()).arg());
let dphi = (self.last_sample * filtered_bb.conj()).arg();
self.last_sample = filtered_bb;
if let Some((bit_sample, eye)) = self.elg.next_eye(dphi) {
let _ = self.eye_sender.send(eye).await;
@ -206,7 +207,7 @@ impl FSKReceiver {
let frame_opt = self.frame_constructor.add_byte(self.last_byte);
self.bit_count = Some(0);
//print!("{}", last_byte as char);
print!(".{:x}.", self.last_byte);
eprint!(".{:x}.", self.last_byte);
let _ = std::io::stdout().flush();
return frame_opt;
}
@ -265,7 +266,7 @@ impl Transceiver {
let receiving = Arc::new(RwLock::new(false));
tokio::spawn(async move {
let mut squelch = Squelch::new(200, 0.1);
let mut squelch = Squelch::new(200, 0.5);
let mut iq_sampler =
IQSampler::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32));
@ -288,7 +289,7 @@ impl Transceiver {
match recv.as_mut().unwrap().receive(iq).await
{
Ok(Some(Frame::Data(dat))) => {
println!("GOT DATA");
eprintln!("GOT DATA");
let _ = rx_stream_sender.try_send(dat);
send_ack = false;
recv = None;
@ -319,10 +320,10 @@ impl Transceiver {
} =>
{
state_tx.try_send(TransceiverState::Sending);
println!("Sending message");
eprintln!("Sending message");
Self::transmit(Frame::Data(message.clone()), &mut sample_sender).await;
current_message = None;
println!("Sent message");
eprintln!("Sent message");
state_tx.try_send(TransceiverState::Waiting);
}
};
@ -412,7 +413,7 @@ impl FrameConstructor {
pub fn add_byte(&mut self, byte: u8) -> Result<Option<Frame>, FrameConstructionError> {
if self.frame.is_empty() && byte != 0xC4 && byte != 0x4C && !self.started {
println!("Wrong type {:x}", byte);
eprintln!("Wrong type {:x}", byte);
self.started = true;
return Err(());
}
@ -447,7 +448,7 @@ impl FrameConstructor {
)));
}
println!("Checksum failed");
eprintln!("Checksum failed");
return Err(());
}
@ -500,7 +501,7 @@ impl Frame {
#[tokio::main]
async fn main() {
// Read instance
println!(
eprintln!(
"fir length: {}",
impulse_response::design::estimate_fir_length(1000., 48000.)
);
@ -554,7 +555,7 @@ impl EguiApp {
let instance_id = unsafe { INSTANCE_ID };
tokio::task::spawn(async move {
println!("Waiting for connection ...");
eprintln!("Waiting for connection ...");
// let socket = Arc::new(
// UdpSocket::bind(format!("0.0.0.0:{}", 9000 + instance_id))
@ -609,6 +610,8 @@ impl EguiApp {
let progression = Arc::new(AtomicU64::new(0));
let (finished_tx, mut finished_rx) = channel::<()>(16);
print!("o");
stdout().flush().unwrap();
let send_stream = device
.build_output_stream(
&config,
@ -634,6 +637,8 @@ impl EguiApp {
.unwrap();
send_stream.play().unwrap();
let _ = finished_rx.recv().await;
print!("c");
stdout().flush().unwrap();
}
});

View File

@ -1,10 +1,11 @@
use std::collections::VecDeque;
use crate::filtering::fir::FIRFilter;
use std::collections::VecDeque;
// Crued Early late gate timing error detector
pub struct ELGate {
samples_per_symbol: f32,
buffer: VecDeque<f32>, // Store baseband, matched filtered samples,
eye_buffer: VecDeque<f32>,
loop_filter: FIRFilter,
delta: f32,
@ -18,6 +19,7 @@ impl ELGate {
samples_per_symbol,
loop_filter,
buffer: VecDeque::with_capacity(2 * samples_per_symbol.ceil() as usize),
eye_buffer: VecDeque::with_capacity(2 * samples_per_symbol.ceil() as usize),
delta: 0.5,
next_sample: samples_per_symbol,
current_position: 0.,
@ -30,8 +32,26 @@ impl ELGate {
pub fn next_eye(&mut self, sample: f32) -> Option<(f32, Vec<f32>)> {
self.buffer.push_front(sample);
self.eye_buffer.push_front(sample);
self.current_position += 1.;
if self.current_position >= self.next_sample {
// Eye stuff
let mut eye = Vec::new();
if self.eye_buffer.len() >= (self.samples_per_symbol / 2.) as usize {
let start_index = (self.samples_per_symbol / 2.) as usize;
let end_index = (start_index * 3).min(self.eye_buffer.len());
eye = self
.eye_buffer
.range(start_index..)
.copied()
.collect::<Vec<_>>();
while self.eye_buffer.len() > start_index {
self.eye_buffer.pop_back();
}
}
// Sample center, early late
let early_id = (self.samples_per_symbol / 2. + self.samples_per_symbol * self.delta)
.floor()
@ -63,4 +83,3 @@ impl ELGate {
}
}
}