diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2023-01-01 17:33:01 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2023-01-01 17:33:01 +0100 |
commit | adf283e4bfc50e49e92d369853eb3253481b8fbb (patch) | |
tree | 88a0df7b6467ee66a7aa11a7b52d2f086fabc51b /src/main.rs | |
parent | c08d47f914da5a0f9b505dee72c4a3a6969d878d (diff) | |
download | fl2k_ampliphase-adf283e4bfc50e49e92d369853eb3253481b8fbb.tar.gz fl2k_ampliphase-adf283e4bfc50e49e92d369853eb3253481b8fbb.tar.bz2 fl2k_ampliphase-adf283e4bfc50e49e92d369853eb3253481b8fbb.zip |
Add fl2k send code
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 87 |
1 files changed, 55 insertions, 32 deletions
diff --git a/src/main.rs b/src/main.rs index c04740f..76808e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,36 +31,36 @@ use getopts::Options; mod fl2k; -const TRIG_TABLE_ORDER : usize = 8; -const TRIG_TABLE_SHIFT : usize = 32 - TRIG_TABLE_ORDER; -const TRIG_TABLE_LEN : usize = 1 << TRIG_TABLE_ORDER; +const TRIG_TABLE_ORDER: usize = 8; +const TRIG_TABLE_SHIFT: usize = 32 - TRIG_TABLE_ORDER; +const TRIG_TABLE_LEN: usize = 1 << TRIG_TABLE_ORDER; -const PI : f32 = std::f32::consts::PI; -const INT32_MAX_AS_FLOAT : f32 = 0x1_0000_0000u64 as f32; -const ANG_INCR : f32 = INT32_MAX_AS_FLOAT / (2.0 * PI); +const PI: f32 = std::f32::consts::PI; +const INT32_MAX_AS_FLOAT: f32 = 0x1_0000_0000u64 as f32; +const ANG_INCR: f32 = INT32_MAX_AS_FLOAT / (2.0 * PI); enum Waveform { Sine, Rect } enum Output { Debug, FL2K } struct DDS { - trig_table_quadrature : Vec<i16>, - trig_table_inphase : Vec<i16>, + trig_table_quadrature: Vec<i16>, + trig_table_inphase: Vec<i16>, /* instantaneous phase */ - phase : u32, + phase: u32, /* phase increment */ - phase_step : u32, + phase_step: u32, /* for phase modulation */ - phase_delta : i32, - phase_slope : i32, + phase_delta: i32, + phase_slope: i32, - amplitude : f32, + amplitude: f32, } impl DDS { - fn init(samp_rate : f32, freq : f32, phase : f32, amp : f32, waveform : Waveform) -> Self { + fn init(samp_rate: f32, freq: f32, phase: f32, amp: f32, waveform: Waveform) -> Self { let mut trig_table_inphase = Vec::with_capacity(TRIG_TABLE_LEN); let mut trig_table_quadrature = Vec::with_capacity(TRIG_TABLE_LEN); @@ -94,13 +94,14 @@ impl DDS { } } - fn set_phase(&mut self, phase_delta : i32, phase_slope : i32) { + fn set_phase(&mut self, phase_delta: i32, phase_slope: i32) { self.phase_delta = phase_delta; self.phase_slope = phase_slope; } - fn generate_iq(&mut self, len : usize) -> Vec<(i8, i8)> { - let mut out = Vec::with_capacity(len); + fn generate_iq(&mut self, len: usize) -> (Vec<i8>, Vec<i8>) { + let mut out_i = Vec::with_capacity(len); + let mut out_q = Vec::with_capacity(len); for _ in 0..len { let phase = self.phase as i32; // get current carrier phase, add phase mod, calculate table index @@ -119,11 +120,12 @@ impl DDS { // let i = (amp_i >> 24) as i8; // 0..31 >> 24 => 0..8 let q = (amp_q >> 24) as i8; // 0..31 >> 24 => 0..8 - out.push((i, q)); + out_i.push(i); + out_q.push(q); self.phase_delta += self.phase_slope; } - out + (out_i, out_q) } } @@ -168,12 +170,12 @@ fn main() { Output::FL2K }; - let device_index : u32 = match cli_args.opt_str("d") { + let device_index: u32 = match cli_args.opt_str("d") { Some(s) => s.parse().expect("integer value"), None => 0, }; - let samp_rate : u32 = match cli_args.opt_str("s") { + let samp_rate: u32 = match cli_args.opt_str("s") { Some(s) => s.parse().expect("integer value"), None => 96_000_000, }; @@ -183,7 +185,7 @@ fn main() { None => 1_440_000.0, }; - let input_freq : u32 = match cli_args.opt_str("i") { + let input_freq: u32 = match cli_args.opt_str("i") { Some(s) => s.parse().expect("integer value"), None => 48_000, }; @@ -235,7 +237,7 @@ fn main() { let source_file = File::open(source_file_name).expect("open file"); let mut source_file = BufReader::new(source_file); - const BASEBAND_BUF_SAMPS : usize = 1024; + const BASEBAND_BUF_SAMPS: usize = 1024; // Read file and convert samples thread::spawn(move || { @@ -252,9 +254,9 @@ fn main() { source_file.read_exact(&mut buf_u8).expect("Read from source file"); - let buf : Vec<f32> = buf + let buf: Vec<f32> = buf .iter() - .map(|v| (v/2 + i16::MAX) as f32 / 32768.0) + .map(|v| (v/2 + i16::MAX/2) as f32 / 32768.0) .collect(); if let Err(_) = input_samples_tx.send(buf) { @@ -285,8 +287,8 @@ fn main() { let pd = lastamp * modulation_index * INT32_MAX_AS_FLOAT; - const MIN_VAL : f32 = std::i32::MIN as f32; - const MAX_VAL : f32 = std::i32::MAX as f32; + const MIN_VAL: f32 = std::i32::MIN as f32; + const MAX_VAL: f32 = std::i32::MAX as f32; if pd < MIN_VAL || pd > MAX_VAL { panic!("pd out of bounds {}", pd); @@ -318,9 +320,9 @@ fn main() { for (pd, pdslope) in buf { dds.set_phase(pd, pdslope); - let iq_buf = dds.generate_iq(rf_to_baseband_sample_ratio as usize); + let iq_bufs = dds.generate_iq(rf_to_baseband_sample_ratio as usize); - if let Err(_) = iq_tx.send(iq_buf) { + if let Err(_) = iq_tx.send(iq_bufs) { eprintln!("Quit dds thread"); break; } @@ -331,14 +333,35 @@ fn main() { // Main thread, output to file/device match output { Output::FL2K => { - let fl2k = fl2k::FL2K::open(device_index).expect("fl2k open"); - // TODO fl2k.start_tx(|| {}, 0).expect("fl2k start_tx"); + let mut fl2k = fl2k::FL2K::open(device_index).expect("fl2k open"); + fl2k.start_tx().expect("fl2k start_tx"); + + fl2k.set_sample_rate(samp_rate).expect("set fl2k sample rate"); + + eprintln!("FL2K sample ret set to {}", fl2k.get_sample_rate().unwrap()); + + loop { + let Ok((i, q)) = iq_rx.recv() else { break }; + if fl2k.send(i, q) == false { break }; + } + + fl2k.stop_tx().expect("stop tx"); } Output::Debug => { let out_file = File::create("debug-out.i8").expect("create file"); let mut out_file = BufWriter::new(out_file); loop { - let Ok(buf) = iq_rx.recv() else { break }; + let Ok((i_buf, q_buf)) = iq_rx.recv() else { break }; + + if i_buf.len() != q_buf.len() { + panic!("i_buf and q_buf must have same length"); + } + + let mut buf = Vec::with_capacity(i_buf.len() * 2); + for (i, q) in i_buf.iter().zip(q_buf) { + buf.push(*i); + buf.push(q); + } let buf_u8: &[u8] = unsafe { std::slice::from_raw_parts( |