use clap::Args;
use color_eyre::eyre::{Context, eyre};
use waverave_hackrf::{HackRf, RfPathFilter};
#[derive(Args, Debug)]
pub struct Cmd {
#[arg(short, long)]
freq_hz: Option<u64>,
#[arg(short, long = "if_freq")]
if_freq_hz: Option<u64>,
#[arg(short = 'o', long = "lo_freq")]
lo_freq_hz: Option<u64>,
#[arg(short = 'm', long)]
image_reject: Option<u8>,
#[arg(short, long = "amp_en")]
amp_enable: Option<bool>,
#[arg(short = 'p', long = "ant_en")]
antenna_enable: Option<bool>,
#[arg(short = 'l', long = "lna")]
lna_gain: Option<u16>,
#[arg(short = 'g', long = "vga")]
vga_gain: Option<u16>,
#[arg(short = 'x', long = "txvga")]
txvga_gain: Option<u16>,
#[arg(short, long = "rate", default_value_t = 10e6)]
sample_rate_hz: f64,
#[arg(short, long = "baseband")]
baseband_filter_bw_hz: Option<u32>,
#[arg(short = 'C', long)]
ppm: Option<i32>,
#[arg(short = 'H', long = "ext_trig")]
sync: Option<bool>,
}
impl Cmd {
pub async fn configure(&self, rf: &HackRf) -> color_eyre::Result<()> {
if let Some(freq_hz) = self.freq_hz {
let freq_hz = self
.ppm
.map(|ppm| freq_hz * (1_000_000 - (ppm as u64)) / 1_000_000)
.unwrap_or(freq_hz);
rf.set_freq(freq_hz)
.await
.wrap_err("Failed setting frequency")?;
}
match (self.if_freq_hz, self.lo_freq_hz, self.image_reject) {
(Some(if_freq_hz), Some(lo_freq_hz), Some(image_reject)) => {
if self.freq_hz.is_some() {
return Err(eyre!(
"freq_hz cannot be set while the explicit frequency tuning values are also set"
));
}
let filter = match image_reject {
0 => RfPathFilter::Bypass,
1 => RfPathFilter::LowPass,
2 => RfPathFilter::HighPass,
i => return Err(eyre!("image_reject valid range is 0-2, but got {i}")),
};
rf.set_freq_explicit(if_freq_hz, lo_freq_hz, filter)
.await
.wrap_err("Failed setting explicit frequency tuning")?;
}
(None, None, None) => (),
_ => {
return Err(eyre!(
"If `if_freq_hz`, `lo_freq_hz`, or `image_reject` are set, they all must be set"
));
}
}
if let Some(amp_enable) = self.amp_enable {
rf.set_amp_enable(amp_enable)
.await
.wrap_err("Failed setting amplifier enable on/off")?;
}
if let Some(gain) = self.lna_gain {
rf.set_lna_gain(gain)
.await
.wrap_err("Failed setting LNA gain")?;
}
if let Some(gain) = self.vga_gain {
rf.set_vga_gain(gain)
.await
.wrap_err("Failed setting VGA gain")?;
}
if let Some(gain) = self.txvga_gain {
rf.set_txvga_gain(gain)
.await
.wrap_err("Failed setting TXVGA gain")?;
}
let sample_rate_hz = self
.ppm
.map(|ppm| self.sample_rate_hz * (1e6 - (ppm as f64)) / 1e6)
.unwrap_or(self.sample_rate_hz);
rf.set_sample_rate(sample_rate_hz)
.await
.wrap_err("Failed setting sample rate")?;
if self.ppm.is_some() && self.baseband_filter_bw_hz.is_none() {
let bb = (self.sample_rate_hz * 3.0 / 4.0).round() as u32;
rf.set_baseband_filter_bandwidth(bb)
.await
.wrap_err("Failed setting baseband filter bandwidth")?;
}
if let Some(bb) = self.baseband_filter_bw_hz {
rf.set_baseband_filter_bandwidth(bb)
.await
.wrap_err("Failed setting baseband filter bandwidth")?;
}
if let Some(sync) = self.sync {
rf.set_hw_sync_mode(sync)
.await
.wrap_err("Failed setting HW sync mode")?;
}
Ok(())
}
}