diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am index c4434fe0..6b76d25b 100644 --- a/Transceiver52M/Makefile.am +++ b/Transceiver52M/Makefile.am @@ -191,7 +191,6 @@ noinst_HEADERS += \ 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 be1eec48..940b2981 100644 --- a/Transceiver52M/ms/ms_commandhandler.cpp +++ b/Transceiver52M/ms/ms_commandhandler.cpp @@ -20,10 +20,8 @@ */ #include -#include "l1if.h" #include "ms_rx_upper.h" #include "syncthing.h" -#include "ms_state.h" void upper_trx::driveControl() { @@ -199,8 +197,6 @@ void upper_trx::commandhandler(char *buffer, char *response) 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 @@ void upper_trx::commandhandler(char *buffer, char *response) } } 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 7f4d4af5..5d53221a 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 #include #include #include "grgsm_vitac/grgsm_vitac.h" -#include "ms_state.h" #include "ms_rx_upper.h" extern "C" { @@ -39,6 +37,15 @@ extern "C" { void __lsan_do_recoverable_leak_check(); } +namespace trxcon +{ +extern "C" { +#include +} +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 @@ void upper_trx::start_ms() 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 @@ SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingO 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(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 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 chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; std::complex chan_imp_resp2[CHAN_IMP_RESP_LENGTH * d_OSR]; @@ -227,14 +175,10 @@ SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingO 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 @@ void upper_trx::driveReceiveFIFO() 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 @@ void upper_trx::driveReceiveFIFO() 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 @@ void upper_trx::driveTx() 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 @@ int trxc_main(int argc, char *argv[]) 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 09154bf7..5e25a483 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 @@ class upper_trx : public ms_trx { 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 @@ class upper_trx : public ms_trx { 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 @@ class upper_trx : public ms_trx { { 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 c00d0727..00000000 --- a/Transceiver52M/ms/ms_state.h +++ /dev/null @@ -1,175 +0,0 @@ -#pragma once - -#include -#include - -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 ffad6c08..ba2ef53c 100644 --- a/trxcon/trx_if.c +++ b/trxcon/trx_if.c @@ -602,32 +602,9 @@ rsp_error: 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 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what) 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 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what) 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 @@ int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn, 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 abbde973..8cf95d8e 100644 --- a/trxcon/trx_if.h +++ b/trxcon/trx_if.h @@ -84,3 +84,4 @@ int trx_if_cmd_measure(struct trx_instance *trx, 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 4e3ac278..67fb1d7f 100644 --- a/trxcon/trxcon.c +++ b/trxcon/trxcon.c @@ -271,9 +271,8 @@ static void signal_handler(int signum) } } -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 @@ int main(int argc, char **argv) /* Initialize pseudo-random generator */ srand(time(NULL)); - init_external_transceiver(argc, argv); - - // while (!app_data.quit) - // osmo_select_main(0); - - gshutdown = true; - stop_trx(); + if (init_external_transceiver) + init_external_transceiver(app_data.trx, argc, argv); + else + while (!app_data.quit) + osmo_select_main(0); + if (close_external_transceiver) + close_external_transceiver(argc, argv); exit: /* Close active connections */