cosmetic: uhd: Move smpl_buf out of UHDDevice, move UHDDevice class definition to .h

* move class definition to .h file, like we do for other devices.
* move smpl_buf class to a different file inside uhd/.
* Preparation work to have smpl_buf being used in a generic way for
devices other than UHD (LMS).

Change-Id: Ib4594320da9bb7f6e9f52e7d70d11ecd11106aae
diff --git a/Transceiver52M/device/uhd/smpl_buf.cpp b/Transceiver52M/device/uhd/smpl_buf.cpp
new file mode 100644
index 0000000..d8bdbc4
--- /dev/null
+++ b/Transceiver52M/device/uhd/smpl_buf.cpp
@@ -0,0 +1,186 @@
+/*
+ * Sample Buffer - Allows reading and writing of timed samples
+ *
+ * Copyright 2010,2011 Free Software Foundation, Inc.
+ * Copyright (C) 2015 Ettus Research LLC
+ * Copyright 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * Author: Tom Tsou <tom.tsou@ettus.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * See the COPYING file in the main directory for details.
+ */
+
+#include "smpl_buf.h"
+#include <inttypes.h>
+
+smpl_buf::smpl_buf(size_t len, double rate)
+	: buf_len(len), clk_rt(rate),
+	  time_start(0), time_end(0), data_start(0), data_end(0)
+{
+	data = new uint32_t[len];
+}
+
+smpl_buf::~smpl_buf()
+{
+	delete[] data;
+}
+
+ssize_t smpl_buf::avail_smpls(TIMESTAMP timestamp) const
+{
+	if (timestamp < time_start)
+		return ERROR_TIMESTAMP;
+	else if (timestamp >= time_end)
+		return 0;
+	else
+		return time_end - timestamp;
+}
+
+ssize_t smpl_buf::avail_smpls(uhd::time_spec_t timespec) const
+{
+	return avail_smpls(timespec.to_ticks(clk_rt));
+}
+
+ssize_t smpl_buf::read(void *buf, size_t len, TIMESTAMP timestamp)
+{
+	int type_sz = 2 * sizeof(short);
+
+	// Check for valid read
+	if (timestamp < time_start)
+		return ERROR_TIMESTAMP;
+	if (timestamp >= time_end)
+		return 0;
+	if (len >= buf_len)
+		return ERROR_READ;
+
+	// How many samples should be copied
+	size_t num_smpls = time_end - timestamp;
+	if (num_smpls > len)
+		num_smpls = len;
+
+	// Starting index
+	size_t read_start = (data_start + (timestamp - time_start)) % buf_len;
+
+	// Read it
+	if (read_start + num_smpls < buf_len) {
+		size_t numBytes = len * type_sz;
+		memcpy(buf, data + read_start, numBytes);
+	} else {
+		size_t first_cp = (buf_len - read_start) * type_sz;
+		size_t second_cp = len * type_sz - first_cp;
+
+		memcpy(buf, data + read_start, first_cp);
+		memcpy((char*) buf + first_cp, data, second_cp);
+	}
+
+	data_start = (read_start + len) % buf_len;
+	time_start = timestamp + len;
+
+	if (time_start > time_end)
+		return ERROR_READ;
+	else
+		return num_smpls;
+}
+
+ssize_t smpl_buf::read(void *buf, size_t len, uhd::time_spec_t ts)
+{
+	return read(buf, len, ts.to_ticks(clk_rt));
+}
+
+ssize_t smpl_buf::write(void *buf, size_t len, TIMESTAMP timestamp)
+{
+	int type_sz = 2 * sizeof(short);
+
+	// Check for valid write
+	if ((len == 0) || (len >= buf_len))
+		return ERROR_WRITE;
+	if ((timestamp + len) <= time_end)
+		return ERROR_TIMESTAMP;
+
+	if (timestamp < time_end) {
+		LOGC(DDEV, ERR) << "Overwriting old buffer data: timestamp="<<timestamp<<" time_end="<<time_end;
+		uhd::time_spec_t ts = uhd::time_spec_t::from_ticks(timestamp, clk_rt);
+		LOGC(DDEV, DEBUG) << "Requested timestamp = " << timestamp << " (real_sec=" << std::fixed << ts.get_real_secs() << " = " << ts.to_ticks(clk_rt) << ") rate=" << clk_rt;
+		// Do not return error here, because it's a rounding error and is not fatal
+	}
+	if (timestamp > time_end && time_end != 0) {
+		LOGC(DDEV, ERR) << "Skipping buffer data: timestamp="<<timestamp<<" time_end="<<time_end;
+		uhd::time_spec_t ts = uhd::time_spec_t::from_ticks(timestamp, clk_rt);
+		LOGC(DDEV, DEBUG) << "Requested timestamp = " << timestamp << " (real_sec=" << std::fixed << ts.get_real_secs() << " = " << ts.to_ticks(clk_rt) << ") rate=" << clk_rt;
+		// Do not return error here, because it's a rounding error and is not fatal
+	}
+
+	// Starting index
+	size_t write_start = (data_start + (timestamp - time_start)) % buf_len;
+
+	// Write it
+	if ((write_start + len) < buf_len) {
+		size_t numBytes = len * type_sz;
+		memcpy(data + write_start, buf, numBytes);
+	} else {
+		size_t first_cp = (buf_len - write_start) * type_sz;
+		size_t second_cp = len * type_sz - first_cp;
+
+		memcpy(data + write_start, buf, first_cp);
+		memcpy(data, (char*) buf + first_cp, second_cp);
+	}
+
+	data_end = (write_start + len) % buf_len;
+	time_end = timestamp + len;
+
+	if (!data_start)
+		data_start = write_start;
+
+	if (((write_start + len) > buf_len) && (data_end > data_start))
+		return ERROR_OVERFLOW;
+	else if (time_end <= time_start)
+		return ERROR_WRITE;
+	else
+		return len;
+}
+
+ssize_t smpl_buf::write(void *buf, size_t len, uhd::time_spec_t ts)
+{
+	return write(buf, len, ts.to_ticks(clk_rt));
+}
+
+std::string smpl_buf::str_status(size_t ts) const
+{
+	std::ostringstream ost("Sample buffer: ");
+
+	ost << "timestamp = " << ts;
+	ost << ", length = " << buf_len;
+	ost << ", time_start = " << time_start;
+	ost << ", time_end = " << time_end;
+	ost << ", data_start = " << data_start;
+	ost << ", data_end = " << data_end;
+
+	return ost.str();
+}
+
+std::string smpl_buf::str_code(ssize_t code)
+{
+	switch (code) {
+	case ERROR_TIMESTAMP:
+		return "Sample buffer: Requested timestamp is not valid";
+	case ERROR_READ:
+		return "Sample buffer: Read error";
+	case ERROR_WRITE:
+		return "Sample buffer: Write error";
+	case ERROR_OVERFLOW:
+		return "Sample buffer: Overrun";
+	default:
+		return "Sample buffer: Unknown error";
+	}
+}