#include "usb_if.hpp" #include #include #include #include #include #include #include using namespace std; // AD9361 driver platform shim static RFTool::USBInterface usb; extern "C" { #include "ad9361/platform/platform.h" #include "usb_platform.h" int32_t spi_init(uint32_t device_id, uint8_t clk_pha, uint8_t clk_pol) { return 0; }; int32_t spi_read(uint8_t *data, uint8_t bytes_number) { throw runtime_error("spi_read not supported, use spi_write_then_read"); }; int spi_write_then_read(struct spi_device *spi, const unsigned char *txbuf, unsigned n_tx, unsigned char *rxbuf, unsigned n_rx) { if (n_tx < 2) throw runtime_error("n_tx must be >= 2"); vector payload; payload.push_back(uint8_t(n_tx + n_rx)); for (int i = 0; i < n_tx; i++) payload.push_back(txbuf[i]); for (int i = 0; i < n_rx; i++) payload.push_back(0); uint8_t cmd_buf[32], resp_buf[32]; usb.build_command(0x10, payload, cmd_buf); if (!usb.exec_command(cmd_buf, true, resp_buf)) return -1; RFTool::swap_endian(resp_buf, 32); for (int i = 0; i < n_rx; i++) { rxbuf[i] = resp_buf[6 + n_tx + i]; } return 0; }; void gpio_init(uint32_t device_id){}; void gpio_direction(uint8_t pin, uint8_t direction){}; bool gpio_is_valid(int number) { return (number == 0); }; void gpio_set_value(unsigned gpio, int value) { // resetn is ctrl sig bit 1 and inverted (so active high) if (gpio == 0) { if (value == 0) { usb.set_fpga_ctrl(0x02); } else { usb.set_fpga_ctrl(0x00); } } }; void enter_rx_streaming_mode() { uint8_t cmd_buf[32], resp_buf[32]; usb.build_command(0x30, vector{}, cmd_buf); usb.exec_command(cmd_buf, false, resp_buf); }; void leave_rx_streaming_mode() { uint8_t cmd_buf[32], resp_buf[32]; usb.build_command(0x31, vector{}, cmd_buf); usb.flush(); usb.exec_command(cmd_buf, true, resp_buf); usb.flush(); }; static const uint8_t rx_magic[4] = {0x52, 0x58, 0x49, 0x51}; // static const uint8_t rx_magic[4] = {0x51, 0x49, 0x58, 0x52}; const int rx_packet_len = 4096; static bool first_rx_get = true; static uint8_t rx_buffer_a[rx_packet_len], rx_buffer_b[rx_packet_len]; static uint8_t *current_packet = rx_buffer_a; static uint8_t *last_packet = rx_buffer_b; void rx_purge() { first_rx_get = true; }; int rx_get_data(iq_sample *buf) { if (!usb.get_rx_packet(current_packet)) return 0; int out_idx = 0; // Workaround for a broken USB interface ATM for (int i = 0; i < (rx_packet_len - 4); i++) { if (((current_packet[i + 0] & 0xC0) == 0x00) && ((current_packet[i + 1] & 0xC0) == 0x40) && ((current_packet[i + 2] & 0xC0) == 0x80) && ((current_packet[i + 3] & 0xC0) == 0xC0)) { // Extract I and Q uint16_t i_raw = (uint16_t(current_packet[i + 1] & 0x3F) << 6) | (uint16_t(current_packet[i]) & 0x3F); uint16_t q_raw = (uint16_t(current_packet[i + 3] & 0x3F) << 6) | (uint16_t(current_packet[i + 2]) & 0x3F); // Sign extend buf[out_idx].i = ((i_raw & 0x800) == 0x800) ? (i_raw | 0xF000) : i_raw; buf[out_idx].q = ((q_raw & 0x800) == 0x800) ? (q_raw | 0xF000) : q_raw; out_idx++; i += 3; } else { // cout << "bad alignment" << endl; } } return out_idx; } void udelay(unsigned long usecs) { timespec dly; dly.tv_sec = 0; dly.tv_nsec = usecs * 1000; nanosleep(&dly, nullptr); }; void mdelay(unsigned long msecs) { msleep_interruptible(msecs); } unsigned long msleep_interruptible(unsigned int msecs) { this_thread::sleep_for(chrono::milliseconds(msecs)); return 0; }; // AXIADC functions are not yet implemented and dummies to prevent linker errors void axiadc_init(struct ad9361_rf_phy *phy){}; int axiadc_post_setup(struct ad9361_rf_phy *phy) { return 0; }; unsigned int axiadc_read(struct axiadc_state *st, unsigned long reg) { return 0; }; void axiadc_write(struct axiadc_state *st, unsigned reg, unsigned val){}; int axiadc_set_pnsel(struct axiadc_state *st, int channel, enum adc_pn_sel sel) { return 0; } void axiadc_idelay_set(struct axiadc_state *st, unsigned lane, unsigned val){}; };