1use std::sync::mpsc;
2
3use nusb::transfer::{ControlOut, ControlType, Recipient, RequestBuffer};
4
5use crate::{
6 Buffer, Error, HackRf,
7 consts::{ControlRequest, TransceiverMode},
8 error::StateChangeError,
9};
10
11pub struct SweepParams {
13 pub sample_rate_hz: u32,
15 pub freq_mhz: Vec<(u16, u16)>,
17 pub blocks_per_tuning: u16,
20 pub step_width_hz: u32,
23 pub offset_hz: u32,
26 pub mode: SweepMode,
28}
29
30impl SweepParams {
31 pub fn initialize_from_sample_rate(sample_rate_hz: u32) -> Self {
32 Self {
33 sample_rate_hz,
34 freq_mhz: Vec::new(),
35 blocks_per_tuning: 1,
36 step_width_hz: sample_rate_hz,
37 offset_hz: sample_rate_hz * 3 / 8,
38 mode: SweepMode::Interleaved,
39 }
40 }
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub enum SweepMode {
45 Linear,
47 Interleaved,
51}
52
53const SWEEP_BUF_SIZE: usize = 16384;
54const SWEEP_SAMPLE_SIZE: usize = (SWEEP_BUF_SIZE - 10) / 2;
55
56pub struct SweepBuf {
57 freq_hz: u64,
58 buf: Buffer,
59}
60
61impl SweepBuf {
62 pub fn freq_hz(&self) -> u64 {
63 self.freq_hz
64 }
65
66 pub fn samples(&self) -> &[num_complex::Complex<i8>] {
67 unsafe { self.buf.samples().get_unchecked(5..) }
69 }
70
71 pub fn samples_mut(&mut self) -> &mut [num_complex::Complex<i8>] {
72 unsafe { self.buf.samples_mut().get_unchecked_mut(5..) }
74 }
75
76 fn parse(buf: Buffer) -> Result<Self, Error> {
77 let bytes = buf.bytes();
78 if bytes.len() != SWEEP_BUF_SIZE {
79 return Err(Error::ReturnData);
80 }
81 let header: &[u8; 2] = unsafe { &*(bytes.as_ptr() as *const [u8; 2]) };
84 let freq: [u8; 8] = unsafe { *(bytes.as_ptr().add(2) as *const [u8; 8]) };
85 if header != &[0x7f, 0x7f] {
86 return Err(Error::ReturnData);
87 }
88 let freq_hz = u64::from_le_bytes(freq);
89 if !(100_000..=7_100_000_000).contains(&freq_hz) {
90 return Err(Error::ReturnData);
91 }
92 Ok(Self { freq_hz, buf })
93 }
94}
95
96pub struct Sweep {
98 rf: HackRf,
99 queue: nusb::transfer::Queue<nusb::transfer::RequestBuffer>,
100 buf_pool: mpsc::Receiver<Vec<u8>>,
101 buf_pool_send: mpsc::Sender<Vec<u8>>,
102}
103
104impl Sweep {
105 pub async fn new(rf: HackRf, params: &SweepParams) -> Result<Self, StateChangeError> {
109 if let Err(err) = rf.set_sample_rate(params.sample_rate_hz as f64).await {
110 return Err(StateChangeError { err, rf });
111 }
112
113 Self::new_with_custom_sample_rate(rf, params).await
114 }
115
116 pub async fn new_with_custom_sample_rate(
118 rf: HackRf,
119 params: &SweepParams,
120 ) -> Result<Self, StateChangeError> {
121 const MAX_SWEEP_RANGES: usize = 10;
122 const TUNING_BLOCK_BYTES: usize = 16384;
123 if params.freq_mhz.is_empty()
124 || params.freq_mhz.len() > MAX_SWEEP_RANGES
125 || params.blocks_per_tuning < 1
126 || params.step_width_hz < 1
127 {
128 return Err(StateChangeError {
129 rf,
130 err: Error::InvalidParameter("Invalid sweep parameters"),
131 });
132 }
133
134 let mut data = Vec::with_capacity(params.freq_mhz.len() * 4 + 9);
136 data.extend_from_slice(¶ms.step_width_hz.to_le_bytes());
137 data.extend_from_slice(¶ms.offset_hz.to_be_bytes());
138 data.push(match params.mode {
139 SweepMode::Linear => 0,
140 SweepMode::Interleaved => 0,
141 });
142 for (lo, hi) in params.freq_mhz.iter().copied() {
143 data.extend_from_slice(&lo.to_le_bytes());
144 data.extend_from_slice(&hi.to_le_bytes());
145 }
146
147 let num_bytes = (params.blocks_per_tuning as u32) * (TUNING_BLOCK_BYTES as u32);
148
149 if let Err(e) = rf
151 .interface
152 .control_out(ControlOut {
153 control_type: ControlType::Vendor,
154 recipient: Recipient::Device,
155 request: ControlRequest::InitSweep as u8,
156 value: (num_bytes & 0xffff) as u16,
157 index: (num_bytes >> 16) as u16,
158 data: &data,
159 })
160 .await
161 .into_result()
162 {
163 return Err(StateChangeError { rf, err: e.into() });
164 }
165
166 if let Err(err) = rf.set_transceiver_mode(TransceiverMode::RxSweep).await {
168 return Err(StateChangeError { rf, err });
169 }
170 let queue = rf.interface.bulk_in_queue(0x81);
171 let (buf_pool_send, buf_pool) = mpsc::channel();
172 Ok(Self {
173 rf,
174 queue,
175 buf_pool,
176 buf_pool_send,
177 })
178 }
179
180 pub fn submit(&mut self) {
187 let req = if let Ok(buf) = self.buf_pool.try_recv() {
188 RequestBuffer::reuse(buf, SWEEP_BUF_SIZE)
189 } else {
190 RequestBuffer::new(SWEEP_BUF_SIZE)
191 };
192 self.queue.submit(req);
193 }
194
195 pub async fn next_complete(&mut self) -> Result<SweepBuf, Error> {
197 let buf = self.queue.next_complete().await.into_result()?;
198 let buf = Buffer::new(buf, self.buf_pool_send.clone());
199 SweepBuf::parse(buf)
200 }
201
202 pub fn pending(&self) -> usize {
204 self.queue.pending()
205 }
206
207 pub async fn stop(mut self) -> Result<HackRf, Error> {
212 while self.pending() > 0 {
213 let _ = self.next_complete().await;
214 }
215 self.rf.set_transceiver_mode(TransceiverMode::Off).await?;
216 Ok(self.rf)
217 }
218}