From fd99c6ce05e2b62dcba93201e2a2d1ac83b3673d Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Sat, 21 Dec 2019 00:40:09 +0100 Subject: radioInterfaceMulti: Fail to tune on freq not following multi-arfcn restrictions multi-arfcn feature uses a hardcoded disposition of logical channels on a physical channel. Logical channels in the phisical channel are separated by MCBTS_SPACING Hz, that is 4 GSM ARFCNs. As a result, multi-arfcn restricts the TRX ARFCN setup to the following: ARFCN(TRX0)=N, ARFCN(TRX1)=N+1*4, ARFCN(TRX2)=N+2*4, ... Let's make sure radioInterfaceMulti verifies the requested Rx/Tx frequencies for each logical channel over TRXC match the restriction explained above. It will check freq going to be set is indeed separated by MCBTS_SPACING from already set channels, making sure the ARFCN series is consistent. Otherwise, before this patch, one could set in osmo-bsc: ARFCN(TRX0)=N, ARFCN(TRX1)=N+2 and osmo-trx would silently ack the related Rx/TxTUNE TRXC commands, but actually still transmit on ARFCN N+4 instead. As a result, in this scenario TRX!=0 were unusable with multi-arfcn. Related: OS#4207 Change-Id: I2f3d66a611d3a489b3e4d9431994f4ec77b4460f --- Transceiver52M/radioInterface.h | 8 ++++ Transceiver52M/radioInterfaceMulti.cpp | 73 ++++++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h index d9fa414..c75a983 100644 --- a/Transceiver52M/radioInterface.h +++ b/Transceiver52M/radioInterface.h @@ -156,16 +156,24 @@ public: void close(); }; +struct freq_cfg_state { + bool set; + double freq_hz; +}; + class RadioInterfaceMulti : public RadioInterface { private: bool pushBuffer(); int pullBuffer(); + bool verify_arfcn_consistency(double freq, size_t chan, bool tx); virtual double setTxGain(double dB, size_t chan); signalVector *outerSendBuffer; signalVector *outerRecvBuffer; std::vector history; std::vector active; + std::vector rx_freq_state; + std::vector tx_freq_state; Resampler *dnsampler; Resampler *upsampler; diff --git a/Transceiver52M/radioInterfaceMulti.cpp b/Transceiver52M/radioInterfaceMulti.cpp index 668305c..a0c24b5 100644 --- a/Transceiver52M/radioInterfaceMulti.cpp +++ b/Transceiver52M/radioInterfaceMulti.cpp @@ -73,6 +73,8 @@ void RadioInterfaceMulti::close() powerScaling.resize(0); history.resize(0); active.resize(0); + rx_freq_state.resize(0); + tx_freq_state.resize(0); RadioInterface::close(); } @@ -148,6 +150,8 @@ bool RadioInterfaceMulti::init(int type) mReceiveFIFO.resize(mChans); powerScaling.resize(mChans); history.resize(mChans); + rx_freq_state.resize(mChans); + tx_freq_state.resize(mChans); active.resize(MCHANS, false); inchunk = RESAMP_INRATE * 4; @@ -362,42 +366,67 @@ static bool fltcmp(double a, double b) return fabs(a - b) < FREQ_DELTA_LIMIT ? true : false; } +bool RadioInterfaceMulti::verify_arfcn_consistency(double freq, size_t chan, bool tx) +{ + double freq_i; + std::string str_dir = tx ? "Tx" : "Rx"; + std::vector &v = tx ? tx_freq_state : rx_freq_state; + + for (size_t i = 0; i < mChans; i++) { + if (i == chan) + continue; + if (!v[i].set) + continue; + + freq_i = v[i].freq_hz + (double) ((int)chan - (int)i) * MCBTS_SPACING; + if (!fltcmp(freq, freq_i)) { + LOGCHAN(chan, DMAIN, ERROR) + << "Setting " << str_dir << " frequency " << freq + << " is incompatible: already configured channel " + << i << " uses frequency " << v[i].freq_hz + << " (expected " << freq_i << ")"; + return false; + } + } + v[chan].set = true; + v[chan].freq_hz = freq; + return true; +} + bool RadioInterfaceMulti::tuneTx(double freq, size_t chan) { - if (chan >= mChans) - return false; + double shift; - double shift = (double) getFreqShift(mChans); + if (chan >= mChans) + return false; - if (!chan) - return mDevice->setTxFreq(freq + shift * MCBTS_SPACING); + if (!verify_arfcn_consistency(freq, chan, true)) + return false; - double center = mDevice->getTxFreq(); - if (!fltcmp(freq, center + (double) (chan - shift) * MCBTS_SPACING)) { - LOG(NOTICE) << "Channel " << chan << " RF Tx frequency offset is " - << freq / 1e6 << " MHz"; - } + if (chan == 0) { + shift = (double) getFreqShift(mChans); + return mDevice->setTxFreq(freq + shift * MCBTS_SPACING); + } - return true; + return true; } bool RadioInterfaceMulti::tuneRx(double freq, size_t chan) { - if (chan >= mChans) - return false; + double shift; - double shift = (double) getFreqShift(mChans); + if (chan >= mChans) + return false; - if (!chan) - return mDevice->setRxFreq(freq + shift * MCBTS_SPACING); + if (!verify_arfcn_consistency(freq, chan, false)) + return false; - double center = mDevice->getRxFreq(); - if (!fltcmp(freq, center + (double) (chan - shift) * MCBTS_SPACING)) { - LOG(NOTICE) << "Channel " << chan << " RF Rx frequency offset is " - << freq / 1e6 << " MHz"; - } + if (chan == 0) { + shift = (double) getFreqShift(mChans); + return mDevice->setRxFreq(freq + shift * MCBTS_SPACING); + } - return true; + return true; } double RadioInterfaceMulti::setRxGain(double db, size_t chan) -- cgit v1.2.3