fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmo-trx/+/43115?usp=email )
(
9 is the latest approved patch-set. No files were changed between the latest approved patch-set and the submitted one. )Change subject: Transceiver52M: migrate to libosmo-trx ......................................................................
Transceiver52M: migrate to libosmo-trx
Replace the local TRXC/TRXD implementation with libosmo-trx's shared osmo_trxc_msg/osmo_trxd_burst_{ind,req} API, including SETSLOT parsing via osmo_trxc_setslot_parse()/_build(). Take a chance to fix SETSLOT to always send a response, distinguishing bogus input from unsupported VAMOS channel combinations.
Only the TRXC/TRXD build/parse API is used here, not the osmo_trx_ep endpoint API: osmo-trx runs its socket I/O on dedicated threads that don't drive osmo_select_main(), which osmo_trx_ep depends on.
Change-Id: I458ec85c56e2101d073c8c35f11c147191c4ea0c Related: OS#5283 --- M Transceiver52M/Makefile.am M Transceiver52M/Transceiver.cpp M Transceiver52M/Transceiver.h D Transceiver52M/proto_trxd.c D Transceiver52M/proto_trxd.h M Transceiver52M/sigProcLib.cpp M Transceiver52M/sigProcLib.h 7 files changed, 308 insertions(+), 496 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, approved Jenkins Builder: Verified
diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am index 74152b3..4cf5f9c 100644 --- a/Transceiver52M/Makefile.am +++ b/Transceiver52M/Makefile.am @@ -23,9 +23,28 @@
SUBDIRS = arch device
-AM_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES) -I${srcdir}/arch/common -I${srcdir}/device/common -AM_CXXFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS) -AM_CFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS) +AM_CPPFLAGS = \ + -Wall \ + $(STD_DEFINES_AND_INCLUDES) \ + -I${srcdir}/arch/common \ + -I${srcdir}/device/common \ + -I$(top_srcdir)/libosmo-trx/include \ + -I$(top_builddir)/libosmo-trx/include \ + $(NULL) + +AM_CXXFLAGS = \ + -lpthread \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOCTRL_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) \ + $(NULL) + +AM_CFLAGS = \ + -lpthread \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOCTRL_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) \ + $(NULL)
noinst_LTLIBRARIES = libtransceiver_common.la
@@ -37,7 +56,6 @@ sigProcLib.cpp \ signalVector.cpp \ Transceiver.cpp \ - proto_trxd.c \ grgsm_vitac/grgsm_vitac.cpp \ grgsm_vitac/viterbi_detector.cc
@@ -67,8 +85,7 @@ sigProcLib.h \ signalVector.h \ Transceiver.h \ - Resampler.h \ - proto_trxd.h + Resampler.h
if ENABLE_MULTI_ARFCN noinst_HEADERS += \ @@ -79,7 +96,8 @@ endif
COMMON_LDADD = \ - libtransceiver_common.la \ + $(builddir)/libtransceiver_common.la \ + $(top_builddir)/libosmo-trx/src/libosmo-trx.la \ $(ARCH_LA) \ $(GSM_LA) \ $(COMMON_LA) \ diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index 46d06db..9dc26a4 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -25,6 +25,7 @@
#include <stdio.h> #include <netinet/in.h> +#include <algorithm> // std::transform #include <iomanip> // std::setprecision #include <fstream> #include "Transceiver.h" @@ -33,12 +34,14 @@
extern "C" { #include "osmo_signal.h" -#include "proto_trxd.h"
#include <osmocom/core/utils.h> #include <osmocom/core/socket.h> #include <osmocom/core/bits.h> +#include <osmocom/core/msgb.h> #include <osmocom/vty/cpu_sched_vty.h> +#include <osmocom/trx/trxc.h> +#include <osmocom/trx/trxd.h> }
#ifdef HAVE_CONFIG_H @@ -142,7 +145,8 @@ mRxServiceLoopThreads(mChans), mRxLowerLoopThread(nullptr), mTxLowerLoopThread(nullptr), mTxPriorityQueueServiceLoopThreads(mChans), mTransmitLatency(wTransmitLatency), mRadioInterface(wRadioInterface), mOn(false),mForceClockInterface(false), mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelayAB(0), - mMaxExpectedDelayNB(0), mWriteBurstToDiskMask(0), mVersionTRXD(mChans), mStates(mChans) + mMaxExpectedDelayNB(0), mWriteBurstToDiskMask(0), mVersionTRXD(mChans), mStates(mChans), + mBurstIndMsg(mChans) { txFullScale = mRadioInterface->fullScaleInputValue(); rxFullScale = mRadioInterface->fullScaleOutputValue(); @@ -151,6 +155,11 @@ for (size_t j = 0; j < ARRAY_SIZE(mHandover[i]); j++) mHandover[i][j] = false; } + + for (size_t i = 0; i < mChans; i++) { + mBurstIndMsg[i] = msgb_alloc(OSMO_TRXD_MSG_BUF_SIZE, "trxd_burst_ind"); + OSMO_ASSERT(mBurstIndMsg[i] != NULL); + } }
Transceiver::~Transceiver() @@ -166,6 +175,7 @@ mTxPriorityQueues[i].clear(); if (mDataSockets[i] >= 0) close(mDataSockets[i]); + msgb_free(mBurstIndMsg[i]); } }
@@ -655,6 +665,29 @@ }; #endif
+/* Convert a soft bit in rxBurst's native -1..+1 range (+1.0 = confident '1') + * into the sbit_t domain (-127..127) used by struct osmo_trxd_burst_ind. */ +static inline sbit_t float_soft_bit_to_sbit(float x) +{ + /* The input is not guaranteed to be within the range of [-1, +1] + * (amplitude estimation error, noise), so clamp on both ends. */ + if (x > 1.0f) + x = 1.0f; + else if (x < -1.0f) + x = -1.0f; + + /* x in [-1, +1] maps exactly onto sbit_t's [-127, +127] */ + return (sbit_t) lround(-127.0 * x); +} + +/* Convert a diversity-averaged burst energy sample into the dBm-domain RSSI. */ +static inline int8_t energy_to_rssi_dbm(float energy, double rxFullScale, double rssi_offset) +{ + double energy_dbfs = 20.0 * log10(rxFullScale / energy); + double rssi_dbm = -(energy_dbfs + rssi_offset); + return (int8_t) lround(rssi_dbm); +} + /* * Pull bursts from the FIFO and handle according to the slot * and burst correlation type. Equalzation is currently disabled. @@ -662,7 +695,7 @@ * -ENOENT: timeslot is off (fn and tn in bi are filled), * -EIO: read error */ -int Transceiver::pullRadioVector(size_t chan, struct trx_ul_burst_ind *bi) +int Transceiver::pullRadioVector(size_t chan, struct osmo_trxd_burst_ind *bi) { int rc; struct estim_burst_params ebp; @@ -691,17 +724,12 @@ CorrType type = expectedCorrType(burstTime, chan);
/* Initialize struct bi */ - bi->nbits = 0; + memset(bi, 0, sizeof(*bi)); + bi->flags = OSMO_TRXD_F_MOD_TYPE | OSMO_TRXD_F_TS_INFO | OSMO_TRXD_F_CI_CB; bi->fn = burstTime.FN(); bi->tn = burstTime.TN(); - bi->rssi = 0.0; - bi->toa = 0.0; - bi->noise = 0.0; - bi->idle = false; - bi->modulation = MODULATION_GMSK; - bi->tss = 0; /* TODO: we only support tss 0 right now */ - bi->tsc = 0; - bi->ci = 0.0; + bi->mod = OSMO_TRXD_MOD_T_GMSK; + bi->tsc_set = 0; /* TODO: we only support tsc_set 0 right now */
/* Debug: dump bursts to disk */ /* bits 0-7 - chan 0 timeslots @@ -748,8 +776,7 @@ }
rssi_offset = rssiOffset(chan); - bi->rssi = 20.0 * log10(rxFullScale / avg) + rssi_offset; - bi->noise = 20.0 * log10(rxFullScale / state->mNoiseLev) + rssi_offset; + bi->rssi = energy_to_rssi_dbm(avg, rxFullScale, rssi_offset);
if (type == IDLE) goto ret_idle; @@ -786,21 +813,21 @@ rxBurst = demodAnyBurst(*shvec_ptr, (CorrType)rc, cfg->rx_sps, &ebp); }
- bi->toa = ebp.toa; + bi->toa256 = (int16_t) lround(ebp.toa * 256.0); bi->tsc = ebp.tsc; - bi->ci = ebp.ci; + bi->ci_cb = (int16_t) lround(ebp.ci * 10.0);
/* EDGE demodulator returns 444 (gSlotLen * 3) bits */ if (rxBurst->size() == EDGE_BURST_NBITS) { - bi->modulation = MODULATION_8PSK; - bi->nbits = EDGE_BURST_NBITS; + bi->mod = OSMO_TRXD_MOD_T_8PSK; + bi->burst_len = EDGE_BURST_NBITS; } else { /* size() here is actually gSlotLen + 8, due to guard periods */ - bi->modulation = MODULATION_GMSK; - bi->nbits = gSlotLen; + bi->mod = OSMO_TRXD_MOD_T_GMSK; + bi->burst_len = gSlotLen; }
- // Convert -1..+1 soft bits to 0..1 soft bits - vectorSlicer(bi->rx_burst, rxBurst->begin(), bi->nbits); + std::transform(rxBurst->begin(), rxBurst->begin() + bi->burst_len, + bi->burst, float_soft_bit_to_sbit);
delete rxBurst; delete radio_burst; @@ -809,7 +836,8 @@ ret_idle: if (ctr_changed) dispatch_trx_rate_ctr_change(state, chan); - bi->idle = true; + bi->flags |= OSMO_TRXD_F_NOPE_IND; + bi->burst_len = 0; delete radio_burst; return 0; } @@ -820,36 +848,6 @@ mTxPriorityQueues[i].clear(); }
- -/** - * Matches a buffer with a command. - * @param buf a buffer to look command in - * @param cmd a command to look in buffer - * @param params pointer to arguments, or NULL - * @return true if command matches, otherwise false - */ -static bool match_cmd(const char *buf, - const char *cmd, const char **params) -{ - size_t cmd_len = strlen(cmd); - - /* Check a command itself */ - if (strncmp(buf, cmd, cmd_len)) - return false; - - /* A command has arguments */ - if (params != NULL) { - /* Make sure there is a space */ - if (buf[cmd_len] != ' ') - return false; - - /* Update external pointer */ - *params = buf + cmd_len + 1; - } - - return true; -} - void Transceiver::ctrl_sock_send(ctrl_msg& m, int chan) { ctrl_sock_state& s = mCtrlSockets[chan]; @@ -896,17 +894,15 @@
int Transceiver::ctrl_sock_handle_rx(int chan) { + struct osmo_trxc_msg cmd, rsp; ctrl_msg cmd_received; ctrl_msg cmd_to_send; - char *buffer = cmd_received.data; - char *response = cmd_to_send.data; - const size_t response_size = sizeof(cmd_to_send.data); - const char *command, *params; int msgLen; + int rc; ctrl_sock_state& s = mCtrlSockets[chan];
/* Attempt to read from control socket */ - msgLen = read(s.conn_bfd.fd, buffer, sizeof(cmd_received.data)-1); + msgLen = read(s.conn_bfd.fd, cmd_received.data, sizeof(cmd_received.data) - 1); if (msgLen < 0 && errno == EAGAIN) return 0; /* Try again later */ if (msgLen <= 0) { @@ -914,184 +910,196 @@ return -EIO; }
- - /* Zero-terminate received string */ - buffer[msgLen] = '\0'; - - /* Verify a command signature */ - if (strncmp(buffer, "CMD ", 4)) { + rc = osmo_trxc_msg_parse(&cmd, cmd_received.data, msgLen); + if (rc < 0 || cmd.type != OSMO_TRXC_MT_CMD) { LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus message on control interface"; return -EIO; }
- /* Set command pointer */ - command = buffer + 4; - LOGCHAN(chan, DTRXCTRL, INFO) << "command is '" << command << "'"; + memset(&rsp, 0, sizeof(rsp)); + rsp.type = OSMO_TRXC_MT_RSP; + rsp.status = 1; /* default: NACK, cleared to 0 on the success path of each verb below */ + snprintf(rsp.cmd, sizeof(rsp.cmd), "%s", cmd.cmd);
- if (match_cmd(command, "POWEROFF", NULL)) { + LOGCHAN(chan, DTRXCTRL, INFO) << "command is '" << osmo_trxc_msg_name(&cmd) << "'"; + + if (!strcmp(cmd.cmd, "POWEROFF")) { stop(); - snprintf(response, response_size, "RSP POWEROFF 0"); - } else if (match_cmd(command, "POWERON", NULL)) { - if (!start()) { - snprintf(response, response_size, "RSP POWERON 1"); - } else { - snprintf(response, response_size, "RSP POWERON 0"); + rsp.status = 0; + } else if (!strcmp(cmd.cmd, "POWERON")) { + if (start()) { + rsp.status = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) mHandover[i][j] = false; } } - } else if (match_cmd(command, "HANDOVER", ¶ms)) { + } else if (!strcmp(cmd.cmd, "HANDOVER")) { unsigned ts = 0, ss = 0; - sscanf(params, "%u %u", &ts, &ss); - if (ts > 7 || ss > 7) { - snprintf(response, response_size, "RSP HANDOVER 1 %u %u", ts, ss); - } else { + if (osmo_trxc_msg_params_scan(&cmd, "%u %u", &ts, &ss) == 2 && ts <= 7 && ss <= 7) { mHandover[ts][ss] = true; - snprintf(response, response_size, "RSP HANDOVER 0 %u %u", ts, ss); + rsp.status = 0; } - } else if (match_cmd(command, "NOHANDOVER", ¶ms)) { + snprintf(rsp.params, sizeof(rsp.params), "%u %u", ts, ss); + } else if (!strcmp(cmd.cmd, "NOHANDOVER")) { unsigned ts = 0, ss = 0; - sscanf(params, "%u %u", &ts, &ss); - if (ts > 7 || ss > 7) { - snprintf(response, response_size, "RSP NOHANDOVER 1 %u %u", ts, ss); - } else { + if (osmo_trxc_msg_params_scan(&cmd, "%u %u", &ts, &ss) == 2 && ts <= 7 && ss <= 7) { mHandover[ts][ss] = false; - snprintf(response, response_size, "RSP NOHANDOVER 0 %u %u", ts, ss); + rsp.status = 0; } - } else if (match_cmd(command, "SETMAXDLY", ¶ms)) { + snprintf(rsp.params, sizeof(rsp.params), "%u %u", ts, ss); + } else if (!strcmp(cmd.cmd, "SETMAXDLY")) { //set expected maximum time-of-arrival for Access Bursts - int maxDelay; - sscanf(params, "%d", &maxDelay); - mMaxExpectedDelayAB = maxDelay; // 1 GSM symbol is approx. 1 km - snprintf(response, response_size, "RSP SETMAXDLY 0 %d", maxDelay); - } else if (match_cmd(command, "SETMAXDLYNB", ¶ms)) { + int maxDelay = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &maxDelay) == 1) { + mMaxExpectedDelayAB = maxDelay; // 1 GSM symbol is approx. 1 km + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", maxDelay); + } else if (!strcmp(cmd.cmd, "SETMAXDLYNB")) { //set expected maximum time-of-arrival for Normal Bursts - int maxDelay; - sscanf(params, "%d", &maxDelay); - mMaxExpectedDelayNB = maxDelay; // 1 GSM symbol is approx. 1 km - snprintf(response, response_size, "RSP SETMAXDLYNB 0 %d", maxDelay); - } else if (match_cmd(command, "SETRXGAIN", ¶ms)) { - int newGain; - sscanf(params, "%d", &newGain); - newGain = mRadioInterface->setRxGain(newGain, chan); - snprintf(response, response_size, "RSP SETRXGAIN 0 %d", newGain); - } else if (match_cmd(command, "NOISELEV", NULL)) { + int maxDelay = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &maxDelay) == 1) { + mMaxExpectedDelayNB = maxDelay; // 1 GSM symbol is approx. 1 km + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", maxDelay); + } else if (!strcmp(cmd.cmd, "SETRXGAIN")) { + int newGain = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &newGain) == 1) { + newGain = mRadioInterface->setRxGain(newGain, chan); + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", newGain); + } else if (!strcmp(cmd.cmd, "NOISELEV")) { if (mOn) { float lev = mStates[chan].mNoiseLev; - snprintf(response, response_size, "RSP NOISELEV 0 %d", + rsp.status = 0; + snprintf(rsp.params, sizeof(rsp.params), "%d", (int) round(20.0 * log10(rxFullScale / lev))); - } - else { - snprintf(response, response_size, "RSP NOISELEV 1 0"); - } - } else if (match_cmd(command, "SETPOWER", ¶ms)) { - int power; - sscanf(params, "%d", &power); - power = mRadioInterface->setPowerAttenuation(power, chan); - mStates[chan].mPower = power; - snprintf(response, response_size, "RSP SETPOWER 0 %d", power); - } else if (match_cmd(command, "ADJPOWER", ¶ms)) { - int power, step; - sscanf(params, "%d", &step); - power = mStates[chan].mPower + step; - power = mRadioInterface->setPowerAttenuation(power, chan); - mStates[chan].mPower = power; - snprintf(response, response_size, "RSP ADJPOWER 0 %d", power); - } else if (match_cmd(command, "NOMTXPOWER", NULL)) { - int power = mRadioInterface->getNominalTxPower(chan); - snprintf(response, response_size, "RSP NOMTXPOWER 0 %d", power); - } else if (match_cmd(command, "RXTUNE", ¶ms)) { - // tune receiver - int freqKhz; - sscanf(params, "%d", &freqKhz); - mRxFreq = (freqKhz + cfg->freq_offset_khz) * 1e3; - if (!mRadioInterface->tuneRx(mRxFreq, chan)) { - LOGCHAN(chan, DTRXCTRL, FATAL) << "RX failed to tune"; - snprintf(response, response_size, "RSP RXTUNE 1 %d", freqKhz); - } - else - snprintf(response, response_size, "RSP RXTUNE 0 %d", freqKhz); - } else if (match_cmd(command, "TXTUNE", ¶ms)) { - // tune txmtr - int freqKhz; - sscanf(params, "%d", &freqKhz); - mTxFreq = (freqKhz + cfg->freq_offset_khz) * 1e3; - if (!mRadioInterface->tuneTx(mTxFreq, chan)) { - LOGCHAN(chan, DTRXCTRL, FATAL) << "TX failed to tune"; - snprintf(response, response_size, "RSP TXTUNE 1 %d", freqKhz); - } - else - snprintf(response, response_size, "RSP TXTUNE 0 %d", freqKhz); - } else if (match_cmd(command, "SETTSC", ¶ms)) { - // set TSC - unsigned TSC; - sscanf(params, "%u", &TSC); - if (TSC > 7) { - snprintf(response, response_size, "RSP SETTSC 1 %d", TSC); } else { + snprintf(rsp.params, sizeof(rsp.params), "0"); + } + } else if (!strcmp(cmd.cmd, "SETPOWER")) { + int power = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &power) == 1) { + power = mRadioInterface->setPowerAttenuation(power, chan); + mStates[chan].mPower = power; + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", power); + } else if (!strcmp(cmd.cmd, "ADJPOWER")) { + int power = mStates[chan].mPower, step; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &step) == 1) { + power = mStates[chan].mPower + step; + power = mRadioInterface->setPowerAttenuation(power, chan); + mStates[chan].mPower = power; + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", power); + } else if (!strcmp(cmd.cmd, "NOMTXPOWER")) { + int power = mRadioInterface->getNominalTxPower(chan); + rsp.status = 0; + snprintf(rsp.params, sizeof(rsp.params), "%d", power); + } else if (!strcmp(cmd.cmd, "RXTUNE")) { + // tune receiver + int freqKhz = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &freqKhz) == 1) { + mRxFreq = (freqKhz + cfg->freq_offset_khz) * 1e3; + if (!mRadioInterface->tuneRx(mRxFreq, chan)) + LOGCHAN(chan, DTRXCTRL, FATAL) << "RX failed to tune"; + else + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", freqKhz); + } else if (!strcmp(cmd.cmd, "TXTUNE")) { + // tune txmtr + int freqKhz = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &freqKhz) == 1) { + mTxFreq = (freqKhz + cfg->freq_offset_khz) * 1e3; + if (!mRadioInterface->tuneTx(mTxFreq, chan)) + LOGCHAN(chan, DTRXCTRL, FATAL) << "TX failed to tune"; + else + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", freqKhz); + } else if (!strcmp(cmd.cmd, "SETTSC")) { + // set TSC + unsigned TSC = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%u", &TSC) == 1 && TSC <= 7) { LOGC(DTRXCTRL, NOTICE) << "Changing TSC from " << mTSC << " to " << TSC; mTSC = TSC; - snprintf(response, response_size, "RSP SETTSC 0 %d", TSC); + rsp.status = 0; } - } else if (match_cmd(command, "SETSLOT", ¶ms)) { + snprintf(rsp.params, sizeof(rsp.params), "%u", TSC); + } else if (!strcmp(cmd.cmd, "SETSLOT")) { // set slot type - int corrCode; - int timeslot; - sscanf(params, "%d %d", ×lot, &corrCode); - if ((timeslot < 0) || (timeslot > 7)) { + struct osmo_trxc_setslot ss; + if (osmo_trxc_setslot_parse(&ss, &cmd) < 0) { LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus message on control interface"; - snprintf(response, response_size, "RSP SETSLOT 1 %d %d", timeslot, corrCode); - return 0; + } else if (ss.vamos) { + LOGCHAN(chan, DTRXCTRL, NOTICE) << "VAMOS channel combinations are not supported"; + } else { + mStates[chan].chanType[ss.tn] = (ChannelCombination) ss.chan_comb; + setModulus(ss.tn, chan); + rsp.status = 0; } - mStates[chan].chanType[timeslot] = (ChannelCombination) corrCode; - setModulus(timeslot, chan); - snprintf(response, response_size, "RSP SETSLOT 0 %d %d", timeslot, corrCode); - } else if (match_cmd(command, "SETFORMAT", ¶ms)) { + snprintf(rsp.params, sizeof(rsp.params), "%s", cmd.params); + } else if (!strcmp(cmd.cmd, "SETFORMAT")) { // set TRXD protocol version - unsigned version_recv; - sscanf(params, "%u", &version_recv); + unsigned version_recv = 0; + osmo_trxc_msg_params_scan(&cmd, "%u", &version_recv); LOGCHAN(chan, DTRXCTRL, INFO) << "BTS requests TRXD version switch: " << version_recv; if (version_recv > TRX_DATA_FORMAT_VER) { LOGCHAN(chan, DTRXCTRL, INFO) << "rejecting TRXD version " << version_recv << " in favor of " << TRX_DATA_FORMAT_VER; - snprintf(response, response_size, "RSP SETFORMAT %u %u", TRX_DATA_FORMAT_VER, version_recv); + rsp.status = TRX_DATA_FORMAT_VER; } else { LOGCHAN(chan, DTRXCTRL, NOTICE) << "switching to TRXD version " << version_recv; mVersionTRXD[chan] = version_recv; - snprintf(response, response_size, "RSP SETFORMAT %u %u", version_recv, version_recv); + rsp.status = version_recv; } - } else if (match_cmd(command, "RFMUTE", ¶ms)) { + snprintf(rsp.params, sizeof(rsp.params), "%u", version_recv); + } else if (!strcmp(cmd.cmd, "RFMUTE")) { // (Un)mute RF TX and RX - unsigned mute; - sscanf(params, "%u", &mute); - mStates[chan].mMuted = mute ? true : false; - snprintf(response, response_size, "RSP RFMUTE 0 %u", mute); - } else if (match_cmd(command, "_SETBURSTTODISKMASK", ¶ms)) { + unsigned mute = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%u", &mute) == 1) { + mStates[chan].mMuted = mute ? true : false; + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%u", mute); + } else if (!strcmp(cmd.cmd, "_SETBURSTTODISKMASK")) { // debug command! may change or disappear without notice // set a mask which bursts to dump to disk - int mask; - sscanf(params, "%d", &mask); - mWriteBurstToDiskMask = mask; - snprintf(response, response_size, "RSP _SETBURSTTODISKMASK 0 %d", mask); + int mask = 0; + if (osmo_trxc_msg_params_scan(&cmd, "%d", &mask) == 1) { + mWriteBurstToDiskMask = mask; + rsp.status = 0; + } + snprintf(rsp.params, sizeof(rsp.params), "%d", mask); } else { - LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus command " << command << " on control interface."; - snprintf(response, response_size, "RSP ERR 1"); + LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus command " << cmd.cmd << " on control interface."; + snprintf(rsp.cmd, sizeof(rsp.cmd), "%s", OSMO_TRXC_CMD_ERR); }
- LOGCHAN(chan, DTRXCTRL, INFO) << "response is '" << response << "'"; - transceiver->ctrl_sock_send(cmd_to_send, chan); + LOGCHAN(chan, DTRXCTRL, INFO) << "response is '" << osmo_trxc_msg_name(&rsp) << "'"; + + rc = osmo_trxc_msg_build(cmd_to_send.data, sizeof(cmd_to_send.data), &rsp); + if (rc < 0) { + LOGCHAN(chan, DTRXCTRL, ERROR) << "failed to build response (rc=" << rc << ")"; + return -EIO; + } + ctrl_sock_send(cmd_to_send, chan); return 0; }
bool Transceiver::driveTxPriorityQueue(size_t chan) { + char buffer[OSMO_TRXD_MSG_BUF_SIZE]; int msgLen; - int burstLen; - struct trxd_hdr_v01_dl *dl; - char buffer[sizeof(*dl) + EDGE_BURST_NBITS]; - uint32_t fn; - uint8_t tn; + struct osmo_trxd_parse_state st; + struct osmo_trxd_burst_req br; + int rc;
// check data socket msgLen = read(mDataSockets[chan], buffer, sizeof(buffer)); @@ -1100,48 +1108,37 @@ return false; }
- switch (msgLen) { - case sizeof(*dl) + gSlotLen: /* GSM burst */ - burstLen = gSlotLen; - break; - case sizeof(*dl) + EDGE_BURST_NBITS: /* EDGE burst */ - if (cfg->tx_sps != 4) { - LOGCHAN(chan, DTRXDDL, ERROR) << "EDGE burst received but SPS is set to " << cfg->tx_sps; - return false; - } - burstLen = EDGE_BURST_NBITS; - break; - default: - LOGCHAN(chan, DTRXDDL, ERROR) << "badly formatted packet on GSM->TRX interface (len="<< msgLen << ")"; - return false; - } - - dl = (struct trxd_hdr_v01_dl *) buffer; - - /* Convert TDMA FN to the host endianness */ - fn = osmo_load32be(&dl->common.fn); - tn = dl->common.tn; - - /* Make sure we support the received header format */ - switch (dl->common.version) { - case 0: - /* Version 1 has the same format */ - case 1: - break; - default: - LOGCHAN(chan, DTRXDDL, ERROR) << "Rx TRXD message with unknown header version " << unsigned(dl->common.version); + osmo_trxd_parse_state_init(&st); + rc = osmo_trxd_burst_req_parse(&st, &br, (const uint8_t *) buffer, msgLen); + if (rc < 0) { + LOGCHAN(chan, DTRXDDL, ERROR) << "failed to parse BURST.req (rc=" << rc << ")"; return false; }
- LOGCHAN(chan, DTRXDDL, DEBUG) << "Rx TRXD message (hdr_ver=" << unsigned(dl->common.version) - << "): fn=" << fn << ", tn=" << unsigned(tn) << ", burst_len=" << burstLen; + switch (br.burst_len) { + case gSlotLen: /* GSM burst */ + break; + case EDGE_BURST_NBITS: /* EDGE burst */ + if (cfg->tx_sps != 4) { + LOGCHAN(chan, DTRXDDL, ERROR) << "EDGE burst received but SPS is set to " << cfg->tx_sps; + return false; + } + break; + default: + LOGCHAN(chan, DTRXDDL, ERROR) << "badly formatted packet on GSM->TRX interface (burst_len=" + << br.burst_len << ")"; + return false; + } + + LOGCHAN(chan, DTRXDDL, DEBUG) << "Rx TRXD message: fn=" << br.fn << ", tn=" << unsigned(br.tn) + << ", burst_len=" << br.burst_len;
TransceiverState *state = &mStates[chan]; - GSM::Time currTime = GSM::Time(fn, tn); + GSM::Time currTime = GSM::Time(br.fn, br.tn);
/* Verify proper FN order in DL stream */ - if (state->first_dl_fn_rcv[tn]) { - int32_t delta = GSM::FNDelta(currTime.FN(), state->last_dl_time_rcv[tn].FN()); + if (state->first_dl_fn_rcv[br.tn]) { + int32_t delta = GSM::FNDelta(currTime.FN(), state->last_dl_time_rcv[br.tn].FN()); if (delta == 1) { /* usual expected scenario, continue code flow */ } else if (delta == 0) { @@ -1151,7 +1148,7 @@ return true; } else if (delta < 0) { LOGCHAN(chan, DTRXDDL, INFO) << "Rx TRXD msg with previous FN " << currTime - << " vs last " << state->last_dl_time_rcv[tn]; + << " vs last " << state->last_dl_time_rcv[br.tn]; state->ctrs.tx_trxd_fn_outoforder++; dispatch_trx_rate_ctr_change(state, chan); /* Allow adding radio vector below, since it gets sorted in the queue */ @@ -1161,25 +1158,25 @@ * setups. Also, osmo-trx supports optionally filling empty bursts on * its own. In that case bts-trx is not obliged to submit all bursts. */ LOGCHAN(chan, DTRXDDL, INFO) << "Rx TRXD msg with future FN " << currTime - << " vs last " << state->last_dl_time_rcv[tn] + << " vs last " << state->last_dl_time_rcv[br.tn] << ", " << delta - 1 << " FN lost"; state->ctrs.tx_trxd_fn_skipped += delta - 1; dispatch_trx_rate_ctr_change(state, chan); } if (delta > 0) - state->last_dl_time_rcv[tn] = currTime; + state->last_dl_time_rcv[br.tn] = currTime; } else { /* Initial check, simply store state */ - state->first_dl_fn_rcv[tn] = true; - state->last_dl_time_rcv[tn] = currTime; + state->first_dl_fn_rcv[br.tn] = true; + state->last_dl_time_rcv[br.tn] = currTime; }
- BitVector newBurst(burstLen); + BitVector newBurst(br.burst_len); BitVector::iterator itr = newBurst.begin(); - uint8_t *bufferItr = dl->soft_bits; + const ubit_t *bufferItr = br.burst; while (itr < newBurst.end()) *itr++ = *bufferItr++;
- addRadioVector(chan, newBurst, dl->tx_att, currTime); + addRadioVector(chan, newBurst, br.att, currTime);
return true; } @@ -1203,32 +1200,36 @@ return true; }
-void Transceiver::logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi) +void Transceiver::logRxBurst(size_t chan, const struct osmo_trxd_burst_ind *bi) { std::ostringstream os; - for (size_t i=0; i < bi->nbits; i++) { - if (bi->rx_burst[i] > 0.5) os << "1"; - else if (bi->rx_burst[i] > 0.25) os << "|"; - else if (bi->rx_burst[i] > 0.0) os << "'"; + for (size_t i = 0; i < bi->burst_len; i++) { + /* sbit_t polarity: <0 confident '1', 127 confident '0' (see float_soft_bit_to_sbit()) */ + if (bi->burst[i] < 0) os << "1"; + else if (bi->burst[i] < 64) os << "|"; + else if (bi->burst[i] < 127) os << "'"; else os << "-"; }
double rssi_offset = rssiOffset(chan); + double noise_dbfs = 20.0 * log10(rxFullScale / mStates[chan].mNoiseLev) + rssi_offset; + double rssi_dbfs = -bi->rssi - rssi_offset;
LOGCHAN(chan, DTRXDUL, DEBUG) << std::fixed << std::right << " time: " << unsigned(bi->tn) << ":" << bi->fn - << " RSSI: " << std::setw(5) << std::setprecision(1) << (bi->rssi - rssi_offset) - << "dBFS/" << std::setw(6) << -bi->rssi << "dBm" - << " noise: " << std::setw(5) << std::setprecision(1) << (bi->noise - rssi_offset) - << "dBFS/" << std::setw(6) << -bi->noise << "dBm" - << " TOA: " << std::setw(5) << std::setprecision(2) << bi->toa - << " C/I: " << std::setw(5) << std::setprecision(2) << bi->ci << "dB" + << " RSSI: " << std::setw(5) << std::setprecision(1) << rssi_dbfs + << "dBFS/" << std::setw(6) << int(bi->rssi) << "dBm" + << " noise: " << std::setw(5) << std::setprecision(1) << (noise_dbfs - rssi_offset) + << "dBFS/" << std::setw(6) << -noise_dbfs << "dBm" + << " TOA: " << std::setw(5) << std::setprecision(2) << (bi->toa256 / 256.0) + << " C/I: " << std::setw(5) << std::setprecision(2) << (bi->ci_cb / 10.0) << "dB" << " bits: " << os; }
bool Transceiver::driveReceiveFIFO(size_t chan) { - struct trx_ul_burst_ind bi; + struct osmo_trxd_burst_ind bi; + struct msgb *msg; int rc;
if ((rc = pullRadioVector(chan, &bi)) < 0) { @@ -1239,17 +1240,26 @@ return false; /* other errors: we want to stop the process */ }
- if (!bi.idle && log_check_level(DTRXDUL, LOGL_DEBUG)) + if (!(bi.flags & OSMO_TRXD_F_NOPE_IND) && log_check_level(DTRXDUL, LOGL_DEBUG)) logRxBurst(chan, &bi);
- switch (mVersionTRXD[chan]) { - case 0: - return trxd_send_burst_ind_v0(chan, mDataSockets[chan], &bi); - case 1: - return trxd_send_burst_ind_v1(chan, mDataSockets[chan], &bi); - default: - OSMO_ASSERT(false); + msg = mBurstIndMsg[chan]; + rc = osmo_trxd_burst_ind_build(msg, mVersionTRXD[chan], &bi); + if (rc < 0) { + LOGCHAN(chan, DTRXDUL, ERROR) << "failed to build BURST.ind (rc=" << rc << ")"; + msgb_trim(msg, 0); + return false; } + osmo_trxd_build_fin(msg, mVersionTRXD[chan]); + + rc = write(mDataSockets[chan], msgb_data(msg), msgb_length(msg)); + msgb_trim(msg, 0); + if (rc < 0) { + LOGCHAN(chan, DTRXDUL, NOTICE) << "mDataSockets write(" << mDataSockets[chan] << ") failed: " << rc; + return false; + } + + return true; }
void Transceiver::driveTxFIFO() @@ -1310,16 +1320,22 @@
bool Transceiver::writeClockInterface() { - int msgLen; char command[50]; + int rc; // FIXME -- This should be adaptive. - sprintf(command,"IND CLOCK %llu",(unsigned long long) (mTransmitDeadlineClock.FN()+2)); + uint32_t fn = mTransmitDeadlineClock.FN() + 2; + + rc = osmo_trxc_clock_ind_build(command, sizeof(command), fn); + if (rc < 0) { + LOGC(DTRXCLK, ERROR) << "failed to build IND CLOCK " << fn; + return false; + }
LOGC(DTRXCLK, INFO) << "sending " << command;
- msgLen = write(mClockSocket, command, strlen(command) + 1); - if (msgLen <= 0) { - LOGC(DTRXCLK, ERROR) << "mClockSocket write(" << mClockSocket << ") failed: " << msgLen; + rc = write(mClockSocket, command, strlen(command) + 1); + if (rc <= 0) { + LOGC(DTRXCLK, ERROR) << "mClockSocket write(" << mClockSocket << ") failed: " << rc; return false; }
diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h index babe420..53b887e 100644 --- a/Transceiver52M/Transceiver.h +++ b/Transceiver52M/Transceiver.h @@ -34,6 +34,8 @@ extern "C" { #include <osmocom/core/signal.h> #include <osmocom/core/select.h> +#include <osmocom/trx/trxc.h> +#include <osmocom/trx/trxd.h> #include "config_defs.h" }
@@ -41,6 +43,9 @@
extern Transceiver *transceiver;
+/* The latest TRXD header format version advertised/accepted by this TRX implementation */ +#define TRX_DATA_FORMAT_VER 1 + /** Channel descriptor for transceiver object and channel number pair */ struct TrxChanThParams { Transceiver *trx; @@ -150,7 +155,7 @@ private: size_t mChans; struct ctrl_msg { - char data[101]; + char data[OSMO_TRXC_MSG_BUF_SIZE]; ctrl_msg() {}; };
@@ -202,7 +207,7 @@ void pushRadioVector(GSM::Time &nowTime);
/** Pull and demodulate a burst from the receive FIFO */ - int pullRadioVector(size_t chan, struct trx_ul_burst_ind *ind); + int pullRadioVector(size_t chan, struct osmo_trxd_burst_ind *ind);
/** Set modulus for specific timeslot */ void setModulus(size_t timeslot, size_t chan); @@ -233,6 +238,11 @@ std::vector<unsigned> mVersionTRXD; ///< Format version to use for TRXD protocol communication, per channel std::vector<TransceiverState> mStates;
+ /* Per-channel BURST.ind scratch buffer (driveReceiveFIFO()): allocated + * once in the constructor, then reused (trimmed, not freed) for every + * burst to avoid an alloc/free pair on the Rx hot path. */ + std::vector<struct msgb *> mBurstIndMsg; + /** Start and stop I/O threads through the control socket API */ bool start(); void stop(); @@ -264,7 +274,7 @@ double rssiOffset(size_t chan); void reset();
- void logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi); + void logRxBurst(size_t chan, const struct osmo_trxd_burst_ind *bi); };
void *RxUpperLoopAdapter(TrxChanThParams *params); diff --git a/Transceiver52M/proto_trxd.c b/Transceiver52M/proto_trxd.c deleted file mode 100644 index 418daa6..0000000 --- a/Transceiver52M/proto_trxd.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2019 sysmocom - s.f.m.c. GmbH - * All Rights Reserved - * - * SPDX-License-Identifier: AGPL-3.0+ - * - * Author: Pau Espin Pedrol pespin@sysmocom.de - * - * 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 "proto_trxd.h" - -#include <osmocom/core/bits.h> - -static void trxd_fill_common(struct trxd_hdr_common *common, const struct trx_ul_burst_ind *bi, uint8_t version) -{ - common->version = version & 0b1111; - common->reserved = 0; - common->tn = bi->tn; - osmo_store32be(bi->fn, &common->fn); -} - -static void trxd_fill_v0_specific(struct trxd_hdr_v0_specific *v0, const struct trx_ul_burst_ind *bi) -{ - int toa_int; - - /* in 1/256 symbols, round to closest integer */ - toa_int = (int) lround(bi->toa * 256.0); - v0->rssi = (uint8_t) lround(bi->rssi); - osmo_store16be(toa_int, &v0->toa); -} - -static void trxd_fill_v1_specific(struct trxd_hdr_v1_specific *v1, const struct trx_ul_burst_ind *bi) -{ - int16_t ci_int_cB; - - /* deciBels->centiBels, round to closest integer */ - ci_int_cB = (int16_t) lround(bi->ci * 10.0); - - v1->idle = !!bi->idle; - v1->modulation = (bi->modulation == MODULATION_GMSK) ? - TRXD_MODULATION_GMSK(bi->tss) : - TRXD_MODULATION_8PSK(bi->tss); - v1->tsc = bi->tsc; - osmo_store16be(ci_int_cB, &v1->ci); -} - -static void trxd_fill_burst_normalized255(uint8_t* soft_bits, const struct trx_ul_burst_ind *bi) -{ - unsigned i; - for (i = 0; i < bi->nbits; i++) - soft_bits[i] = (uint8_t) round(bi->rx_burst[i] * 255.0); -} - -bool trxd_send_burst_ind_v0(size_t chan, int fd, const struct trx_ul_burst_ind *bi) { - int rc; - - /* v0 doesn't support idle frames, they are simply dropped, not sent */ - if (bi->idle) - return true; - - /* +2: Historically (OpenBTS times), two extra non-used bytes are sent appended to each burst */ - char buf[sizeof(struct trxd_hdr_v0) + bi->nbits + 2]; - struct trxd_hdr_v0* pkt = (struct trxd_hdr_v0*)buf; - - trxd_fill_common(&pkt->common, bi, 0); - trxd_fill_v0_specific(&pkt->v0, bi); - trxd_fill_burst_normalized255(&pkt->soft_bits[0], bi); - - /* +1: Historical reason. There's an uninitizalied byte in there: pkt->soft_bits[bi->nbits] */ - pkt->soft_bits[bi->nbits + 1] = '\0'; - - rc = write(fd, buf, sizeof(struct trxd_hdr_v0) + bi->nbits + 2); - if (rc <= 0) { - CLOGCHAN(chan, DMAIN, LOGL_NOTICE, "mDataSockets write(%d) failed: %d\n", fd, rc); - return false; - } - return true; -} - -bool trxd_send_burst_ind_v1(size_t chan, int fd, const struct trx_ul_burst_ind *bi) { - int rc; - size_t buf_len; - - buf_len = sizeof(struct trxd_hdr_v1); - if (!bi->idle) - buf_len += bi->nbits; - char buf[buf_len]; - - struct trxd_hdr_v1* pkt = (struct trxd_hdr_v1*)buf; - trxd_fill_common(&pkt->common, bi, 1); - trxd_fill_v0_specific(&pkt->v0, bi); - trxd_fill_v1_specific(&pkt->v1, bi); - - if (!bi->idle) - trxd_fill_burst_normalized255(&pkt->soft_bits[0], bi); - - rc = write(fd, buf, buf_len); - if (rc <= 0) { - CLOGCHAN(chan, DMAIN, LOGL_NOTICE, "mDataSockets write(%d) failed: %d\n", fd, rc); - return false; - } - return true; -} diff --git a/Transceiver52M/proto_trxd.h b/Transceiver52M/proto_trxd.h deleted file mode 100644 index c250a74..0000000 --- a/Transceiver52M/proto_trxd.h +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include <stdint.h> -#include <stdbool.h> -#include <unistd.h> -#include <math.h> - -#include <osmocom/core/endian.h> - -#include "debug.h" - -#define MAX_RX_BURST_BUF_SIZE 444 /* 444 = EDGE_BURST_NBITS */ - -enum Modulation { - MODULATION_GMSK, - MODULATION_8PSK, -/* Not supported yet: - MODULATION_AQPSK, - MODULATION_16QAM, - MODULATION_32QAM -*/ -}; - -struct trx_ul_burst_ind { - float rx_burst[MAX_RX_BURST_BUF_SIZE]; /* soft bits normalized 0..1 */ - unsigned nbits; // number of symbols per slot in rxBurst, not counting guard periods - uint32_t fn; // TDMA frame number - uint8_t tn; // TDMA time-slot number - double rssi; // in dBFS - double toa; // in symbols - double noise; // noise level in dBFS - bool idle; // true if no valid burst is included - enum Modulation modulation; // modulation type - uint8_t tss; // training sequence set - uint8_t tsc; // training sequence code - float ci; // Carrier-to-Interference ratio, in dB -}; - -bool trxd_send_burst_ind_v0(size_t chan, int fd, const struct trx_ul_burst_ind *bi); -bool trxd_send_burst_ind_v1(size_t chan, int fd, const struct trx_ul_burst_ind *bi); - -/* The latest supported TRXD header format version */ -#define TRX_DATA_FORMAT_VER 1 - -struct trxd_hdr_common { -#if OSMO_IS_LITTLE_ENDIAN - uint8_t tn:3, - reserved:1, - version:4; -#elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ - uint8_t version:4, reserved:1, tn:3; -#endif - uint32_t fn; /* big endian */ -} __attribute__ ((packed)); - -struct trxd_hdr_v0_specific { - uint8_t rssi; - uint16_t toa; /* big endian */ -} __attribute__ ((packed)); - -struct trxd_hdr_v0 { - struct trxd_hdr_common common; - struct trxd_hdr_v0_specific v0; - uint8_t soft_bits[0]; -} __attribute__ ((packed)); - -/* Downlink burst (BTS->TRX), v0 anf v1 use same format */ -struct trxd_hdr_v01_dl { - struct trxd_hdr_common common; - uint8_t tx_att; /* Tx Attentuation */ - uint8_t soft_bits[0]; -} __attribute__ ((packed)); - - -#define TRXD_MODULATION_GMSK(ts_set) (0b0000 | (ts_set & 0b0011)) -#define TRXD_MODULATION_8PSK(ts_set) (0b0100 | (ts_set & 0b0001)) -#define TRXD_MODULATION_AQPSK(ts_set) (0b0110 | (ts_set & 0b0001)) -#define TRXD_MODULATION_16QAM(ts_set) (0b1000 | (ts_set & 0b0001)) -#define TRXD_MODULATION_32QAM(ts_set) (0b1010 | (ts_set & 0b0001)) - -struct trxd_hdr_v1_specific { -#if OSMO_IS_LITTLE_ENDIAN - uint8_t tsc:3, - modulation:4, - idle:1; -#elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ - uint8_t idle:1, modulation:4, tsc:3; -#endif - int16_t ci; /* big endian, in centiBels */ -} __attribute__ ((packed)); - -struct trxd_hdr_v1 { - struct trxd_hdr_common common; - struct trxd_hdr_v0_specific v0; - struct trxd_hdr_v1_specific v1; - uint8_t soft_bits[0]; -} __attribute__ ((packed)); diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp index 5fac365..c3483d7 100644 --- a/Transceiver52M/sigProcLib.cpp +++ b/Transceiver52M/sigProcLib.cpp @@ -542,19 +542,6 @@ return pulse; }
-/* Convert -1..+1 soft bits to 0..1 soft bits */ -void vectorSlicer(float *dest, const float *src, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) { - dest[i] = 0.5 * (src[i] + 1.0f); - if (dest[i] > 1.0) - dest[i] = 1.0; - else if (dest[i] < 0.0) - dest[i] = 0.0; - } -} - static signalVector *rotateBurst(const BitVector &wBurst, int guardPeriodLength, int sps) { diff --git a/Transceiver52M/sigProcLib.h b/Transceiver52M/sigProcLib.h index 39c8ddd..97da08e 100644 --- a/Transceiver52M/sigProcLib.h +++ b/Transceiver52M/sigProcLib.h @@ -59,9 +59,6 @@ /** Destroy the signal processing library */ void sigProcLibDestroy(void);
-/** Operate soft slicer on a soft-bit vector */ -void vectorSlicer(float *dest, const float *src, size_t len); - /** GMSK modulate a GSM burst of bits */ signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength,