trcon<->l1 data if without sockets

direct call of UL rx receive data handler + sched check if ts is active
tx dir call stub for for tx thread queue.

Change-Id: I5911004db58742cf39b968fcf87bc1243f7a374a
diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am
index c4434fe..6b76d25 100644
--- a/Transceiver52M/Makefile.am
+++ b/Transceiver52M/Makefile.am
@@ -191,7 +191,6 @@
 	ms/bladerf_specific.h \
 	ms/uhd_specific.h \
 	ms/ms_rx_upper.h \
-	ms/ms_state.h \
 	itrq.h
 # -fsanitize=address,undefined -shared-libsan -O0
 #
diff --git a/Transceiver52M/ms/ms_commandhandler.cpp b/Transceiver52M/ms/ms_commandhandler.cpp
index be1eec4..940b298 100644
--- a/Transceiver52M/ms/ms_commandhandler.cpp
+++ b/Transceiver52M/ms/ms_commandhandler.cpp
@@ -20,10 +20,8 @@
  */
 
 #include <radioInterface.h>
-#include "l1if.h"
 #include "ms_rx_upper.h"
 #include "syncthing.h"
-#include "ms_state.h"
 
 void upper_trx::driveControl()
 {
@@ -199,8 +197,6 @@
 			sprintf(response, "RSP SETSLOT 1 %d %d", timeslot, corrCode);
 			return;
 		}
-		mStates.chanType[timeslot] = (ChannelCombination)corrCode;
-		mStates.setModulus(timeslot);
 		sprintf(response, "RSP SETSLOT 0 %d %d", timeslot, corrCode);
 	} else if (!strcmp(command, "SETRXMASK")) {
 		int slot;
@@ -214,7 +210,6 @@
 		}
 	} else if (!strcmp(command, "SYNC")) {
 		// msleep(10);
-		mStates.mode = trx_mode::TRX_MODE_MS_TRACK;
 		sprintf(response, "RSP SYNC 0");
 		mMaxExpectedDelay = 48;
 		// setRxGain(30);
diff --git a/Transceiver52M/ms/ms_rx_upper.cpp b/Transceiver52M/ms/ms_rx_upper.cpp
index 7f4d4af..5d53221 100644
--- a/Transceiver52M/ms/ms_rx_upper.cpp
+++ b/Transceiver52M/ms/ms_rx_upper.cpp
@@ -21,12 +21,10 @@
 
 #include "sigProcLib.h"
 #include "syncthing.h"
-#include "l1if.h"
 #include <signalVector.h>
 #include <radioVector.h>
 #include <radioInterface.h>
 #include "grgsm_vitac/grgsm_vitac.h"
-#include "ms_state.h"
 #include "ms_rx_upper.h"
 
 extern "C" {
@@ -39,6 +37,15 @@
 void __lsan_do_recoverable_leak_check();
 }
 
+namespace trxcon
+{
+extern "C" {
+#include <trxcon/trx_if.h>
+}
+trx_instance *trxcon_instance; // local handle
+static tx_queue_t txq;
+} // namespace trxcon
+
 #ifdef LOG
 #undef LOG
 #define LOG(...) upper_trx::dummy_log()
@@ -89,35 +96,6 @@
 	ms_trx::start();
 }
 
-/* Detect SCH synchronization sequence within a burst */
-bool upper_trx::detectSCH(ms_TransceiverState *state, signalVector &burst, struct estim_burst_params *ebp)
-{
-	int shift;
-	sch_detect_type full;
-	float mag, threshold = 4.0;
-
-	full = (state->mode == trx_mode::TRX_MODE_MS_TRACK) ? sch_detect_type::SCH_DETECT_NARROW :
-							      sch_detect_type::SCH_DETECT_FULL;
-
-	if (!detectSCHBurst(burst, threshold, rx_sps, full, ebp))
-		return false;
-
-	std::clog << "SCH : Timing offset     " << ebp->toa << " symbols" << std::endl;
-
-	mag = fabsf(ebp->toa);
-	if (mag < 1.0f)
-		return true;
-
-	shift = (int)(mag / 2.0f);
-	if (!shift)
-		shift++;
-
-	shift = ebp->toa > 0 ? shift : -shift;
-	std::clog << "SCH : shift ->     " << shift << " symbols" << std::endl;
-	// mRadioInterface->applyOffset(shift);
-	return false;
-}
-
 SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset) __attribute__((optnone))
 {
 	float pow, avg = 1.0;
@@ -161,50 +139,20 @@
 		return &bits;
 	}
 
-	CorrType type = TSC;
-
-	// tickle UL by returning null bursts if demod is skipped due to unused TS
-	switch (mStates.mode) {
-	case trx_mode::TRX_MODE_MS_TRACK:
-		if (mStates.chanType[burst_time.TN()] == ChannelCombination::NONE_INACTIVE) {
-			type = OFF;
-			goto release;
-		} else if (is_sch)
-			type = SCH;
-		else if (!is_fcch) // all ts0, but not fcch or sch..
-			type = TSC;
-		break;
-
-	case trx_mode::TRX_MODE_OFF:
-	default:
-		goto release;
-	}
+	auto ts = trxcon::trxcon_instance->ts_list[burst_time.TN()];
+	if (ts == NULL || ts->mf_layout == NULL)
+		return 0;
 
 	convert_and_scale<float, int16_t>(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
 
 	pow = energyDetect(sv, 20 * rx_sps);
 	if (pow < -1) {
 		LOG(ALERT) << "Received empty burst";
-		goto release;
+		return NULL;
 	}
 
 	avg = sqrt(pow);
-
-	if (type == SCH) {
-		std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
-		int d_c0_burst_start = get_sch_chan_imp_resp(ss, &chan_imp_resp[0]);
-		detect_burst(ss, &chan_imp_resp[0], d_c0_burst_start, outbin);
-
-		for (int i = 0; i < 148; i++)
-			(bits)[i] = (!outbin[i]) < 1 ? -1 : 1;
-
-		// auto rv = decode_sch(bits->begin(), false);
-		// dbgout << "U SCH@"
-		//        << " " << e.gsmts.FN() << ":" << e.gsmts.TN() << " " << d_c0_burst_start
-		//        << " DECODE:" << (rv ? "yes" : "---") << std::endl;
-
-		// std::cerr << dbgout.str();
-	} else {
+	{
 		float ncmax, dcmax;
 		std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 		std::complex<float> chan_imp_resp2[CHAN_IMP_RESP_LENGTH * d_OSR];
@@ -227,14 +175,10 @@
 		for (int i = 0; i < 148; i++)
 			(bits)[i] = (outbin[i]) < 1 ? -1 : 1;
 	}
-
 	RSSI = (int)floor(20.0 * log10(rxFullScale / avg));
 	timingOffset = (int)round(0);
 
 	return &bits;
-
-release:
-	return NULL;
 }
 
 void upper_trx::driveReceiveFIFO()
@@ -248,12 +192,13 @@
 
 	SoftVector *rxBurst = pullRadioVector(burstTime, RSSI, TOA);
 
-	trxd_from_trx response;
-	response.ts = burstTime.TN();
-	response.fn = htonl(burstTime.FN());
-	response.rssi = RSSI;
-	response.toa = htons(TOA);
 	if (rxBurst) {
+		trxd_from_trx response;
+		response.ts = burstTime.TN();
+		response.fn = htonl(burstTime.FN());
+		response.rssi = RSSI;
+		response.toa = htons(TOA);
+
 		SoftVector::const_iterator burstItr = rxBurst->begin();
 		if (burstTime.TN() == 0 && gsm_sch_check_fn(burstTime.FN())) {
 			clamp_array(rxBurst->begin(), 148, 1.5f);
@@ -267,45 +212,19 @@
 			for (int i = 0; i < 148; i++)
 				((int8_t *)response.symbols)[i] = *burstItr++ > 0.0f ? -127 : 127;
 		}
+		trxcon::trx_data_rx_handler(trxcon::trxcon_instance, (uint8_t *)&response);
 	}
-
-#ifdef IPCIF
-	push_d(response);
-#else
-	int rv = sendto(mDataSockets, &response, sizeof(trxd_from_trx), 0, (struct sockaddr *)&datadest,
-			sizeof(struct sockaddr_in));
-	if (rv < 0) {
-		std::cerr << "fuck, send?" << std::endl;
-		exit(0);
-	}
-
-#endif
 }
 
 void upper_trx::driveTx()
 {
-#ifdef IPCIF
-	auto burst = pop_d();
-	if (!burst) {
-		// std::cerr << "wtf no tx burst?" << std::endl;
-		// exit(0);
-		continue;
+	trxd_to_trx e;
+	while (!trxcon::txq.spsc_pop(&e)) {
+		trxcon::txq.spsc_prep_pop();
 	}
-#else
-	trxd_to_trx buffer;
 
-	socklen_t addr_len = sizeof(datasrc);
-	int rdln = recvfrom(mDataSockets, (void *)&buffer, sizeof(trxd_to_trx), 0, &datasrc, &addr_len);
-	if (rdln < 0 && errno == EAGAIN) {
-		std::cerr << "fuck, rcv?" << std::endl;
-		exit(0);
-	}
-	if(rdln < sizeof(buffer)) // nope ind has len 6 or something like that
-		return;
+	trxd_to_trx *burst = &e;
 
-
-	trxd_to_trx *burst = &buffer;
-#endif
 	auto proper_fn = ntohl(burst->fn);
 	// std::cerr << "got burst!" << proper_fn << ":" << burst->ts
 	// 	  << " current: " << timekeeper.gsmtime().FN()
@@ -341,30 +260,8 @@
 
 	submit_burst(burst_buf, txburst->size(), currTime);
 	delete txburst;
-
-#ifdef IPCIF
-	free(burst);
-#endif
 }
 
-// __attribute__((xray_always_instrument)) static void *rx_stream_callback(struct bladerf *dev,
-// 									struct bladerf_stream *stream,
-// 									struct bladerf_metadata *meta, void *samples,
-// 									size_t num_samples, void *user_data)
-// {
-// 	struct ms_trx *trx = (struct ms_trx *)user_data;
-// 	return trx->rx_cb(dev, stream, meta, samples, num_samples, user_data);
-// }
-
-// __attribute__((xray_always_instrument)) static void *tx_stream_callback(struct bladerf *dev,
-// 									struct bladerf_stream *stream,
-// 									struct bladerf_metadata *meta, void *samples,
-// 									size_t num_samples, void *user_data)
-// {
-// 	struct ms_trx *trx = (struct ms_trx *)user_data;
-// 	return BLADERF_STREAM_NO_DATA;
-// }
-
 int trxc_main(int argc, char *argv[])
 {
 	pthread_setname_np(pthread_self(), "main_trxc");
@@ -384,14 +281,21 @@
 	return status;
 }
 
-extern "C" volatile bool gshutdown = false;
-extern "C" void init_external_transceiver(int argc, char **argv)
+extern "C" {
+void init_external_transceiver(struct trx_instance *trx, int argc, char **argv)
 {
+	trxcon::trxcon_instance = (trxcon::trx_instance *)trx;
 	std::cout << "init?" << std::endl;
 	trxc_main(argc, argv);
 }
 
-extern "C" void stop_trx()
+void close_external_transceiver(int argc, char **argv)
 {
 	std::cout << "Shutting down transceiver..." << std::endl;
 }
+
+void tx_external_transceiver(uint8_t *burst)
+{
+	trxcon::txq.spsc_push((trxd_to_trx *)burst);
+}
+}
\ No newline at end of file
diff --git a/Transceiver52M/ms/ms_rx_upper.h b/Transceiver52M/ms/ms_rx_upper.h
index 09154bf..5e25a48 100644
--- a/Transceiver52M/ms/ms_rx_upper.h
+++ b/Transceiver52M/ms/ms_rx_upper.h
@@ -28,13 +28,12 @@
 #include "GSMCommon.h"
 #include "radioClock.h"
 #include "syncthing.h"
-#include "ms_state.h"
+#include "l1if.h"
 
+using tx_queue_t = spsc_cond<8 * 1, trxd_to_trx, true, false>;
 class upper_trx : public ms_trx {
 	int rx_sps, tx_sps;
 
-	ms_TransceiverState mStates;
-
 	bool mOn; ///< flag to indicate that transceiver is powered on
 	double mTxFreq; ///< the transmit frequency
 	double mRxFreq; ///< the receive frequency
@@ -42,9 +41,6 @@
 	unsigned mMaxExpectedDelay; ///< maximum TOA offset in GSM symbols
 	unsigned long long mRxSlotMask[8]; ///< MS - enabled multiframe slot mask
 
-	int mDataSockets;
-	sockaddr_in datadest;
-	sockaddr datasrc;
 	int mCtrlSockets;
 	sockaddr_in ctrldest;
 	sockaddr ctrlsrc;
@@ -98,8 +94,6 @@
 
 	SoftVector *pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset);
 
-	bool detectSCH(ms_TransceiverState *state, signalVector &burst, struct estim_burst_params *ebp);
-
 	std::thread thr_control, thr_rx, thr_tx;
 
     public:
@@ -110,12 +104,8 @@
 	{
 		auto c_srcport = 6700 + 2 * 0 + 1;
 		auto c_dstport = 6700 + 2 * 0 + 101;
-		auto d_srcport = 6700 + 2 * 0 + 2;
-		auto d_dstport = 6700 + 2 * 0 + 102;
 
 		openudp(&mCtrlSockets, c_srcport, "127.0.0.1");
-		openudp(&mDataSockets, d_srcport, "127.0.0.1");
 		resolveAddress(&ctrldest, "127.0.0.1", c_dstport);
-		resolveAddress(&datadest, "127.0.0.1", d_dstport);
 	};
 };
diff --git a/Transceiver52M/ms/ms_state.h b/Transceiver52M/ms/ms_state.h
deleted file mode 100644
index c00d072..0000000
--- a/Transceiver52M/ms/ms_state.h
+++ /dev/null
@@ -1,175 +0,0 @@
-#pragma once
-
-#include <radioVector.h>
-#include <signalVector.h>
-
-enum class trx_mode {
-	TRX_MODE_OFF,
-	TRX_MODE_BTS,
-	TRX_MODE_MS_ACQUIRE,
-	TRX_MODE_MS_TRACK,
-};
-
-enum class ChannelCombination {
-	FILL, ///< Channel is transmitted, but unused
-	I, ///< TCH/FS
-	II, ///< TCH/HS, idle every other slot
-	III, ///< TCH/HS
-	IV, ///< FCCH+SCH+CCCH+BCCH, uplink RACH
-	V, ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
-	VI, ///< CCCH+BCCH, uplink RACH
-	VII, ///< SDCCH/8 + SACCH/8
-	VIII, ///< TCH/F + FACCH/F + SACCH/M
-	IX, ///< TCH/F + SACCH/M
-	X, ///< TCH/FD + SACCH/MD
-	XI, ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
-	XII, ///< PCCCH+PDTCH+PACCH+PTCCH
-	XIII, ///< PDTCH+PACCH+PTCCH
-	NONE_INACTIVE, ///< Channel is inactive, default
-	LOOPBACK ///< similar go VII, used in loopback testing
-};
-
-struct ms_TransceiverState {
-	ms_TransceiverState() : mFreqOffsets(10), mode(trx_mode::TRX_MODE_OFF)
-	{
-		for (int i = 0; i < 8; i++) {
-			chanType[i] = ChannelCombination::NONE_INACTIVE;
-			fillerModulus[i] = 26;
-
-			for (int n = 0; n < 102; n++)
-				fillerTable[n][i] = nullptr;
-		}
-	}
-
-	~ms_TransceiverState()
-	{
-		for (int i = 0; i < 8; i++) {
-			for (int n = 0; n < 102; n++)
-				delete fillerTable[n][i];
-		}
-	}
-
-	void setModulus(size_t timeslot)
-	{
-		switch (chanType[timeslot]) {
-		case ChannelCombination::NONE_INACTIVE:
-		case ChannelCombination::I:
-		case ChannelCombination::II:
-		case ChannelCombination::III:
-		case ChannelCombination::FILL:
-			fillerModulus[timeslot] = 26;
-			break;
-		case ChannelCombination::IV:
-		case ChannelCombination::VI:
-		case ChannelCombination::V:
-			fillerModulus[timeslot] = 51;
-			break;
-			//case V:
-		case ChannelCombination::VII:
-			fillerModulus[timeslot] = 102;
-			break;
-		case ChannelCombination::XIII:
-			fillerModulus[timeslot] = 52;
-			break;
-		default:
-			break;
-		}
-	}
-
-	CorrType expectedCorrType(GSM::Time currTime, unsigned long long *mRxSlotMask)
-	{
-		unsigned burstTN = currTime.TN();
-		unsigned burstFN = currTime.FN();
-
-		if (mode == trx_mode::TRX_MODE_MS_TRACK) {
-			/* 102 modulus case currently unhandled */
-			if (fillerModulus[burstTN] > 52)
-				return OFF;
-
-			int modFN = burstFN % fillerModulus[burstTN];
-			unsigned long long reg = (unsigned long long)1 << modFN;
-			if (reg & mRxSlotMask[burstTN])
-				return TSC;
-			else
-				return OFF;
-		}
-
-		switch (chanType[burstTN]) {
-		case ChannelCombination::NONE_INACTIVE:
-			return OFF;
-			break;
-		case ChannelCombination::FILL:
-			return IDLE;
-			break;
-		case ChannelCombination::I:
-			return TSC;
-			/*if (burstFN % 26 == 25) 
-      return IDLE;
-    else
-      return TSC;*/
-			break;
-		case ChannelCombination::II:
-			return TSC;
-			break;
-		case ChannelCombination::III:
-			return TSC;
-			break;
-		case ChannelCombination::IV:
-		case ChannelCombination::VI:
-			return RACH;
-			break;
-		case ChannelCombination::V: {
-			int mod51 = burstFN % 51;
-			if ((mod51 <= 36) && (mod51 >= 14))
-				return RACH;
-			else if ((mod51 == 4) || (mod51 == 5))
-				return RACH;
-			else if ((mod51 == 45) || (mod51 == 46))
-				return RACH;
-			else
-				return TSC;
-			break;
-		}
-		case ChannelCombination::VII:
-			if ((burstFN % 51 <= 14) && (burstFN % 51 >= 12))
-				return IDLE;
-			else
-				return TSC;
-			break;
-		case ChannelCombination::XIII: {
-			int mod52 = burstFN % 52;
-			if ((mod52 == 12) || (mod52 == 38))
-				return RACH;
-			else if ((mod52 == 25) || (mod52 == 51))
-				return IDLE;
-			else
-				return TSC;
-			break;
-		}
-		case ChannelCombination::LOOPBACK:
-			if ((burstFN % 51 <= 50) && (burstFN % 51 >= 48))
-				return IDLE;
-			else
-				return TSC;
-			break;
-		default:
-			return OFF;
-			break;
-		}
-	}
-
-	/* Initialize a multiframe slot in the filler table */
-	void init(size_t slot, signalVector *burst, bool fill);
-
-	ChannelCombination chanType[8];
-
-	/* The filler table */
-	signalVector *fillerTable[102][8];
-	int fillerModulus[8];
-
-	/* Received noise energy levels */
-	avgVector mFreqOffsets;
-
-	/* Transceiver mode */
-	trx_mode mode;
-};
\ No newline at end of file
diff --git a/trxcon/trx_if.c b/trxcon/trx_if.c
index ffad6c0..ba2ef53 100644
--- a/trxcon/trx_if.c
+++ b/trxcon/trx_if.c
@@ -602,32 +602,9 @@
 static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
 {
 	struct trx_instance *trx = ofd->data;
-	struct trx_meas_set meas;
 	uint8_t buf[TRXD_BUF_SIZE];
-	sbit_t bits[148];
-	int8_t rssi, tn;
-	int16_t toa256;
-	uint32_t fn;
 	ssize_t read_len;
 
-#ifdef IPCIF
-	struct trxd_from_trx* rcvd = trxif_from_trx_d();
-	if (!rcvd) {
-		LOGP(DTRX, LOGL_ERROR, "read() failed with rc=%zd\n", rcvd);
-		return rcvd;
-	}
-
-	tn = rcvd->ts;
-	fn = rcvd->fn;
-	rssi = -(int8_t) rcvd->rssi;
-	toa256 = (int16_t) rcvd->toa;
-
-	/* Copy and convert bits {254..0} to sbits {-127..127} */
-	//osmo_ubit2sbit(bits, rcvd->symbols, 148);
-	memcpy(bits, rcvd->symbols, 148);
-
-	free(rcvd);
-#else
 	read_len = read(ofd->fd, buf, sizeof(buf));
 	if (read_len <= 0) {
 		LOGP(DTRXD, LOGL_ERROR, "read() failed with rc=%zd\n", read_len);
@@ -641,7 +618,18 @@
 		     read_len);
 		return -EINVAL;
 	}
-#endif
+
+	return trx_data_rx_handler(trx, buf);
+}
+
+int trx_data_rx_handler(struct trx_instance *trx, uint8_t *buf)
+{
+	struct trx_meas_set meas;
+	sbit_t bits[148];
+	int8_t rssi, tn;
+	int16_t toa256;
+	uint32_t fn;
+
 	tn = buf[0];
 	fn = osmo_load32be(buf + 1);
 	rssi = -(int8_t)buf[5];
@@ -681,6 +669,8 @@
 	return 0;
 }
 
+extern void tx_external_transceiver(uint8_t *burst) __attribute__((weak));
+
 int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
 	uint8_t pwr, const ubit_t *bits)
 {
@@ -719,7 +709,10 @@
 	memcpy(buf + 6, bits, 148);
 
 	/* Send data to transceiver */
-	send(trx->trx_ofd_data.fd, buf, 154, 0);
+	if (tx_external_transceiver)
+		tx_external_transceiver(buf);
+	else
+		send(trx->trx_ofd_data.fd, buf, 154, 0);
 
 #endif
 	return 0;
diff --git a/trxcon/trx_if.h b/trxcon/trx_if.h
index abbde97..8cf95d8 100644
--- a/trxcon/trx_if.h
+++ b/trxcon/trx_if.h
@@ -84,3 +84,4 @@
 
 int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
 	uint8_t pwr, const ubit_t *bits);
+int trx_data_rx_handler(struct trx_instance *trx, uint8_t *buf);
\ No newline at end of file
diff --git a/trxcon/trxcon.c b/trxcon/trxcon.c
index 4e3ac27..67fb1d7 100644
--- a/trxcon/trxcon.c
+++ b/trxcon/trxcon.c
@@ -271,9 +271,8 @@
 	}
 }
 
-extern void init_external_transceiver(int argc, char **argv);
-extern void stop_trx();
-extern volatile bool gshutdown;
+extern void init_external_transceiver(struct trx_instance *trx, int argc, char **argv) __attribute__((weak));
+extern void close_external_transceiver(int argc, char **argv) __attribute__((weak));
 
 int main(int argc, char **argv)
 {
@@ -372,14 +371,14 @@
 	/* Initialize pseudo-random generator */
 	srand(time(NULL));
 
-	init_external_transceiver(argc, argv);
+	if (init_external_transceiver)
+		init_external_transceiver(app_data.trx, argc, argv);
+	else
+		while (!app_data.quit)
+			osmo_select_main(0);
 
-	// while (!app_data.quit)
-	// 	osmo_select_main(0);
-
-	gshutdown = true;
-	stop_trx();
-
+	if (close_external_transceiver)
+		close_external_transceiver(argc, argv);
 
 exit:
 	/* Close active connections */