From e52ac7fea53542970ead13617acd285768ac936b Mon Sep 17 00:00:00 2001 From: Alexander Hurd Date: Mon, 18 Jun 2018 00:30:21 -0400 Subject: [PATCH] tx updates --- Registation.cpp | 10 +- Sensor.cpp | 10 +- Settings.cpp | 50 +++++----- SoapySidekiq.hpp | 6 +- Streaming.cpp | 232 +++++++++++++++++++++++++++++++++-------------- 5 files changed, 206 insertions(+), 102 deletions(-) diff --git a/Registation.cpp b/Registation.cpp index 35643a0..2fc7a95 100644 --- a/Registation.cpp +++ b/Registation.cpp @@ -14,7 +14,7 @@ static std::vector findSidekiq(const SoapySDR::Kwargs &args) { skiq_xport_type_t type = skiq_xport_type_auto; /* query the list of all Sidekiq cards on the PCIe interface */ - if(skiq_get_cards(type, &number_of_cards, card_list) < 0){ + if(skiq_get_cards(type, &number_of_cards, card_list) != 0){ SoapySDR_log(SOAPY_SDR_ERROR, "Failure: skiq_get_cards"); } @@ -23,10 +23,14 @@ static std::vector findSidekiq(const SoapySDR::Kwargs &args) { bool deviceAvailable = false; /* determine the serial number based on the card number */ - skiq_read_serial_string(i, &serial_str); + if(skiq_read_serial_string(i, &serial_str) != 0){ + SoapySDR_log(SOAPY_SDR_ERROR, "Failure: skiq_read_serial_string"); + } /* check if card is avail */ - skiq_is_card_avail(i, &card_owner); + if(skiq_is_card_avail(i, &card_owner) != 0){ + SoapySDR_log(SOAPY_SDR_ERROR, "Failure: skiq_is_card_avail"); + } deviceAvailable = (card_owner == getpid()); // owner must be this process(pid) if (!deviceAvailable) { SoapySDR_logf(SOAPY_SDR_WARNING, "Unable to access card #%d, owner pid (%d)", i, card_owner); diff --git a/Sensor.cpp b/Sensor.cpp index cf0da31..28ecd6e 100644 --- a/Sensor.cpp +++ b/Sensor.cpp @@ -16,7 +16,9 @@ SoapySDR::ArgInfo SoapySidekiq::getSensorInfo(const std::string &key) const { std::string SoapySidekiq::readSensor(const std::string &key) const { if (key.compare("temperature")) { int8_t temp = 0; - skiq_read_temp(card, &temp); + if (skiq_read_temp(card, &temp) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_temp (card %i)", card); + } return std::to_string(temp); } bool supported = false; @@ -25,18 +27,18 @@ std::string SoapySidekiq::readSensor(const std::string &key) const { SoapySDR_logf(SOAPY_SDR_WARNING, "Acceleration not supported by card %i", card); return "{}"; } - if (skiq_write_accel_state(card, 1) < 0) {// enable + if (skiq_write_accel_state(card, 1) != 0) {// enable SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_accel_state (card %i)", card); return "{}"; } int16_t x_data = 0; int16_t y_data = 0; int16_t z_data = 0; - if (skiq_read_accel(card, &x_data, &y_data, &z_data) < 0) { + if (skiq_read_accel(card, &x_data, &y_data, &z_data) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_accel (card %i)", card); return "{}"; } - if (skiq_write_accel_state(card, 0) < 0) { // disable + if (skiq_write_accel_state(card, 0) != 0) { // disable SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_accel_state (card %i)", card); return "{}"; }; diff --git a/Settings.cpp b/Settings.cpp index 305b94f..237f67d 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -48,13 +48,13 @@ SoapySidekiq::SoapySidekiq(const SoapySDR::Kwargs &args) { SoapySDR_logf(SOAPY_SDR_DEBUG, "Sidekiq opening card %d", card); /* init sidekiq */ - if (skiq_init(type, level, &card, 1) < 0) { + if (skiq_init(type, level, &card, 1) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_init (card %d)", card); } } SoapySidekiq::~SoapySidekiq(void) { - if (skiq_exit() < 0) { + if (skiq_exit() != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_exit", card); } } @@ -119,7 +119,7 @@ bool SoapySidekiq::hasDCOffsetMode(const int direction, const size_t channel) co void SoapySidekiq::setDCOffsetMode(const int direction, const size_t channel, const bool automatic) { if (direction == SOAPY_SDR_RX) { - if (skiq_write_rx_dc_offset_corr(card, rx_hdl, automatic) < 0) { + if (skiq_write_rx_dc_offset_corr(card, rx_hdl, automatic) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_dc_offset_corr (card %d, enable %d)", card, automatic); } } @@ -128,7 +128,7 @@ void SoapySidekiq::setDCOffsetMode(const int direction, const size_t channel, co bool SoapySidekiq::getDCOffsetMode(const int direction, const size_t channel) const { bool enable; if (direction == SOAPY_SDR_RX) { - if (skiq_read_rx_dc_offset_corr(card, rx_hdl, &enable) < 0) { + if (skiq_read_rx_dc_offset_corr(card, rx_hdl, &enable) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_dc_offset_corr (card %d)", card); } return enable; @@ -157,7 +157,7 @@ void SoapySidekiq::setGainMode(const int direction, const size_t channel, const "Setting Sidekiq RX Gain Mode: %s", automatic ? "skiq_rx_gain_auto" : "skiq_rx_gain_manual"); skiq_rx_gain_t mode = automatic ? skiq_rx_gain_auto : skiq_rx_gain_manual; - if (skiq_write_rx_gain_mode(card, rx_hdl, mode) < 0) { + if (skiq_write_rx_gain_mode(card, rx_hdl, mode) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_gain_mode (card %d, mode %d)", card, mode); } } @@ -166,7 +166,7 @@ void SoapySidekiq::setGainMode(const int direction, const size_t channel, const bool SoapySidekiq::getGainMode(const int direction, const size_t channel) const { if (direction == SOAPY_SDR_RX) { skiq_rx_gain_t p_gain_mode; - if (skiq_read_rx_gain_mode(card, rx_hdl, &p_gain_mode) < 0) { + if (skiq_read_rx_gain_mode(card, rx_hdl, &p_gain_mode) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_gain_mode (card %d)", card); } return p_gain_mode == skiq_rx_gain_auto; @@ -183,7 +183,7 @@ void SoapySidekiq::setGain(const int direction, const size_t channel, const doub void SoapySidekiq::setGain(const int direction, const size_t channel, const std::string &name, const double value) { if (direction == SOAPY_SDR_RX) { - if (skiq_write_rx_gain(card, rx_hdl, value) < 0) { + if (skiq_write_rx_gain(card, rx_hdl, value) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_gain (card %d, value %d)", card, value); } } @@ -192,7 +192,7 @@ void SoapySidekiq::setGain(const int direction, const size_t channel, const std: double SoapySidekiq::getGain(const int direction, const size_t channel, const std::string &name) const { if (direction == SOAPY_SDR_RX) { uint8_t gain_index; - if (skiq_read_rx_gain(card, rx_hdl, &gain_index) < 0) { + if (skiq_read_rx_gain(card, rx_hdl, &gain_index) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_gain (card %d)", card); } return static_cast(gain_index); @@ -205,7 +205,7 @@ SoapySDR::Range SoapySidekiq::getGainRange(const int direction, const size_t cha if (direction == SOAPY_SDR_RX) { uint8_t gain_index_min; uint8_t gain_index_max; - if (skiq_read_rx_gain_index_range(card, rx_hdl, &gain_index_min, &gain_index_max) < 0) { + if (skiq_read_rx_gain_index_range(card, rx_hdl, &gain_index_min, &gain_index_max) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_gain_index_range (card %d)", card); } return SoapySDR::Range(gain_index_max, gain_index_max); @@ -227,7 +227,7 @@ void SoapySidekiq::setFrequency(const int direction, rx_center_frequency = (uint64_t) frequency; resetBuffer = true; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting rx center freq: %d", rx_center_frequency); - if (skiq_write_rx_LO_freq(card, rx_hdl, rx_center_frequency) < 0) { + if (skiq_write_rx_LO_freq(card, rx_hdl, rx_center_frequency) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_LO_freq (card %d, frequency %d)", card, @@ -239,7 +239,7 @@ void SoapySidekiq::setFrequency(const int direction, tx_center_frequency = (uint64_t) frequency; resetBuffer = true; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting tx center freq: %d", tx_center_frequency); - if (skiq_write_tx_LO_freq(card, tx_hdl, tx_center_frequency) < 0) { + if (skiq_write_tx_LO_freq(card, tx_hdl, tx_center_frequency) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_LO_freq (card %d, frequency %d)", card, @@ -252,7 +252,7 @@ double SoapySidekiq::getFrequency(const int direction, const size_t channel, con if (direction == SOAPY_SDR_RX && name == "RF") { uint64_t freq; double tuned_freq; - if (skiq_read_rx_LO_freq(card, rx_hdl, &freq, &tuned_freq) < 0) { + if (skiq_read_rx_LO_freq(card, rx_hdl, &freq, &tuned_freq) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_LO_freq (card %d)", card); } return static_cast(freq); @@ -261,7 +261,7 @@ double SoapySidekiq::getFrequency(const int direction, const size_t channel, con if (direction == SOAPY_SDR_TX && name == "RF") { uint64_t freq; double tuned_freq; - if (skiq_read_tx_LO_freq(card, tx_hdl, &freq, &tuned_freq) < 0) { + if (skiq_read_tx_LO_freq(card, tx_hdl, &freq, &tuned_freq) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_tx_LO_freq (card %d)", card); } return static_cast(freq); @@ -284,14 +284,14 @@ SoapySDR::RangeList SoapySidekiq::getFrequencyRange(const int direction, uint64_t min; if (direction == SOAPY_SDR_RX && name == "RF") { - if (skiq_read_rx_LO_freq_range(card, &max, &min) < 0) { + if (skiq_read_rx_LO_freq_range(card, &max, &min) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_LO_freq_range (card %d)", card); } results.push_back(SoapySDR::Range(min, max)); } if (direction == SOAPY_SDR_TX && name == "RF") { - if (skiq_read_tx_LO_freq_range(card, &max, &min) < 0) { + if (skiq_read_tx_LO_freq_range(card, &max, &min) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_tx_LO_freq_range (card %d)", card); } results.push_back(SoapySDR::Range(min, max)); @@ -317,7 +317,7 @@ void SoapySidekiq::setSampleRate(const int direction, const size_t channel, cons rx_sample_rate = (uint32_t) rate; resetBuffer = true; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting rx sample rate: %d", rx_sample_rate); - if (skiq_write_rx_sample_rate_and_bandwidth(card, rx_hdl, rx_sample_rate, rx_bandwidth) < 0) { + if (skiq_write_rx_sample_rate_and_bandwidth(card, rx_hdl, rx_sample_rate, rx_bandwidth) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_sample_rate_and_bandwidth (card %d, sample_rate %d, bandwidth %d)", card, @@ -330,7 +330,7 @@ void SoapySidekiq::setSampleRate(const int direction, const size_t channel, cons tx_sample_rate = (uint32_t) rate; resetBuffer = true; SoapySDR_logf(SOAPY_SDR_DEBUG, "Setting tx sample rate: %d", tx_sample_rate); - if (skiq_write_tx_sample_rate_and_bandwidth(card, tx_hdl, tx_sample_rate, tx_bandwidth) < 0) { + if (skiq_write_tx_sample_rate_and_bandwidth(card, tx_hdl, tx_sample_rate, tx_bandwidth) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_sample_rate_and_bandwidth (card %d, sample_rate %d, bandwidth %d)", card, @@ -344,14 +344,14 @@ double SoapySidekiq::getSampleRate(const int direction, const size_t channel) co uint32_t rate; double actual_rate; if (direction == SOAPY_SDR_RX) { - if (skiq_read_rx_sample_rate(card, rx_hdl, &rate, &actual_rate) < 0) { + if (skiq_read_rx_sample_rate(card, rx_hdl, &rate, &actual_rate) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_sample_rate (card %d)", card); } return static_cast(rate); } if (direction == SOAPY_SDR_TX) { - if (skiq_read_tx_sample_rate(card, tx_hdl, &rate, &actual_rate)) { + if (skiq_read_tx_sample_rate(card, tx_hdl, &rate, &actual_rate) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_tx_sample_rate (card %d)", card); } return static_cast(rate); @@ -364,11 +364,11 @@ std::vector SoapySidekiq::listSampleRates(const int direction, const siz std::vector results; uint32_t min_sample_rate; - if (skiq_read_min_sample_rate(card, &min_sample_rate) < 0) { + if (skiq_read_min_sample_rate(card, &min_sample_rate) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_min_sample_rate (card %d)", card); } uint32_t max_sample_rate; - if (skiq_read_max_sample_rate(card, &max_sample_rate) < 0) { + if (skiq_read_max_sample_rate(card, &max_sample_rate) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_min_sample_rate (card %d)", card); } @@ -385,7 +385,7 @@ std::vector SoapySidekiq::listSampleRates(const int direction, const siz void SoapySidekiq::setBandwidth(const int direction, const size_t channel, const double bw) { if (direction == SOAPY_SDR_RX) { rx_bandwidth = (uint32_t) bw; - if (skiq_write_rx_sample_rate_and_bandwidth(card, rx_hdl, rx_sample_rate, rx_bandwidth) < 0) { + if (skiq_write_rx_sample_rate_and_bandwidth(card, rx_hdl, rx_sample_rate, rx_bandwidth) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_sample_rate_and_bandwidth (card %d, sample_rate %d, bandwidth %d)", card, @@ -396,7 +396,7 @@ void SoapySidekiq::setBandwidth(const int direction, const size_t channel, const if (direction == SOAPY_SDR_TX) { tx_bandwidth = (uint32_t) bw; - if (skiq_write_tx_sample_rate_and_bandwidth(card, tx_hdl, tx_sample_rate, tx_bandwidth) < 0) { + if (skiq_write_tx_sample_rate_and_bandwidth(card, tx_hdl, tx_sample_rate, tx_bandwidth) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_sample_rate_and_bandwidth (card %d, sample_rate %d, bandwidth %d)", card, @@ -412,13 +412,13 @@ double SoapySidekiq::getBandwidth(const int direction, const size_t channel) con uint32_t bandwidth; uint32_t actual_bandwidth; if (direction == SOAPY_SDR_RX) { - if (skiq_read_rx_sample_rate_and_bandwidth(card, rx_hdl, &rate, &actual_rate, &bandwidth, &actual_bandwidth) < 0) { + if (skiq_read_rx_sample_rate_and_bandwidth(card, rx_hdl, &rate, &actual_rate, &bandwidth, &actual_bandwidth) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_rx_sample_rate_and_bandwidth (card %d)", card); } } if (direction == SOAPY_SDR_TX) { - if (skiq_read_tx_sample_rate_and_bandwidth(card, tx_hdl, &rate, &actual_rate, &bandwidth, &actual_bandwidth) < 0) { + if (skiq_read_tx_sample_rate_and_bandwidth(card, tx_hdl, &rate, &actual_rate, &bandwidth, &actual_bandwidth) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_read_tx_sample_rate_and_bandwidth (card %d)", card); } } diff --git a/SoapySidekiq.hpp b/SoapySidekiq.hpp index 2e8fdff..97601b8 100644 --- a/SoapySidekiq.hpp +++ b/SoapySidekiq.hpp @@ -17,7 +17,7 @@ #include #define DEFAULT_BUFFER_LENGTH (65536) -#define DEFAULT_NUM_BUFFERS (8) +#define DEFAULT_NUM_BUFFERS (10) #define DEFAULT_ELEMS_PER_SAMPLE (2) class SoapySidekiq : public SoapySDR::Device { @@ -208,6 +208,10 @@ class SoapySidekiq : public SoapySDR::Device { std::string readSetting(const std::string &key) const; private: + + SoapySDR::Stream* const TX_STREAM = (SoapySDR::Stream*) 0x1; + SoapySDR::Stream* const RX_STREAM = (SoapySDR::Stream*) 0x2; + // sidekiq card uint8_t card; diff --git a/Streaming.cpp b/Streaming.cpp index 15de244..7146160 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -3,6 +3,7 @@ #include "SoapySidekiq.hpp" #include #include // memcpy +#include std::vector SoapySidekiq::getStreamFormats(const int direction, const size_t channel) const { std::vector formats; @@ -50,17 +51,17 @@ void SoapySidekiq::rx_receive_operation(void) { SoapySDR_log(SOAPY_SDR_INFO, "Starting RX Sidekiq Thread"); /* set rx source as iq data */ - if (skiq_write_rx_data_src(card, rx_hdl, skiq_data_src_iq) < 0) { + if (skiq_write_rx_data_src(card, rx_hdl, skiq_data_src_iq) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_rx_data_src (card %d)", card); } /* set a modest rx timeout */ - if (skiq_set_rx_transfer_timeout(card, 100000) < 0) { + if (skiq_set_rx_transfer_timeout(card, 100000) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_set_rx_transfer_timeout (card %d)", card); } /* start rx streaming */ - if (skiq_start_rx_streaming(card, rx_hdl) < 0) { + if (skiq_start_rx_streaming(card, rx_hdl) != 0) { SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_start_rx_streaming (card %d)", card); } @@ -68,16 +69,23 @@ void SoapySidekiq::rx_receive_operation(void) { skiq_rx_block_t *p_rx_block; uint32_t len; + // metadata + uint64_t overload = 0; + // loop until stream is deactivated while (rx_running) { + // check for overflow - if (_buf_count == numBuffers) { + if (_buf_count == numBuffers || overload) { SoapySDR_log(SOAPY_SDR_WARNING, "Detected overflow Event in RX Sidekiq Thread"); _overflowEvent = true; } /* blocking skiq_receive */ if (skiq_receive(card, &rx_hdl, &p_rx_block, &len) == skiq_rx_status_success) { + // metadata + overload = p_rx_block->overload; + // number of i and q samples uint32_t num_samples = (len - SKIQ_RX_HEADER_SIZE_IN_BYTES) / sizeof(int16_t); @@ -152,68 +160,78 @@ SoapySDR::Stream *SoapySidekiq::setupStream(const int direction, throw std::runtime_error("setupStream invalid channel selection"); } - // check the format - if (format == "CS16") { - useShort = true; - shortsPerWord = 1; - bufferLength = bufferElems * elementsPerSample * shortsPerWord; - SoapySDR_log(SOAPY_SDR_INFO, "Using format CS16."); - } else if (format == "CF32") { - useShort = false; - shortsPerWord = sizeof(float) / sizeof(short); - bufferLength = - bufferElems * elementsPerSample * shortsPerWord; // allocate enough space for floats instead of shorts - SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32."); - } else { - throw std::runtime_error( - "setupStream invalid format '" + format - + "' -- Only CS16 or CF32 is supported by SoapySidekiq module."); - } + if (direction == SOAPY_SDR_RX) { + // check the format + if (format == "CS16") { + useShort = true; + shortsPerWord = 1; + bufferLength = bufferElems * elementsPerSample * shortsPerWord; + SoapySDR_log(SOAPY_SDR_INFO, "Using format CS16."); + } else if (format == "CF32") { + useShort = false; + shortsPerWord = sizeof(float) / sizeof(short); + bufferLength = + bufferElems * elementsPerSample * shortsPerWord; // allocate enough space for floats instead of shorts + SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32."); + } else { + throw std::runtime_error( + "setupStream invalid format '" + format + + "' -- Only CS16 or CF32 is supported by SoapySidekiq module."); + } - bufferLength = DEFAULT_BUFFER_LENGTH; - if (args.count("bufflen") != 0) { - try { - int bufferLength_in = std::stoi(args.at("bufflen")); - if (bufferLength_in > 0) { - bufferLength = bufferLength_in; + bufferLength = DEFAULT_BUFFER_LENGTH; + if (args.count("bufflen") != 0) { + try { + int bufferLength_in = std::stoi(args.at("bufflen")); + if (bufferLength_in > 0) { + bufferLength = bufferLength_in; + } } + catch (const std::invalid_argument &) {} } - catch (const std::invalid_argument &) {} - } - SoapySDR_logf(SOAPY_SDR_DEBUG, "Sidekiq Using buffer length %d", bufferLength); - - numBuffers = DEFAULT_NUM_BUFFERS; - if (args.count("buffers") != 0) { - try { - int numBuffers_in = std::stoi(args.at("buffers")); - if (numBuffers_in > 0) { - numBuffers = numBuffers_in; + SoapySDR_logf(SOAPY_SDR_DEBUG, "Sidekiq Using rx buffer length %d", bufferLength); + + numBuffers = DEFAULT_NUM_BUFFERS; + if (args.count("buffers") != 0) { + try { + int numBuffers_in = std::stoi(args.at("buffers")); + if (numBuffers_in > 0) { + numBuffers = numBuffers_in; + } } + catch (const std::invalid_argument &) {} } - catch (const std::invalid_argument &) {} - } - SoapySDR_logf(SOAPY_SDR_DEBUG, "Sidekiq Using %d buffers", numBuffers); + SoapySDR_logf(SOAPY_SDR_DEBUG, "Sidekiq Using %d rx buffers", numBuffers); - // buff mutext - { - std::lock_guard lock(_buf_mutex); + // buff mutext + { + std::lock_guard lock(_buf_mutex); - // clear async fifo counts - _buf_tail = 0; - _buf_count = 0; - _buf_head = 0; + // clear async fifo counts + _buf_tail = 0; + _buf_count = 0; + _buf_head = 0; - // allocate buffers - _buffs.resize(numBuffers); - for (auto &buff : _buffs) buff.reserve(bufferLength); - for (auto &buff : _buffs) buff.clear(); + // allocate buffers + _buffs.resize(numBuffers); + for (auto &buff : _buffs) buff.reserve(bufferLength); + for (auto &buff : _buffs) buff.clear(); + } + return RX_STREAM; + } else if (direction == SOAPY_SDR_TX) { + return TX_STREAM; + } else { + throw std::runtime_error("Invalid direction"); } - return (SoapySDR::Stream *) this; } void SoapySidekiq::closeStream(SoapySDR::Stream *stream) { + this->deactivateStream(stream, 0, 0); - _buffs.clear(); + + if (stream == RX_STREAM) { + _buffs.clear(); + } } size_t SoapySidekiq::getStreamMTU(SoapySDR::Stream *stream) const { @@ -225,12 +243,22 @@ int SoapySidekiq::activateStream(SoapySDR::Stream *stream, const long long timeNs, const size_t numElems) { if (flags != 0) return SOAPY_SDR_NOT_SUPPORTED; - resetBuffer = true; - bufferedElems = 0; - // start the receive thread - if (!_rx_receive_thread.joinable()) { - _rx_receive_thread = std::thread(&SoapySidekiq::rx_receive_operation, this); + if (stream == RX_STREAM) { + resetBuffer = true; + bufferedElems = 0; + + // start the receive thread + if (!_rx_receive_thread.joinable()) { + SoapySDR_logf(SOAPY_SDR_DEBUG, "Start RX"); + _rx_receive_thread = std::thread(&SoapySidekiq::rx_receive_operation, this); + } + } else if (stream == TX_STREAM) { + SoapySDR_logf(SOAPY_SDR_DEBUG, "Start TX"); + /* start tx streaming */ + if (skiq_start_tx_streaming(card, tx_hdl) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_start_tx_streaming (card %d)", card); + } } return 0; @@ -238,16 +266,22 @@ int SoapySidekiq::activateStream(SoapySDR::Stream *stream, int SoapySidekiq::deactivateStream(SoapySDR::Stream *stream, const int flags, const long long timeNs) { if (flags != 0) return SOAPY_SDR_NOT_SUPPORTED; + if (stream == RX_STREAM) { + // stop receive thread + if (_rx_receive_thread.joinable()) { + rx_running = false; + _rx_receive_thread.join(); + } - // stop receive thread - if (_rx_receive_thread.joinable()) { - rx_running = false; - _rx_receive_thread.join(); - } - - /* stop rx streaming */ - if (skiq_stop_rx_streaming(card, rx_hdl) < 0) { - SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_stop_rx_streaming (card %d)", card); + /* stop rx streaming */ + if (skiq_stop_rx_streaming(card, rx_hdl) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_stop_rx_streaming (card %d)", card); + } + } else if (stream == TX_STREAM) { + /* stop tx streaming */ + if (skiq_stop_tx_streaming(card, tx_hdl) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_stop_tx_streaming (card %d)", card); + } } return 0; @@ -259,6 +293,10 @@ int SoapySidekiq::readStream(SoapySDR::Stream *stream, int &flags, long long &timeNs, const long timeoutUs) { + if (stream != RX_STREAM) { + return SOAPY_SDR_NOT_SUPPORTED; + } + // drop remainder buffer on reset if (resetBuffer && bufferedElems != 0) { bufferedElems = 0; @@ -308,7 +346,51 @@ int SoapySidekiq::writeStream(SoapySDR::Stream *stream, int &flags, const long long timeNs, const long timeoutUs) { -return -1; + + if (stream != TX_STREAM) { + return SOAPY_SDR_NOT_SUPPORTED; + } + + const uint32_t block_size_in_words = 1020; + + // tx data flow mode + if (skiq_write_tx_data_flow_mode(card, tx_hdl, skiq_tx_immediate_data_flow_mode) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_data_flow_mode (card %d)", card); + } + // tx block size + if (skiq_write_tx_block_size(card, tx_hdl, block_size_in_words) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_block_size (card %d)", card); + } + // transfer mode (sync for now) + if (skiq_write_tx_transfer_mode(card, tx_hdl, skiq_tx_transfer_mode_sync) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_block_size (card %d)", card); + } + // tx attenuation + if (skiq_write_tx_attenuation(card, tx_hdl, 0) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_write_tx_attenuation (card %d)", card); + } + + + size_t data_bytes = numElems * 2 * sizeof(int16_t); + uint32_t num_blocks = (data_bytes / (block_size_in_words * 2)); + if ((data_bytes % (block_size_in_words * 4)) == 0) { + num_blocks++; + } + + uint32_t i; + uint64_t timestamp = 0; + + for (i = 0; i < num_blocks; i++) { + skiq_tx_block_t *p_block = skiq_tx_block_allocate(block_size_in_words); + memcpy(p_block->data, buffs[0], block_size_in_words); + skiq_tx_set_block_timestamp(p_block, timestamp); + if (skiq_transmit(card, tx_hdl, p_block, NULL) != 0) { + SoapySDR_logf(SOAPY_SDR_ERROR, "Failure: skiq_transmit (card %d)", card); + } + timestamp += block_size_in_words; + } + + return numElems; } /******************************************************************* @@ -332,6 +414,10 @@ int SoapySidekiq::acquireReadBuffer(SoapySDR::Stream *stream, int &flags, long long &timeNs, const long timeoutUs) { + if (stream != RX_STREAM) { + return SOAPY_SDR_NOT_SUPPORTED; + } + std::unique_lock lock(_buf_mutex); // reset is issued by various settings @@ -373,6 +459,9 @@ int SoapySidekiq::acquireReadBuffer(SoapySDR::Stream *stream, } void SoapySidekiq::releaseReadBuffer(SoapySDR::Stream *stream, const size_t handle) { + if (stream != RX_STREAM) { + throw std::runtime_error("Invalid stream"); + } SoapySDR_logf(SOAPY_SDR_TRACE, "Release Read Buffer %d", handle); std::lock_guard lock(_buf_mutex); _buffs[handle].clear(); @@ -383,6 +472,9 @@ int SoapySidekiq::acquireWriteBuffer(SoapySDR::Stream *stream, size_t &handle, void **buffs, const long timeoutUs) { + if (stream != TX_STREAM) { + return SOAPY_SDR_NOT_SUPPORTED; + } return -1; @@ -393,5 +485,7 @@ void SoapySidekiq::releaseWriteBuffer(SoapySDR::Stream *stream, const size_t numElems, int &flags, const long long timeNs) { - + if (stream != TX_STREAM) { + throw std::runtime_error("Invalid stream"); + } } \ No newline at end of file