Updates to account, ui, etc

This commit is contained in:
2025-05-13 22:57:29 -04:00
parent a273d4134b
commit abfa6b534c
38 changed files with 781 additions and 215 deletions

View File

@@ -21,25 +21,42 @@ pub const DEVICE_RTL2832U: DeviceInfo = DeviceInfo {
pid: 0x2832,
};
// Timeout
pub const TIMEOUT: Duration = Duration::from_secs(1);
// pub const DEFAULT_BUFFER_LENGTH: usize = 4096;
pub const DEFAULT_BUFFER_LENGTH: usize = 64;
pub const FIR_LENGTH: usize = 16;
// Request Types
pub const REQ_CTRL_OUT: u8 =
rusb::constants::LIBUSB_ENDPOINT_OUT | rusb::constants::LIBUSB_REQUEST_TYPE_VENDOR;
// Blocks
pub const BLOCK_DEMOD: u16 = 0;
pub const BLOCK_USB: u16 = 1;
pub const BLOCK_SYS: u16 = 2;
pub const BLOCK_TUN: u16 = 3;
pub const BLOCK_ROM: u16 = 4;
pub const BLOCK_IRB: u16 = 5;
pub const BLOCK_IIC: u16 = 6;
// Registers
pub const DEMOD_CTL: u16 = 0x3000;
pub const DEMOD_CTL_1: u16 = 0x300b;
// USB
pub const USB_EPA_CTL: u16 = 0x2148;
pub const USB_SYSCTL: u16 = 0x2000;
pub const USB_EPA_MAXPKT: u16 = 0x2158;
/// ADS-B downlink frequency (1090 MHz)
pub const ADSB_FREQUENCY_HZ: u32 = 1_090_000_000;
/// RTL-SDR sample rate in samples/second.
pub const SAMPLE_RATE_HZ: u32 = 2_048_000;
pub const DEFAULT_FIR: &'static [i32; FIR_LENGTH] = &[
-54, -36, -41, -40, -32, -14, 14, 53, 101, 156, 215, 273, 327, 372, 404, 421,
];
// pub const DEFAULT_BUFFER_LENGTH: usize = 4096;
pub const DEFAULT_BUFFER_LENGTH: usize = 64;
pub const DEFAULT_RTL_XTAL_FREQ: u32 = 28_800_000;
pub const MIN_RTL_XTAL_FREQ: u32 = DEFAULT_RTL_XTAL_FREQ - 1000;
pub const MAX_RTL_XTAL_FREQ: u32 = DEFAULT_RTL_XTAL_FREQ + 1000;

View File

@@ -7,8 +7,9 @@ use rusb::{
};
use crate::error::{Error, Result};
use crate::constants::{
ADSB_FREQUENCY_HZ, BLOCK_USB, DEFAULT_BUFFER_LENGTH, REQ_CTRL_OUT, SAMPLE_RATE_HZ, TIMEOUT,
USB_EPA_CTL, USB_SYSCTL,
ADSB_FREQUENCY_HZ, BLOCK_SYS, BLOCK_USB, DEFAULT_BUFFER_LENGTH, DEFAULT_FIR,
DEFAULT_RTL_XTAL_FREQ, DEMOD_CTL, DEMOD_CTL_1, REQ_CTRL_OUT, SAMPLE_RATE_HZ, TIMEOUT,
USB_EPA_CTL, USB_EPA_MAXPKT, USB_SYSCTL,
};
/// rusb/libusb implementation of `RtlSdrDevice`
@@ -83,7 +84,7 @@ impl RtlSdrDevice {
Some(e) => e,
None => return Err(Error::new("Unable to find endpoint on device")),
};
log::debug!("Found readable endpoint: {:?}", endpoint.to_string());
log::debug!("Found readable endpoint: {}", endpoint.to_string());
let mut sdr = Self::new(handle, endpoint);
@@ -158,6 +159,10 @@ impl RtlSdrDevice {
self.test_write()?;
self.initialize_baseband()?;
self.set_i2c_repeater(true)?;
// Reset the internal USB buffer
self.reset_buffer()?;
@@ -191,6 +196,7 @@ impl RtlSdrDevice {
.map_err(|err| Error::new(format!("Failed to set alternate setting: {:?}", err)))
}
/// Attempt to write a test message, and reset the device on a failure
fn test_write(&self) -> Result<()> {
log::trace!("Testing write to device...");
let length = ctrl_write_register(&self.handle, BLOCK_USB, USB_SYSCTL, 0x89, 1)?;
@@ -215,6 +221,66 @@ impl RtlSdrDevice {
Ok(())
}
fn reset_demod(&self) -> Result<()> {
log::trace!("Resetting demod...");
demod_ctrl_write_register(&self.handle, 1, 0x01, 0x14, 1)
.map_err(|err| Error::new(format!("Failed to reset the internal demod: {:?}", err)))?;
demod_ctrl_write_register(&self.handle, 1, 0x01, 0x10, 1)
.map_err(|err| Error::new(format!("Failed to reset the internal demod: {:?}", err)))?;
Ok(())
}
fn initialize_baseband(&self) -> Result<()> {
// Initialize the USB
ctrl_write_register(&self.handle, BLOCK_USB, USB_SYSCTL, 0x09, 1)?;
ctrl_write_register(&self.handle, BLOCK_USB, USB_EPA_MAXPKT, 0x0002, 2)?;
ctrl_write_register(&self.handle, BLOCK_USB, USB_EPA_CTL, 0x1002, 2)?;
// Power on demod
ctrl_write_register(&self.handle, BLOCK_SYS, DEMOD_CTL_1, 0x22, 1)?;
ctrl_write_register(&self.handle, BLOCK_SYS, DEMOD_CTL, 0xe8, 1)?;
// Reset demod
self.reset_demod()?;
// Disable spectrum inversion and adjust channel rejection
ctrl_write_register(&self.handle, 1, 0x15, 0x00, 1)?;
ctrl_write_register(&self.handle, 1, 0x16, 0x00, 2)?;
// Clear DDC shift and IF registers
for i in 0..5 {
demod_ctrl_write_register(&self.handle, 1, 0x16 + i, 0x00, 1)?;
}
self.set_fir(DEFAULT_FIR)?;
// info!("Enable SDR mode, disable DAGC (bit 5)");
demod_ctrl_write_register(&self.handle, 0, 0x19, 0x05, 1)?;
// info!("Init FSM state-holding register");
demod_ctrl_write_register(&self.handle, 1, 0x93, 0xf0, 1)?;
demod_ctrl_write_register(&self.handle, 1, 0x94, 0x0f, 1)?;
// Disable AGC (en_dagc, bit 0) (seems to have no effect)
demod_ctrl_write_register(&self.handle, 1, 0x11, 0x00, 1)?;
// Disable RF and IF AGC loop
demod_ctrl_write_register(&self.handle, 1, 0x04, 0x00, 1)?;
// Disable PID filter
demod_ctrl_write_register(&self.handle, 0, 0x61, 0x60, 1)?;
// opt_adc_iq = 0, default ADC_I/ADC_Q datapath
demod_ctrl_write_register(&self.handle, 0, 0x06, 0x80, 1)?;
// Enable Zero-IF mode, DC cancellation, and IQ estimation/compensation
demod_ctrl_write_register(&self.handle, 1, 0xb1, 0x1b, 1)?;
// Disable 4.096 MHz clock output on pin TP_CK0
demod_ctrl_write_register(&self.handle, 0, 0x0d, 0x83, 1)?;
Ok(())
}
fn set_center_frequency(&mut self, frequency: u32) -> Result<()> {
log::trace!("Setting center_frequency to {}Hz", frequency);
self.frequency = frequency;
@@ -223,7 +289,77 @@ impl RtlSdrDevice {
fn set_sample_rate(&mut self, rate: u32) -> Result<()> {
log::trace!("Setting sample_rate to {}Hz", rate);
self.rate = rate;
if rate <= 225_000 || rate > 3_200_000 || (rate > 300000 && rate <= 900000) {
return Err(Error::new(format!("Invalid sample rate: {} Hz", rate)));
}
let rsamp_ratio =
((DEFAULT_RTL_XTAL_FREQ as u128 * 2_u128.pow(22) / rate as u128) & 0x0ffffffc) as u128;
log::trace!(
"Sample rate: {}, xtal: {}, rsamp_ratio: {}",
rate,
DEFAULT_RTL_XTAL_FREQ,
rsamp_ratio
);
let real_resamp_ratio = rsamp_ratio | ((rsamp_ratio & 0x08000000) << 1);
let real_rate =
(DEFAULT_RTL_XTAL_FREQ as u128 * 2_u128.pow(22)) as f64 / real_resamp_ratio as f64;
if rate as f64 != real_rate {
log::trace!("Exact sample rate is {} Hz", real_rate);
}
self.rate = real_rate as u32;
let mut tmp: u16 = (rsamp_ratio >> 16) as u16;
demod_ctrl_write_register(&self.handle, 1, 0x9f, tmp, 2)?;
tmp = (rsamp_ratio & 0xffff) as u16;
demod_ctrl_write_register(&self.handle, 1, 0xa1, tmp, 2)?;
Ok(())
}
fn set_fir(&self, fir: &[i32; 16]) -> Result<()> {
log::trace!("Setting fir to {:?}", fir);
const TMP_LEN: usize = 20;
let mut tmp: [u8; TMP_LEN] = [0; TMP_LEN];
// First 8 values are i8
for i in 0..8 {
let val = fir[i];
if val < -128 || val > 127 {
panic!("i8 FIR coefficient out of bounds! {}", val);
}
tmp[i] = val as u8;
}
// Next 12 are i12, so don't line up with byte boundaries and need to unpack
// 12 i12 values from 4 pairs of bytes in fir. Example:
// fir: 4b5, 7f8, 3e8, 619
// tmp: 4b, 57, f8, 3e, 86, 19
for i in (0..8).step_by(2) {
let val0 = fir[8 + i];
let val1 = fir[8 + i + 1];
if val0 < -2048 || val0 > 2047 {
panic!("i12 FIR coefficient out of bounds: {}", val0)
} else if val1 < -2048 || val1 > 2047 {
panic!("i12 FIR coefficient out of bounds: {}", val1)
}
tmp[8 + i * 3 / 2] = (val0 >> 4) as u8;
tmp[8 + i * 3 / 2 + 1] = ((val0 << 4) | ((val1 >> 8) & 0x0f)) as u8;
tmp[8 + i * 3 / 2 + 2] = val1 as u8;
}
for i in 0..TMP_LEN {
demod_ctrl_write_register(&self.handle, 1, 0x1c + i as u16, tmp[i] as u16, 1)?;
}
Ok(())
}
fn set_i2c_repeater(&self, enabled: bool) -> Result<()> {
let value = match enabled {
true => 0x18,
false => 0x10,
};
demod_ctrl_write_register(&self.handle, 1, 0x01, value, 1)?;
Ok(())
}
@@ -397,5 +533,18 @@ fn demod_ctrl_write_register<T: UsbContext>(
let buffer = if length == 1 { &data[1..2] } else { &data };
let index = 0x10 | page;
let address = (address << 8) | 0x20;
log::trace!(
"Received page {}, address 0x{:04X}, value 0x{:04X}, length {} \
- writing control register: {} 0x{:04X} 0x{:04X} {:?}",
page,
address,
value,
length,
REQ_CTRL_OUT,
address,
index,
buffer
);
handle.write_control(REQ_CTRL_OUT, 0x00, address, index, buffer, TIMEOUT)
}