<p>Pau Espin Pedrol has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13872">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lms: Use smpl_buf to recover from timestamp jumps<br><br>Also take the chance to make sure we handle properly short reads (keep<br>reading again).<br><br>Both scenarios can be tested by running osmo-trx-lms and then using<br>on a terminal:<br>sudo kill -STOP `pidof osmo-trx-lms`; sleep 0.5; sudo kill -CONT `pidof osmo-trx-lms`<br><br>Fixes: OS#3339<br>Change-Id: Idfc4e69acc30afb11440b6b9cbdcfa09ff920265<br>---<br>M Transceiver52M/device/lms/LMSDevice.cpp<br>M Transceiver52M/device/lms/LMSDevice.h<br>M Transceiver52M/device/lms/Makefile.am<br>3 files changed, 70 insertions(+), 17 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/72/13872/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/Transceiver52M/device/lms/LMSDevice.cpp b/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>index 035e593..222ce91 100644</span><br><span>--- a/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>+++ b/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>@@ -40,6 +40,7 @@</span><br><span> #define GSM_CARRIER_BW 270000.0 /* 270kHz */</span><br><span> #define LMS_MIN_BW_SUPPORTED 2.5e6 /* 2.5mHz, minimum supported by LMS */</span><br><span> #define LMS_CALIBRATE_BW_HZ OSMO_MAX(GSM_CARRIER_BW, LMS_MIN_BW_SUPPORTED)</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAMPLE_BUF_SZ (1 << 20) /* Size of Rx timestamp based Ring buffer, in bytes */</span><br><span> </span><br><span> LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,</span><br><span> const std::vector<std::string>& tx_paths,</span><br><span>@@ -56,6 +57,8 @@</span><br><span> m_last_rx_overruns.resize(chans, 0);</span><br><span> m_last_rx_dropped.resize(chans, 0);</span><br><span> m_last_tx_underruns.resize(chans, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rx_buffers.resize(chans);</span><br><span> }</span><br><span> </span><br><span> LMSDevice::~LMSDevice()</span><br><span>@@ -71,6 +74,9 @@</span><br><span> LMS_Close(m_lms_dev);</span><br><span> m_lms_dev = NULL;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (size_t i = 0; i < rx_buffers.size(); i++)</span><br><span style="color: hsl(120, 100%, 40%);">+ delete rx_buffers[i];</span><br><span> }</span><br><span> </span><br><span> static void lms_log_callback(int lvl, const char *msg)</span><br><span>@@ -238,6 +244,10 @@</span><br><span> goto out_close;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Set up per-channel Rx timestamp based Ring buffers */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (size_t i = 0; i < rx_buffers.size(); i++)</span><br><span style="color: hsl(120, 100%, 40%);">+ rx_buffers[i] = new smpl_buf(SAMPLE_BUF_SZ / sizeof(uint32_t));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> started = false;</span><br><span> </span><br><span> return NORMAL;</span><br><span>@@ -600,7 +610,9 @@</span><br><span> int LMSDevice::readSamples(std::vector < short *>&bufs, int len, bool * overrun,</span><br><span> TIMESTAMP timestamp, bool * underrun, unsigned *RSSI)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc, num_smpls, expect_smpls;</span><br><span style="color: hsl(120, 100%, 40%);">+ ssize_t avail_smpls;</span><br><span style="color: hsl(120, 100%, 40%);">+ TIMESTAMP expect_timestamp;</span><br><span> unsigned int i;</span><br><span> lms_stream_meta_t rx_metadata = {};</span><br><span> rx_metadata.flushPartialPacket = false;</span><br><span>@@ -614,24 +626,62 @@</span><br><span> </span><br><span> *overrun = false;</span><br><span> *underrun = false;</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i<chans; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">- thread_enable_cancel(false);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = LMS_RecvStream(&m_lms_stream_rx[i], bufs[i], len, &rx_metadata, 100);</span><br><span style="color: hsl(0, 100%, 40%);">- update_stream_stats(i, underrun, overrun);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc != len) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGCHAN(i, DDEV, ERROR) << "LMS: Device receive timed out (" << rc << " vs exp " << len << ").";</span><br><span style="color: hsl(0, 100%, 40%);">- thread_enable_cancel(true);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (timestamp != (TIMESTAMP)rx_metadata.timestamp)</span><br><span style="color: hsl(0, 100%, 40%);">- LOGCHAN(i, DDEV, ERROR) << "recv buffer of len " << rc << " expect " << std::hex << timestamp << " got " << std::hex << (TIMESTAMP)rx_metadata.timestamp << " (" << std::hex << rx_metadata.timestamp <<") diff=" << rx_metadata.timestamp - timestamp;</span><br><span style="color: hsl(0, 100%, 40%);">- thread_enable_cancel(true);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check that timestamp is valid */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = rx_buffers[0]->avail_smpls(timestamp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGC(DDEV, ERROR) << rx_buffers[0]->str_code(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGC(DDEV, ERROR) << rx_buffers[0]->str_status(timestamp);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (((TIMESTAMP) rx_metadata.timestamp) < timestamp)</span><br><span style="color: hsl(0, 100%, 40%);">- rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i<chans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Receive samples from HW until we have enough */</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((avail_smpls = rx_buffers[i]->avail_smpls(timestamp)) < len) {</span><br><span style="color: hsl(120, 100%, 40%);">+ thread_enable_cancel(false);</span><br><span style="color: hsl(120, 100%, 40%);">+ num_smpls = LMS_RecvStream(&m_lms_stream_rx[i], bufs[i], len - avail_smpls, &rx_metadata, 100);</span><br><span style="color: hsl(120, 100%, 40%);">+ update_stream_stats(i, underrun, overrun);</span><br><span style="color: hsl(120, 100%, 40%);">+ thread_enable_cancel(true);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (num_smpls <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(i, DDEV, ERROR) << "Device receive timed out (" << rc << " vs exp " << len << ").";</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(i, DDEV, DEBUG) "Received timestamp = " << (TIMESTAMP)rx_metadata.timestamp << " (" << num_smpls << ")";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ expect_smpls = len - avail_smpls;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (expect_smpls != num_smpls)</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(i, DDEV, NOTICE) << "Unexpected recv buffer len: expect "</span><br><span style="color: hsl(120, 100%, 40%);">+ << expect_smpls << " got " << num_smpls</span><br><span style="color: hsl(120, 100%, 40%);">+ << ", diff=" << expect_smpls - num_smpls;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ expect_timestamp = timestamp + avail_smpls;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (expect_timestamp != (TIMESTAMP)rx_metadata.timestamp)</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(i, DDEV, ERROR) << "Unexpected recv buffer timestamp: expect "</span><br><span style="color: hsl(120, 100%, 40%);">+ << expect_timestamp << " got " << (TIMESTAMP)rx_metadata.timestamp</span><br><span style="color: hsl(120, 100%, 40%);">+ << ", diff=" << rx_metadata.timestamp - expect_timestamp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = rx_buffers[i]->write(bufs[i], num_smpls, (TIMESTAMP)rx_metadata.timestamp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(i, DDEV, ERROR) << rx_buffers[i]->str_code(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGCHAN(i, DDEV, ERROR) << rx_buffers[i]->str_status(timestamp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != smpl_buf::ERROR_OVERFLOW)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We have enough samples */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (size_t i = 0; i < rx_buffers.size(); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = rx_buffers[i]->read(bufs[i], len, timestamp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((rc < 0) || (rc != len)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGC(DDEV, ERROR) << rx_buffers[i]->str_code(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGC(DDEV, ERROR) << rx_buffers[i]->str_status(timestamp);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return len;</span><br><span> }</span><br><span> </span><br><span> int LMSDevice::writeSamples(std::vector < short *>&bufs, int len,</span><br><span>diff --git a/Transceiver52M/device/lms/LMSDevice.h b/Transceiver52M/device/lms/LMSDevice.h</span><br><span>index b0ff03b..2828578 100644</span><br><span>--- a/Transceiver52M/device/lms/LMSDevice.h</span><br><span>+++ b/Transceiver52M/device/lms/LMSDevice.h</span><br><span>@@ -20,6 +20,7 @@</span><br><span> #endif</span><br><span> </span><br><span> #include "radioDevice.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "smpl_buf.h"</span><br><span> </span><br><span> #include <sys/time.h></span><br><span> #include <math.h></span><br><span>@@ -53,6 +54,8 @@</span><br><span> std::vector<uint32_t> m_last_rx_dropped;</span><br><span> std::vector<uint32_t> m_last_tx_underruns;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ std::vector<smpl_buf *> rx_buffers;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> double actualSampleRate; ///< the actual USRP sampling rate</span><br><span> </span><br><span> bool started; ///< flag indicates LMS has started</span><br><span>diff --git a/Transceiver52M/device/lms/Makefile.am b/Transceiver52M/device/lms/Makefile.am</span><br><span>index 8471074..30f105d 100644</span><br><span>--- a/Transceiver52M/device/lms/Makefile.am</span><br><span>+++ b/Transceiver52M/device/lms/Makefile.am</span><br><span>@@ -7,4 +7,4 @@</span><br><span> </span><br><span> noinst_LTLIBRARIES = libdevice.la</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-libdevice_la_SOURCES = LMSDevice.cpp</span><br><span style="color: hsl(120, 100%, 40%);">+libdevice_la_SOURCES = LMSDevice.cpp ../smpl_buf.cpp</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13872">change 13872</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13872"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-trx </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Idfc4e69acc30afb11440b6b9cbdcfa09ff920265 </div>
<div style="display:none"> Gerrit-Change-Number: 13872 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Pau Espin Pedrol <pespin@sysmocom.de> </div>