summaryrefslogtreecommitdiffstats
path: root/src/output
diff options
context:
space:
mode:
authorF5OEO <evaristec@gmail.com>2018-12-11 17:12:25 +0000
committerF5OEO <evaristec@gmail.com>2018-12-11 17:12:25 +0000
commita91bb4387b1254e56de2ff64b2db3cda3d0a08e0 (patch)
treef5f06bb6fd38beb1ae960ed559992abc324da5b5 /src/output
parentf60ba388a646032cbfdcad3c723d1e457cc4457e (diff)
downloaddabmod-a91bb4387b1254e56de2ff64b2db3cda3d0a08e0.tar.gz
dabmod-a91bb4387b1254e56de2ff64b2db3cda3d0a08e0.tar.bz2
dabmod-a91bb4387b1254e56de2ff64b2db3cda3d0a08e0.zip
Add FIR processing with upsampling
Diffstat (limited to 'src/output')
-rw-r--r--src/output/Lime.cpp131
-rw-r--r--src/output/Lime.h7
-rw-r--r--src/output/SDRDevice.h2
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;