From e904cf0165ee80989c6d86572684997109d21fa8 Mon Sep 17 00:00:00 2001 From: F5OEO Date: Mon, 10 Dec 2018 19:51:44 +0000 Subject: First working minimal live version --- src/ConfigParser.cpp | 13 +++-- src/Utils.cpp | 3 + src/output/Lime.cpp | 154 ++++++++++++++++++++++++++++++++++++--------------- src/output/Lime.h | 7 ++- 4 files changed, 124 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 8c80513..209ebe4 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -310,11 +310,14 @@ static void parse_configfile( #if defined(HAVE_LIMESDR) else if (output_selected == "limesdr") { auto& outputlime_conf = mod_settings.sdr_device_config; - outputlime_conf.device = pt.Get("soapyoutput.device", ""); - outputlime_conf.masterClockRate = pt.GetInteger("soapyoutput.master_clock_rate", 0); - - outputlime_conf.txgain = pt.GetReal("soapyoutput.txgain", 0.0); - outputlime_conf.tx_antenna = pt.Get("soapyoutput.tx_antenna", ""); + outputlime_conf.device = pt.Get("limeoutput.device", ""); + outputlime_conf.masterClockRate = pt.GetInteger("limeoutput.master_clock_rate", 0); + + outputlime_conf.txgain = pt.GetReal("limeoutput.txgain", 0.0); + outputlime_conf.txgain = pt.GetReal("limeoutput.txgain", 0.0); + outputlime_conf.txgain = pt.GetReal("limeoutput.txgain", 0.0); + outputlime_conf.txgain = pt.GetReal("limeoutput.txgain", 0.0); + outputlime_conf.tx_antenna = pt.Get("limeoutput.tx_antenna", ""); outputlime_conf.lo_offset = pt.GetReal("soapyoutput.lo_offset", 0.0); outputlime_conf.frequency = pt.GetReal("soapyoutput.frequency", 0); std::string chan = pt.Get("soapyoutput.channel", ""); diff --git a/src/Utils.cpp b/src/Utils.cpp index 50af4fb..fd4f659 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -55,6 +55,9 @@ static void printHeader() #if defined(HAVE_SOAPYSDR) "output_soapysdr " << #endif +#if defined(HAVE_LIMESDR) + "output_limesdr " << +#endif #if defined(__FAST_MATH__) "fast-math " << #endif diff --git a/src/output/Lime.cpp b/src/output/Lime.cpp index e67e90e..d553187 100644 --- a/src/output/Lime.cpp +++ b/src/output/Lime.cpp @@ -31,7 +31,6 @@ DESCRIPTION: #ifdef HAVE_LIMESDR -//#include #include #include #include @@ -84,7 +83,66 @@ Lime::Lime(SDRDeviceConfig& config) : etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); throw std::runtime_error("Cannot init LimeSDR output device"); } + + if (LMS_EnableChannel(m_device, LMS_CH_TX, m_channel, true) < 0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot channel LimeSDR output device"); + } + + if (LMS_SetSampleRate(m_device, m_conf.masterClockRate, 0) < 0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot channel LimeSDR output device"); + } + float_type host_sample_rate=0.0; + if (LMS_GetSampleRate(m_device, LMS_CH_TX, m_channel, &host_sample_rate, NULL) < 0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot getsamplerate LimeSDR output device"); + } + etiLog.level(info) << "LimeSDR master clock rate set to " << + std::fixed << std::setprecision(4) << + host_sample_rate/1000.0 << " kHz"; + + if (LMS_SetLOFrequency(m_device, LMS_CH_TX,m_channel, m_conf.frequency) < 0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot Frequency LimeSDR output device"); + } + + float_type cur_frequency=0.0; + + if (LMS_GetLOFrequency(m_device, LMS_CH_TX,m_channel, &cur_frequency)<0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot GetFrequency LimeSDR output device"); + } + etiLog.level(info) << "LimeSDR:Actual frequency: " << + std::fixed << std::setprecision(3) << + cur_frequency / 1000.0 << " kHz."; + + if (LMS_SetNormalizedGain(m_device, LMS_CH_TX, m_channel, m_conf.txgain/100.0) < 0) //value 0..100 -> Normalize + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot Gain LimeSDR output device"); + } + + + if (LMS_SetAntenna(m_device, LMS_CH_TX, m_channel, LMS_PATH_TX2) < 0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot Antenna LimeSDR output device"); + } + + + double bandwidth_calibrating=2.5e6; // Minimal bandwidth + if (LMS_Calibrate(m_device, LMS_CH_TX, m_channel, bandwidth_calibrating, 0) < 0) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot Gain LimeSDR output device"); + } /* m_device->setMasterClockRate(m_conf.masterClockRate); @@ -130,17 +188,23 @@ Lime::Lime(SDRDeviceConfig& config) : Lime::~Lime() { - /* - if (m_device != nullptr) { - if (m_tx_stream != nullptr) { - m_device->closeStream(m_tx_stream); + + if (m_device != nullptr) + { + + //if (m_tx_stream != nullptr) + { + LMS_StopStream(&m_tx_stream); + LMS_DestroyStream(m_device, &m_tx_stream); } - + /* if (m_rx_stream != nullptr) { m_device->closeStream(m_rx_stream); } - SoapySDR::Device::unmake(m_device); - }*/ + */ + LMS_EnableChannel(m_device, LMS_CH_TX, m_channel, false); + LMS_Close(m_device); + } } void Lime::tune(double lo_offset, double frequency) @@ -277,49 +341,49 @@ void Lime::transmit_frame(const struct FrameData& frame) long long int timeNs = frame.ts.get_ns(); // muting and mutenotimestamp is handled by SDR const bool has_time_spec = (m_conf.enableSync and frame.ts.timestamp_valid); - - if (not m_tx_stream_active) { - int flags = has_time_spec ? SOAPY_SDR_HAS_TIME : 0; - int ret = m_device->activateStream(m_tx_stream, flags, timeNs); - if (ret != 0) { - throw std::runtime_error(string("Soapy activate TX stream failed: ") + - SoapySDR::errToStr(ret)); - } +*/ + if (not m_tx_stream_active) + { + unsigned int buffer_size = 200000*2*sizeof(complexf); + + m_tx_stream.channel = m_channel; + m_tx_stream.fifoSize = buffer_size; + m_tx_stream.throughputVsLatency = 0.5; + m_tx_stream.isTx = LMS_CH_TX; + m_tx_stream.dataFmt = lms_stream_t::LMS_FMT_F32; + + if ( LMS_SetupStream(m_device, &m_tx_stream) < 0 ) + { + etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); + throw std::runtime_error("Cannot Channel Activate LimeSDR output device"); + } + LMS_StartStream(&m_tx_stream); m_tx_stream_active = true; } // The frame buffer contains bytes representing FC32 samples const complexf *buf = reinterpret_cast(frame.buf.data()); const size_t numSamples = frame.buf.size() / sizeof(complexf); - if ((frame.buf.size() % sizeof(complexf)) != 0) { - throw std::runtime_error("Soapy: invalid buffer size"); + if ((frame.buf.size() % sizeof(complexf)) != 0) + { + throw std::runtime_error("Lime: invalid buffer size"); } - // Stream MTU is in samples, not bytes. - const size_t mtu = m_device->getStreamMTU(m_tx_stream); - - size_t num_acc_samps = 0; - while (num_acc_samps < numSamples) { + //etiLog.level(info) << "LimeSDR:Buffer " << std::fixed << numSamples << " /" << m_tx_stream.fifoSize ; - const void *buffs[1]; - buffs[0] = buf + num_acc_samps; - - const size_t samps_to_send = std::min(numSamples - num_acc_samps, mtu); - - const bool eob_because_muting = m_conf.muting; - const bool end_of_burst = eob_because_muting or ( - frame.ts.timestamp_valid and - frame.ts.timestamp_refresh and - samps_to_send <= mtu ); - - int flags = 0; - - auto num_sent = m_device->writeStream( - m_tx_stream, buffs, samps_to_send, flags, timeNs); + auto num_sent = LMS_SendStream( &m_tx_stream, buf, numSamples, NULL, 1000 ); + + if (num_sent <= 0) + { + etiLog.level(info) << num_sent; + //throw std::runtime_error("Lime: Too Loonnnngg"); + } + else + { + //etiLog.level(info) << "OK" << num_sent; + } - if (num_sent == SOAPY_SDR_TIMEOUT) { - continue; - } + /* else if (num_sent == SOAPY_SDR_OVERFLOW) { overflows++; continue; @@ -338,7 +402,7 @@ void Lime::transmit_frame(const struct FrameData& frame) timeNs += 1e9 * num_sent/m_conf.sampleRate; num_acc_samps += num_sent; - + if (end_of_burst) { int ret_deact = m_device->deactivateStream(m_tx_stream); if (ret_deact != 0) { @@ -351,10 +415,10 @@ void Lime::transmit_frame(const struct FrameData& frame) if (eob_because_muting) { break; - } - } + }*/ + //num_acc_samps += num_sent; num_frames_modulated++; - */ + } } // namespace Output diff --git a/src/output/Lime.h b/src/output/Lime.h index 1770aaf..7ab4aca 100644 --- a/src/output/Lime.h +++ b/src/output/Lime.h @@ -79,13 +79,14 @@ class Lime : public Output::SDRDevice private: SDRDeviceConfig& m_conf; lms_device_t *m_device=nullptr; + size_t m_channel=0; // Should be set by config /* SoapySDR::Device *m_device = nullptr; SoapySDR::Stream *m_tx_stream = nullptr; - bool m_tx_stream_active = false; - SoapySDR::Stream *m_rx_stream = nullptr; */ - bool m_rx_stream_active = false; + lms_stream_t m_tx_stream; + bool m_tx_stream_active = false; + size_t underflows = 0; size_t overflows = 0; -- cgit v1.2.3