diff options
| author | Yuval Adam <_@yuv.al> | 2018-08-02 18:28:44 +0300 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2018-08-02 18:28:44 +0300 |
| commit | 9fe4d1ccf6e8d5edabb76cf4b95b0adf4ca4dd3b (patch) | |
| tree | 44204da8365571c59713d7f26634bbb9cf06e1e1 | |
| parent | f0025e9c44c519224b532c54c8b301029a42f98e (diff) | |
Refactor out USB function
| -rw-r--r-- | src/lib.rs | 222 | ||||
| -rw-r--r-- | src/usb.rs | 190 |
2 files changed, 218 insertions, 194 deletions
@@ -1,47 +1,20 @@ extern crate libusb; mod devices; +mod usb; -use std::time::Duration; -use libusb::{Direction, RequestType, Recipient}; use devices::*; - -// const BLOCK_DEMODB: u16 = 0; -const BLOCK_USBB: u16 = 1; -const BLOCK_SYSB: u16 = 2; -// const BLOCK_TUNB: u16 = 3; -const BLOCK_IICB: u8 = 6; - -const ADDR_USB_SYSCTL: u16 = 0x2000; -// const ADDR_USB_CTRL: u16 = 0x2010; -// const ADDR_USB_STAT: u16 = 0x2014; -// const ADDR_USB_EPA_CFG: u16 = 0x2144; -const ADDR_USB_EPA_CTL: u16 = 0x2148; -const ADDR_USB_EPA_MAXPKT: u16 = 0x2158; -// const ADDR_USB_EPA_MAXPKT_2: u16 = 0x215a; -// const ADDR_USB_EPA_FIFO_CFG: u16 = 0x2160; - -const ADDR_SYS_DEMOD_CTL: u16 = 0x3000; -const ADDR_SYS_DEMOD_CTL_1: u16 = 0x300b; +use usb::Usb; const INTERFACE_ID: u8 = 0; -const CTRL_TIMEOUT: Duration = Duration::from_millis(300); const KNOWN_DEVICES: [(u16, u16, &str); 2] = [ (0x0bda, 0x2832, "Generic RTL2832U"), (0x0bda, 0x2838, "Generic RTL2832U OEM") ]; -const FIR_LENGTH: usize = 20; -const FIR_DEFAULT: [u8; FIR_LENGTH] = [ - 0xca, 0xdc, 0xd7, 0xd8, 0xe0, 0xf2, 0x0e, 0x35, 0x06, 0x50, - 0x9c, 0x0d, 0x71, 0x11, 0x14, 0x71, 0x74, 0x19, 0x41, 0xa5, -]; - - pub struct RtlSdr<'a> { ctx: &'a libusb::Context, - // dev: Option<libusb::DeviceHandle<'a>>, iface_id: u8 } @@ -50,153 +23,10 @@ impl<'a> RtlSdr<'a> { pub fn new(ctx: &'a libusb::Context) -> RtlSdr<'a> { RtlSdr { ctx, - // dev: None, iface_id: INTERFACE_ID } } - fn write_reg(&self, handle: &libusb::DeviceHandle, block: u16, addr: u16, val: u16, len: u8) -> usize { - let type_vendor_out = libusb::request_type(Direction::Out, RequestType::Vendor, Recipient::Device); - let mut data: [u8; 2] = [0, 0]; - let index: u16 = (block << 8) | 0x10; - - // switching endianness??? - data[0] = if len == 1 { - (val & 0xff) as u8 - } else { - (val >> 8) as u8 - }; - data[1] = (val & 0xff) as u8; - - match handle.write_control(type_vendor_out, 0, addr, index, &data, CTRL_TIMEOUT) { - Ok(n) => n, - Err(_) => 0 - } - } - - fn demod_read_reg(&self, handle: &libusb::DeviceHandle, page: u8, addr: u16, _len: u8) -> u16 { - let type_vendor_in = libusb::request_type(Direction::In, RequestType::Vendor, Recipient::Device); - let data: [u8; 2] = [0, 0]; - let index: u16 = page.into(); - let addr = (addr << 8) | 0x20; - let _res = handle.write_control(type_vendor_in, 0, addr, index, &data, CTRL_TIMEOUT); - let reg: u16 = ((data[1] as u16) << 8) | (data[0] as u16); - return reg; - } - - fn demod_write_reg(&self, handle: &libusb::DeviceHandle, page: u8, addr: u16, val: u16, len: u8) -> u16 { - let type_vendor_out = libusb::request_type(Direction::Out, RequestType::Vendor, Recipient::Device); - let mut data: [u8; 2] = [0, 0]; - let index: u16 = (0x10 | page).into(); - let addr = (addr << 8) | 0x20; - - data[0] = if len == 1 { - (val & 0xff) as u8 - } else { - (val >> 8) as u8 - }; - data[1] = (val & 0xff) as u8; - - let _res = handle.write_control(type_vendor_out, 0, addr, index, &data, CTRL_TIMEOUT); - self.demod_read_reg(handle, 0x0a, 0x01, 1) - } - - fn read_array(&self, handle: &libusb::DeviceHandle, block: u8, addr: u16, arr: &mut [u8], _len: u8) -> usize { - let type_vendor_in = libusb::request_type(Direction::In, RequestType::Vendor, Recipient::Device); - let index: u16 = (block as u16) << 8; - handle.read_control(type_vendor_in, 0, addr, index, arr, CTRL_TIMEOUT).unwrap() - } - - fn write_array(&self, handle: &libusb::DeviceHandle, block: u8, addr: u16, arr: &[u8], _len: u8) -> Result<usize, libusb::Error> { - let type_vendor_out = libusb::request_type(Direction::Out, RequestType::Vendor, Recipient::Device); - let index: u16 = ((block as u16) << 8) | 0x10; - handle.write_control(type_vendor_out, 0, addr, index, arr, CTRL_TIMEOUT) - } - - fn i2c_read_reg(&self, handle: &libusb::DeviceHandle, i2c_addr: u8, reg: u8) -> Result<u8, &str> { - let addr: u16 = i2c_addr.into(); - let reg: [u8; 1] = [reg]; - let mut data: [u8; 1] = [0]; - - match self.write_array(&handle, BLOCK_IICB, addr, ®, 1) { - Ok(_res) => { - self.read_array(&handle, BLOCK_IICB, addr, &mut data, 1); - Ok(data[0]) - }, - Err(_) => Err("Error") - } - } - - fn set_i2c_repeater(&self, handle: &libusb::DeviceHandle, on: bool) { - let val = match on { - true => 0x18, - false => 0x10 - }; - self.demod_write_reg(&handle, 1, 0x01, val, 1); - } - - fn init_baseband(&self, handle: &libusb::DeviceHandle) { - // init USB - self.write_reg(&handle, BLOCK_USBB, ADDR_USB_SYSCTL, 0x09, 1); - self.write_reg(&handle, BLOCK_USBB, ADDR_USB_EPA_MAXPKT, 0x0002, 2); - self.write_reg(&handle, BLOCK_USBB, ADDR_USB_EPA_CTL, 0x1002, 2); - - // power on demod - self.write_reg(&handle, BLOCK_SYSB, ADDR_SYS_DEMOD_CTL_1, 0x22, 1); - self.write_reg(&handle, BLOCK_SYSB, ADDR_SYS_DEMOD_CTL, 0xe8, 1); - - // reset demod (bit 3, soft_rst) - self.demod_write_reg(&handle, 1, 0x01, 0x14, 1); - self.demod_write_reg(&handle, 1, 0x01, 0x10, 1); - - // disable spectrum inversion and adjacent channel rejection - self.demod_write_reg(&handle, 1, 0x15, 0x00, 1); - self.demod_write_reg(&handle, 1, 0x16, 0x0000, 2); - - // clear both DDC shift and IF frequency registers - for i in 0..6 { - self.demod_write_reg(&handle, 1, 0x16 + i, 0x00, 1); - } - - // set the FIR coefficients - for i in 0..FIR_LENGTH { - self.demod_write_reg(&handle, 1, (0x1c + i) as u16, FIR_DEFAULT[i].into(), 1); - } - - // enable SDR mode, disable DAGC (bit 5) - self.demod_write_reg(&handle, 0, 0x19, 0x05, 1); - - // init FSM state-holding register - self.demod_write_reg(&handle, 1, 0x93, 0xf0, 1); - self.demod_write_reg(&handle, 1, 0x94, 0x0f, 1); - - // disable AGC (en_dagc, bit 0) (this seems to have no effect) - self.demod_write_reg(&handle, 1, 0x11, 0x00, 1); - - // disable RF and IF AGC loop - self.demod_write_reg(&handle, 1, 0x04, 0x00, 1); - - // disable PID filter (enable_PID = 0) - self.demod_write_reg(&handle, 0, 0x61, 0x60, 1); - - // opt_adc_iq = 0, default ADC_I/ADC_Q datapath - self.demod_write_reg(&handle, 0, 0x06, 0x80, 1); - - // Enable Zero-IF mode (en_bbin bit), DC cancellation (en_dc_est), - // IQ estimation/compensation (en_iq_comp, en_iq_est) - self.demod_write_reg(&handle, 1, 0xb1, 0x1b, 1); - - // disable 4.096 MHz clock output on pin TP_CK0 - self.demod_write_reg(&handle, 0, 0x0d, 0x83, 1); - } - - fn deinit_baseband(&self, handle: &libusb::DeviceHandle) { - // deinit tuner? - - // power off demod and ADCs - self.write_reg(&handle, BLOCK_SYSB, ADDR_SYS_DEMOD_CTL, 0x20, 1); - } - pub fn open(&mut self) { for mut dev in self.ctx.devices().unwrap().iter() { let desc = dev.device_descriptor().unwrap(); @@ -217,28 +47,17 @@ impl<'a> RtlSdr<'a> { let _iface = handle.claim_interface(self.iface_id).unwrap(); - let _res = self.write_reg(&handle, BLOCK_USBB, ADDR_USB_SYSCTL, 0x09, 1); - // reset device is write didn't succeed + { + let usb = Usb::new(&handle); - self.init_baseband(&handle); - self.set_i2c_repeater(&handle, true); + usb.test_write(); + // reset device if write didn't succeed - let d = r820t::R820T::new(); - let found = match self.i2c_read_reg(&handle, d.device.i2c_addr, d.device.check_addr) { - Ok(reg) => { - if reg == d.device.check_val { - println!("Found {} tuner\n", d.device.name); - true - } - else { - false - } - }, - Err(_) => false - }; - if !found { - let d = fc0013::FC0013::new(); - let _found = match self.i2c_read_reg(&handle, d.device.i2c_addr, d.device.check_addr) { + usb.init_baseband(); + usb.set_i2c_repeater( true); + + let d = r820t::R820T::new(); + let found = match usb.i2c_read_reg(d.device.i2c_addr, d.device.check_addr) { Ok(reg) => { if reg == d.device.check_val { println!("Found {} tuner\n", d.device.name); @@ -250,9 +69,24 @@ impl<'a> RtlSdr<'a> { }, Err(_) => false }; - } + if !found { + let d = fc0013::FC0013::new(); + let _found = match usb.i2c_read_reg(d.device.i2c_addr, d.device.check_addr) { + Ok(reg) => { + if reg == d.device.check_val { + println!("Found {} tuner\n", d.device.name); + true + } + else { + false + } + }, + Err(_) => false + }; + } - self.deinit_baseband(&handle); + usb.deinit_baseband(); + } if has_kernel_driver { handle.attach_kernel_driver(self.iface_id).ok(); diff --git a/src/usb.rs b/src/usb.rs new file mode 100644 index 0000000..fdae356 --- /dev/null +++ b/src/usb.rs @@ -0,0 +1,190 @@ +extern crate libusb; + +use libusb::DeviceHandle; +use libusb::{Direction, RequestType, Recipient}; +use std::time::Duration; + +// const BLOCK_DEMODB: u16 = 0; +const BLOCK_USBB: u16 = 1; +const BLOCK_SYSB: u16 = 2; +// const BLOCK_TUNB: u16 = 3; +const BLOCK_IICB: u8 = 6; + +const ADDR_USB_SYSCTL: u16 = 0x2000; +// const ADDR_USB_CTRL: u16 = 0x2010; +// const ADDR_USB_STAT: u16 = 0x2014; +// const ADDR_USB_EPA_CFG: u16 = 0x2144; +const ADDR_USB_EPA_CTL: u16 = 0x2148; +const ADDR_USB_EPA_MAXPKT: u16 = 0x2158; +// const ADDR_USB_EPA_MAXPKT_2: u16 = 0x215a; +// const ADDR_USB_EPA_FIFO_CFG: u16 = 0x2160; + +const ADDR_SYS_DEMOD_CTL: u16 = 0x3000; +const ADDR_SYS_DEMOD_CTL_1: u16 = 0x300b; + +const FIR_LENGTH: usize = 20; +const FIR_DEFAULT: [u8; FIR_LENGTH] = [ + 0xca, 0xdc, 0xd7, 0xd8, 0xe0, 0xf2, 0x0e, 0x35, 0x06, 0x50, + 0x9c, 0x0d, 0x71, 0x11, 0x14, 0x71, 0x74, 0x19, 0x41, 0xa5, +]; + + +const CTRL_TIMEOUT: Duration = Duration::from_millis(300); + +pub struct Usb<'a> { + handle: &'a DeviceHandle<'a> +} + +impl<'a> Usb<'a> { + pub fn new(handle: &'a DeviceHandle) -> Usb<'a> { + Usb { + handle + } + } + + pub fn write_reg(&self, block: u16, addr: u16, val: u16, len: u8) -> usize { + let type_vendor_out = libusb::request_type(Direction::Out, RequestType::Vendor, Recipient::Device); + let mut data: [u8; 2] = [0, 0]; + let index: u16 = (block << 8) | 0x10; + + // switching endianness??? + data[0] = if len == 1 { + (val & 0xff) as u8 + } else { + (val >> 8) as u8 + }; + data[1] = (val & 0xff) as u8; + + match self.handle.write_control(type_vendor_out, 0, addr, index, &data, CTRL_TIMEOUT) { + Ok(n) => n, + Err(_) => 0 + } + } + + pub fn demod_read_reg(&self, page: u8, addr: u16, _len: u8) -> u16 { + let type_vendor_in = libusb::request_type(Direction::In, RequestType::Vendor, Recipient::Device); + let data: [u8; 2] = [0, 0]; + let index: u16 = page.into(); + let addr = (addr << 8) | 0x20; + let _res = self.handle.write_control(type_vendor_in, 0, addr, index, &data, CTRL_TIMEOUT); + let reg: u16 = ((data[1] as u16) << 8) | (data[0] as u16); + return reg; + } + + pub fn demod_write_reg(&self, page: u8, addr: u16, val: u16, len: u8) -> u16 { + let type_vendor_out = libusb::request_type(Direction::Out, RequestType::Vendor, Recipient::Device); + let mut data: [u8; 2] = [0, 0]; + let index: u16 = (0x10 | page).into(); + let addr = (addr << 8) | 0x20; + + data[0] = if len == 1 { + (val & 0xff) as u8 + } else { + (val >> 8) as u8 + }; + data[1] = (val & 0xff) as u8; + + let _res = self.handle.write_control(type_vendor_out, 0, addr, index, &data, CTRL_TIMEOUT); + self.demod_read_reg(0x0a, 0x01, 1) + } + + pub fn read_array(&self, block: u8, addr: u16, arr: &mut [u8], _len: u8) -> usize { + let type_vendor_in = libusb::request_type(Direction::In, RequestType::Vendor, Recipient::Device); + let index: u16 = (block as u16) << 8; + self.handle.read_control(type_vendor_in, 0, addr, index, arr, CTRL_TIMEOUT).unwrap() + } + + pub fn write_array(&self, block: u8, addr: u16, arr: &[u8], _len: u8) -> Result<usize, libusb::Error> { + let type_vendor_out = libusb::request_type(Direction::Out, RequestType::Vendor, Recipient::Device); + let index: u16 = ((block as u16) << 8) | 0x10; + self.handle.write_control(type_vendor_out, 0, addr, index, arr, CTRL_TIMEOUT) + } + + pub fn i2c_read_reg(&self, i2c_addr: u8, reg: u8) -> Result<u8, &str> { + let addr: u16 = i2c_addr.into(); + let reg: [u8; 1] = [reg]; + let mut data: [u8; 1] = [0]; + + match self.write_array(BLOCK_IICB, addr, ®, 1) { + Ok(_res) => { + self.read_array(BLOCK_IICB, addr, &mut data, 1); + Ok(data[0]) + }, + Err(_) => Err("Error") + } + } + + pub fn set_i2c_repeater(&self, on: bool) { + let val = match on { + true => 0x18, + false => 0x10 + }; + self.demod_write_reg(1, 0x01, val, 1); + } + + pub fn test_write(&self) { + self.write_reg(BLOCK_USBB, ADDR_USB_SYSCTL, 0x09, 1); + } + + pub fn init_baseband(&self) { + // init USB + self.write_reg(BLOCK_USBB, ADDR_USB_SYSCTL, 0x09, 1); + self.write_reg(BLOCK_USBB, ADDR_USB_EPA_MAXPKT, 0x0002, 2); + self.write_reg(BLOCK_USBB, ADDR_USB_EPA_CTL, 0x1002, 2); + + // power on demod + self.write_reg(BLOCK_SYSB, ADDR_SYS_DEMOD_CTL_1, 0x22, 1); + self.write_reg(BLOCK_SYSB, ADDR_SYS_DEMOD_CTL, 0xe8, 1); + + // reset demod (bit 3, soft_rst) + self.demod_write_reg(1, 0x01, 0x14, 1); + self.demod_write_reg(1, 0x01, 0x10, 1); + + // disable spectrum inversion and adjacent channel rejection + self.demod_write_reg(1, 0x15, 0x00, 1); + self.demod_write_reg(1, 0x16, 0x0000, 2); + + // clear both DDC shift and IF frequency registers + for i in 0..6 { + self.demod_write_reg(1, 0x16 + i, 0x00, 1); + } + + // set the FIR coefficients + for i in 0..FIR_LENGTH { + self.demod_write_reg(1, (0x1c + i) as u16, FIR_DEFAULT[i].into(), 1); + } + + // enable SDR mode, disable DAGC (bit 5) + self.demod_write_reg(0, 0x19, 0x05, 1); + + // init FSM state-holding register + self.demod_write_reg(1, 0x93, 0xf0, 1); + self.demod_write_reg(1, 0x94, 0x0f, 1); + + // disable AGC (en_dagc, bit 0) (this seems to have no effect) + self.demod_write_reg(1, 0x11, 0x00, 1); + + // disable RF and IF AGC loop + self.demod_write_reg(1, 0x04, 0x00, 1); + + // disable PID filter (enable_PID = 0) + self.demod_write_reg(0, 0x61, 0x60, 1); + + // opt_adc_iq = 0, default ADC_I/ADC_Q datapath + self.demod_write_reg(0, 0x06, 0x80, 1); + + // Enable Zero-IF mode (en_bbin bit), DC cancellation (en_dc_est), + // IQ estimation/compensation (en_iq_comp, en_iq_est) + self.demod_write_reg(1, 0xb1, 0x1b, 1); + + // disable 4.096 MHz clock output on pin TP_CK0 + self.demod_write_reg(0, 0x0d, 0x83, 1); + } + + pub fn deinit_baseband(&self) { + // deinit tuner? + + // power off demod and ADCs + self.write_reg(BLOCK_SYSB, ADDR_SYS_DEMOD_CTL, 0x20, 1); + } +} |
