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/fl2k.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/fl2k.rs')
-rw-r--r-- | src/fl2k.rs | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/src/fl2k.rs b/src/fl2k.rs index 8bfc0ec..f2e197b 100644 --- a/src/fl2k.rs +++ b/src/fl2k.rs @@ -1,5 +1,5 @@ -use std::ffi::c_int; -use fl2k_ampliphase::{fl2k_dev_t, fl2k_get_device_count, fl2k_open, fl2k_close, fl2k_stop_tx, fl2k_set_sample_rate, fl2k_get_sample_rate, fl2k_tx_cb_t, fl2k_start_tx}; +use std::{ffi::{c_int, c_void}, sync::mpsc}; +use fl2k_ampliphase::{fl2k_dev_t, fl2k_get_device_count, fl2k_open, fl2k_close, fl2k_stop_tx, fl2k_set_sample_rate, fl2k_get_sample_rate, fl2k_start_tx}; #[derive(Debug)] pub enum FL2KError { @@ -12,7 +12,7 @@ pub enum FL2KError { Unknown(c_int) } -fn handle_return_value(val : c_int) -> Result<(), FL2KError> { +fn handle_return_value(val: c_int) -> Result<(), FL2KError> { if val == fl2k_ampliphase::fl2k_error_FL2K_SUCCESS { Ok(()) } else if val == fl2k_ampliphase::fl2k_error_FL2K_TRUE { Ok(()) } else if val == fl2k_ampliphase::fl2k_error_FL2K_ERROR_INVALID_PARAM { Err(FL2KError::InvalidParam) } @@ -29,20 +29,71 @@ pub fn get_device_count() -> u32 { } pub struct FL2K { - device : *mut fl2k_dev_t, + device: *mut fl2k_dev_t, + callback_ctx: Box<CallbackCtx>, + tx : mpsc::SyncSender<(Vec<i8>, Vec<i8>)>, +} + +pub struct CallbackCtx { + // All three buffers must have same length! + r_buf: Vec<i8>, + g_buf: Vec<i8>, + + rg_bufs_channel: mpsc::Receiver<(Vec<i8>, Vec<i8>)>, + + underflow_count: u32, + buffer_underflows: u32, + + abort: bool, +} + +extern "C" fn tx_callback(data_info: *mut fl2k_ampliphase::fl2k_data_info_t) { + unsafe { + let ctx = (*data_info).ctx as *mut CallbackCtx; + + if (*data_info).device_error != 0 { + (*ctx).abort = true; + } + else { + (*ctx).underflow_count = (*data_info).underflow_cnt; + + match (*ctx).rg_bufs_channel.try_recv() { + Ok((r, g)) => { + (*data_info).sampletype_signed = 1; + + (*ctx).r_buf = r; + (*ctx).g_buf = g; + + (*data_info).r_buf = (*ctx).r_buf.as_mut_ptr(); + (*data_info).g_buf = (*ctx).g_buf.as_mut_ptr(); + }, + Err(_) => { + (*ctx).buffer_underflows += 1; + }, + } + } + } } impl FL2K { - pub fn open(device_index : u32) -> Result<Self, FL2KError> { + pub fn open(device_index: u32) -> Result<Self, FL2KError> { + let (tx, rx) = mpsc::sync_channel(2); + let ctx = CallbackCtx { + r_buf: Vec::new(), + g_buf: Vec::new(), + rg_bufs_channel: rx, + underflow_count: 0, + buffer_underflows: 0, + abort: false, + }; unsafe { - let mut fl2k = FL2K { device: std::mem::zeroed() }; + let mut fl2k = FL2K { device: std::mem::zeroed(), callback_ctx: Box::new(ctx), tx }; handle_return_value(fl2k_open(&mut fl2k.device, device_index))?; Ok(fl2k) } } - - pub fn set_sample_rate(&mut self, sample_rate : u32) -> Result<(), FL2KError> { + pub fn set_sample_rate(&mut self, sample_rate: u32) -> Result<(), FL2KError> { handle_return_value( unsafe { fl2k_set_sample_rate(self.device, sample_rate) }) } @@ -51,14 +102,21 @@ impl FL2K { if sr == 0 { Err(FL2KError::Unknown(0)) } else { Ok(sr) } } - pub fn start_tx(&mut self, callback : fl2k_tx_cb_t, buf_num: u32) -> Result<(), FL2KError> { - let r = unsafe { fl2k_start_tx(self.device, callback, std::ptr::null_mut(), 0) }; + pub fn start_tx(&mut self) -> Result<(), FL2KError> { + let r = unsafe { fl2k_start_tx(self.device, Some(tx_callback), self.callback_ctx.as_mut() as *mut CallbackCtx as *mut c_void, 0) }; handle_return_value(r) } pub fn stop_tx(&self) -> Result<(), FL2KError> { handle_return_value( unsafe { fl2k_stop_tx(self.device) } ) } + + pub fn send(&self, r_buf: Vec<i8>, g_buf: Vec<i8>) -> bool { + if r_buf.len() != g_buf.len() { + panic!("r_buf and g_buf must have same length"); + } + self.tx.send((r_buf, g_buf)).is_ok() + } } |