diff options
author | F5OEO <evaristec@gmail.com> | 2018-12-11 17:12:25 +0000 |
---|---|---|
committer | F5OEO <evaristec@gmail.com> | 2018-12-11 17:12:25 +0000 |
commit | a91bb4387b1254e56de2ff64b2db3cda3d0a08e0 (patch) | |
tree | f5f06bb6fd38beb1ae960ed559992abc324da5b5 /src | |
parent | f60ba388a646032cbfdcad3c723d1e457cc4457e (diff) | |
download | dabmod-a91bb4387b1254e56de2ff64b2db3cda3d0a08e0.tar.gz dabmod-a91bb4387b1254e56de2ff64b2db3cda3d0a08e0.tar.bz2 dabmod-a91bb4387b1254e56de2ff64b2db3cda3d0a08e0.zip |
Add FIR processing with upsampling
Diffstat (limited to 'src')
-rw-r--r-- | src/output/Lime.cpp | 131 | ||||
-rw-r--r-- | src/output/Lime.h | 7 | ||||
-rw-r--r-- | src/output/SDRDevice.h | 2 |
3 files changed, 50 insertions, 90 deletions
diff --git a/src/output/Lime.cpp b/src/output/Lime.cpp index d553187..78e756d 100644 --- a/src/output/Lime.cpp +++ b/src/output/Lime.cpp @@ -49,6 +49,8 @@ Lime::Lime(SDRDeviceConfig& config) : SDRDevice(), m_conf(config) { + m_interpolate=m_conf.upsample; + interpolatebuf=new complexf[200000*m_interpolate]; etiLog.level(info) << "Lime:Creating the device with: " << m_conf.device; @@ -90,7 +92,7 @@ Lime::Lime(SDRDeviceConfig& config) : throw std::runtime_error("Cannot channel LimeSDR output device"); } - if (LMS_SetSampleRate(m_device, m_conf.masterClockRate, 0) < 0) + if (LMS_SetSampleRate(m_device, m_conf.masterClockRate*m_interpolate, 0) < 0) { etiLog.level(error) << "Error making LimeSDR device: %s " << LMS_GetLastErrorMessage(); throw std::runtime_error("Cannot channel LimeSDR output device"); @@ -143,47 +145,23 @@ Lime::Lime(SDRDeviceConfig& config) : 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); - etiLog.level(info) << "SoapySDR master clock rate set to " << - std::fixed << std::setprecision(4) << - m_device->getMasterClockRate()/1000.0 << " kHz"; - - m_device->setSampleRate(SOAPY_SDR_TX, 0, m_conf.sampleRate); - etiLog.level(info) << "SoapySDR:Actual TX rate: " << - std::fixed << std::setprecision(4) << - m_device->getSampleRate(SOAPY_SDR_TX, 0) / 1000.0 << - " ksps."; - - tune(m_conf.lo_offset, m_conf.frequency); - m_conf.frequency = m_device->getFrequency(SOAPY_SDR_TX, 0); - etiLog.level(info) << "SoapySDR:Actual frequency: " << - std::fixed << std::setprecision(3) << - m_conf.frequency / 1000.0 << " kHz."; - - m_device->setGain(SOAPY_SDR_TX, 0, m_conf.txgain); - etiLog.level(info) << "SoapySDR:Actual tx gain: " << - std::fixed << std::setprecision(2) << - m_device->getGain(SOAPY_SDR_TX, 0); - - if (not m_conf.tx_antenna.empty()) { - m_device->setAntenna(SOAPY_SDR_TX, 0, m_conf.tx_antenna); - } - etiLog.level(info) << "SoapySDR:Actual tx antenna: " << - m_device->getAntenna(SOAPY_SDR_TX, 0); - - if (m_device->hasHardwareTime()) { - using namespace std::chrono; - auto n = system_clock::now(); - const long long ticks = duration_cast<nanoseconds>(n.time_since_epoch()).count(); - m_device->setHardwareTime(ticks); + switch(m_interpolate) + { + case 1: + { + static double coeff[]= {-0.0014080960536375642, 0.0010270054917782545, 0.0002103941806126386, -0.0023147952742874622, 0.004256128799170256, -0.0038850826676934958, -0.0006057845894247293, 0.008352266624569893, -0.014639420434832573, 0.01275692880153656, 0.0012119393795728683, -0.02339744009077549, 0.04088031128048897, -0.03649924695491791, -0.001745241112075746, 0.07178881019353867, -0.15494878590106964, 0.22244733572006226, 0.7530255913734436, 0.22244733572006226, -0.15494878590106964, 0.07178881019353867, -0.001745241112075746, -0.03649924695491791, 0.04088031128048897, -0.02339744009077549, 0.0012119393795728683, 0.01275692880153656, -0.014639420434832573, 0.008352266624569893, -0.0006057845894247293, -0.0038850826676934958, 0.004256128799170256, -0.0023147952742874622, 0.0002103941806126386, 0.0010270054917782545, -0.0014080960536375642}; + LMS_SetGFIRCoeff(m_device, LMS_CH_TX, m_channel, LMS_GFIR3, coeff, 37) ; + LMS_SetGFIR(m_device, LMS_CH_TX,m_channel, LMS_GFIR3, true); + } + break; + case 2: + { + static double coeff[]= {0.0007009872933849692, 0.0006160094635561109, -0.0003868100175168365, -0.0010892765130847692, -0.0003017585549969226, 0.0013388358056545258, 0.0014964848523959517, -0.000810395460575819, -0.0028437587898224592, -0.001026041223667562, 0.0033166243229061365, 0.004008698742836714, -0.0016114861937239766, -0.006794447544962168, -0.0029077117796987295, 0.0070640090852975845, 0.009203733876347542, -0.002605677582323551, -0.014204192906618118, -0.007088471669703722, 0.013578214682638645, 0.019509244710206985, -0.0035577849484980106, -0.028872046619653702, -0.016949573531746864, 0.02703845500946045, 0.045044951140880585, -0.00423968443647027, -0.07416801154613495, -0.05744718387722969, 0.09617383778095245, 0.30029231309890747, 0.39504382014274597, 0.30029231309890747, 0.09617383778095245, -0.05744718387722969, -0.07416801154613495, -0.00423968443647027, 0.045044951140880585, 0.02703845500946045, -0.016949573531746864, -0.028872046619653702, -0.0035577849484980106, 0.019509244710206985, 0.013578214682638645, -0.007088471669703722, -0.014204192906618118, -0.002605677582323551, 0.009203733876347542, 0.0070640090852975845, -0.0029077117796987295, -0.006794447544962168, -0.0016114861937239766, 0.004008698742836714, 0.0033166243229061365, -0.001026041223667562, -0.0028437587898224592, -0.000810395460575819, 0.0014964848523959517, 0.0013388358056545258, -0.0003017585549969226, -0.0010892765130847692, -0.0003868100175168365, 0.0006160094635561109, 0.0007009872933849692}; + LMS_SetGFIRCoeff(m_device, LMS_CH_TX, m_channel, LMS_GFIR3, coeff, 65) ; + LMS_SetGFIR(m_device, LMS_CH_TX,m_channel, LMS_GFIR3, true); + } + break; } - - const std::vector<size_t> channels({0}); - m_tx_stream = m_device->setupStream(SOAPY_SDR_TX, "CF32", channels); - m_rx_stream = m_device->setupStream(SOAPY_SDR_RX, "CF32", channels); - */ } Lime::~Lime() @@ -205,6 +183,8 @@ Lime::~Lime() LMS_EnableChannel(m_device, LMS_CH_TX, m_channel, false); LMS_Close(m_device); } + if(interpolatebuf!=nullptr) + delete(interpolatebuf); } void Lime::tune(double lo_offset, double frequency) @@ -238,7 +218,7 @@ double Lime::get_txgain(void) const return 0;//m_device->getGain(SOAPY_SDR_TX, 0); } -SDRDevice::RunStatistics Lime::get_run_statistics(void) const +SDRDevice::RunStatistics Lime::get_run_statistics(void) const { RunStatistics rs; rs.num_underruns = underflows; @@ -337,14 +317,10 @@ double Lime::get_temperature(void) const void Lime::transmit_frame(const struct FrameData& frame) { if (not m_device) throw runtime_error("Lime device not set up"); -/* - 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) { - unsigned int buffer_size = 200000*2*sizeof(complexf); + unsigned int buffer_size = 200000*m_interpolate; m_tx_stream.channel = m_channel; m_tx_stream.fifoSize = buffer_size; @@ -358,6 +334,7 @@ void Lime::transmit_frame(const struct FrameData& frame) throw std::runtime_error("Cannot Channel Activate LimeSDR output device"); } LMS_StartStream(&m_tx_stream); + LMS_SetGFIR(m_device, LMS_CH_TX, m_channel, LMS_GFIR3, true); m_tx_stream_active = true; } @@ -369,10 +346,21 @@ void Lime::transmit_frame(const struct FrameData& frame) throw std::runtime_error("Lime: invalid buffer size"); } - //etiLog.level(info) << "LimeSDR:Buffer " << std::fixed << numSamples << " /" << m_tx_stream.fifoSize ; + size_t num_sent=0; + if(m_interpolate==1) + num_sent= LMS_SendStream( &m_tx_stream, buf, numSamples, NULL, 1000 ); + + if(m_interpolate>1) // We upsample (1 0 0 0), low pass filter is done by FIR + { + for(size_t i=0;i<numSamples;i++) + { + interpolatebuf[i*m_interpolate]=buf[i]; + for(size_t j=1;j<m_interpolate;j++) + interpolatebuf[i*m_interpolate+j]=complexf(0,0); + } + num_sent= LMS_SendStream( &m_tx_stream, interpolatebuf, numSamples*m_interpolate, NULL, 1000 ); + } - auto num_sent = LMS_SendStream( &m_tx_stream, buf, numSamples, NULL, 1000 ); - if (num_sent <= 0) { etiLog.level(info) << num_sent; @@ -382,41 +370,12 @@ void Lime::transmit_frame(const struct FrameData& frame) { //etiLog.level(info) << "OK" << num_sent; } - - /* - else if (num_sent == SOAPY_SDR_OVERFLOW) { - overflows++; - continue; - } - else if (num_sent == SOAPY_SDR_UNDERFLOW) { - underflows++; - continue; - } - - if (num_sent < 0) { - etiLog.level(error) << "Unexpected stream error " << - SoapySDR::errToStr(num_sent); - throw std::runtime_error("Fault in Soapy"); - } - - 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) { - throw std::runtime_error( - string("Soapy activate TX stream failed: ") + - SoapySDR::errToStr(ret_deact)); - } - m_tx_stream_active = false; - } - - if (eob_because_muting) { - break; - }*/ - //num_acc_samps += num_sent; + lms_stream_status_t LimeStatus; + LMS_GetStreamStatus(&m_tx_stream,&LimeStatus); + overflows=LimeStatus.overrun; + underflows=LimeStatus.underrun; + late_packets=LimeStatus.droppedPackets; + num_frames_modulated++; } diff --git a/src/output/Lime.h b/src/output/Lime.h index 7ab4aca..2b5c80c 100644 --- a/src/output/Lime.h +++ b/src/output/Lime.h @@ -32,7 +32,7 @@ DESCRIPTION: #ifdef HAVE_CONFIG_H # include <config.h> #endif - +//#define HAVE_LIMESDR #ifdef HAVE_LIMESDR #include <string> @@ -84,9 +84,10 @@ class Lime : public Output::SDRDevice SoapySDR::Device *m_device = nullptr; SoapySDR::Stream *m_tx_stream = nullptr; */ - lms_stream_t m_tx_stream; + lms_stream_t m_tx_stream; bool m_tx_stream_active = false; - + size_t m_interpolate=1; + complexf *interpolatebuf=nullptr; size_t underflows = 0; size_t overflows = 0; diff --git a/src/output/SDRDevice.h b/src/output/SDRDevice.h index 90a1123..9796479 100644 --- a/src/output/SDRDevice.h +++ b/src/output/SDRDevice.h @@ -63,7 +63,7 @@ struct SDRDeviceConfig { double txgain = 0.0; double rxgain = 0.0; bool enableSync = false; - + unsigned upsample = 1; // When working with timestamps, mute the frames that // do not have a timestamp bool muteNoTimestamps = false; |