/**@file @brief Radio Resource messages, GSM 04.08 9.1. */ /* * OpenBTS provides an open source alternative to legacy telco protocols and * traditionally complex, proprietary hardware systems. * * Copyright 2008, 2009 Free Software Foundation, Inc. * Copyright 2010 Kestrel Signal Processing, Inc. * Copyright 2014 Range Networks, Inc. * * This software is distributed under the terms of the GNU Affero General * Public License version 3. See the COPYING and NOTICE files in the main * directory for licensing information. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. */ #include // for L3APDUData::text #include "GSML3RRElements.h" #include using namespace std; using namespace GSM; void L3CellOptionsBCCH::writeV(L3Frame& dest, size_t &wp) const { dest.writeField(wp,0,1); dest.writeField(wp,mPWRC,1); dest.writeField(wp,mDTX,2); dest.writeField(wp,mRADIO_LINK_TIMEOUT,4); } void L3CellOptionsBCCH::text(ostream& os) const { os << "PWRC=" << mPWRC; os << " DTX=" << mDTX; os << " RADIO_LINK_TIMEOUT=" << mRADIO_LINK_TIMEOUT; } void L3CellOptionsSACCH::writeV(L3Frame& dest, size_t &wp) const { dest.writeField(wp,(mDTX>>2)&0x01,1); dest.writeField(wp,mPWRC,1); dest.writeField(wp,mDTX&0x03,2); dest.writeField(wp,mRADIO_LINK_TIMEOUT,4); } void L3CellOptionsSACCH::text(ostream& os) const { os << "PWRC=" << mPWRC; os << " DTX=" << mDTX; os << " RADIO_LINK_TIMEOUT=" << mRADIO_LINK_TIMEOUT; } void L3CellSelectionParameters::writeV(L3Frame& dest, size_t &wp) const { dest.writeField(wp,mCELL_RESELECT_HYSTERESIS,3); dest.writeField(wp,mMS_TXPWR_MAX_CCH,5); dest.writeField(wp,mACS,1); dest.writeField(wp,mNECI,1); dest.writeField(wp,mRXLEV_ACCESS_MIN,6); } void L3CellSelectionParameters::text(ostream& os) const { os << "CELL-RESELECT-HYSTERESIS=" << mCELL_RESELECT_HYSTERESIS; os << " MS-TXPWR-MAX-CCH=" << mMS_TXPWR_MAX_CCH; os << " ACS=" << mACS; os << " NECI=" << mNECI; os << " RXLEV-ACCESS-MIN=" << mRXLEV_ACCESS_MIN; } void L3ControlChannelDescription::writeV(L3Frame& dest, size_t &wp) const { dest.writeField(wp,0,1); dest.writeField(wp,mATT,1); dest.writeField(wp,mBS_AG_BLKS_RES,3); dest.writeField(wp,mCCCH_CONF,3); dest.writeField(wp,0,5); dest.writeField(wp,mBS_PA_MFRMS,3); dest.writeField(wp,mT3212,8); } void L3ControlChannelDescription::text(ostream& os) const { os << "ATT=" << mATT; os << " BS_AG_BLKS_RES=" << mBS_AG_BLKS_RES; os << " CCCH_CONF=" << mCCCH_CONF; os << " BS_PA_MFRMS=" << mBS_PA_MFRMS; os << " T3212=" << mT3212; } bool L3FrequencyList::contains(unsigned wARFCN) const { for (unsigned i=0; imax) max=mARFCNs[i]; } return max - base(); } void L3FrequencyList::writeV(L3Frame& dest, size_t &wp) const { // If this were used as Frequency List, it had to be coded // as the variable bit map format, GSM 04.08 10.5.2.13.7. // But it is used as Cell Channel Description and is coded // as the variable bit map format, GSM 04.08 10.5.2.1b.7. // Difference is in abscence of Length field. // The header occupies first 7 most significant bits of // the first V-part octet and should be 1000111b=0x47 for // the variable length bitmap. dest.writeField(wp,0x47,7); // base ARFCN unsigned baseARFCN = base(); dest.writeField(wp,baseARFCN,10); // bit map unsigned delta = spread(); unsigned numBits = 8*lengthV() - 17; if (numBits output( os, "" ); //std::copy( mData.begin(), mData.end(), output ); for (size_t i = 0 ; i < mData.size() ; ++i) { os << (mData[i] ? "1" : "0"); } } void L3MeasurementResults::parseV(const L3Frame& frame, size_t &rp) { // GSM 04.08 10.5.2.20 mBA_USED = frame.readField(rp,1); mDTX_USED = frame.readField(rp,1); mRXLEV_FULL_SERVING_CELL = frame.readField(rp,6); rp++; // spare mMEAS_VALID = frame.readField(rp,1); mRXLEV_SUB_SERVING_CELL = frame.readField(rp,6); rp++; // spare mRXQUAL_FULL_SERVING_CELL = frame.readField(rp,3); mRXQUAL_SUB_SERVING_CELL = frame.readField(rp,3); mNO_NCELL = frame.readField(rp,3); for (unsigned i=0; i<6; i++) { mRXLEV_NCELL[i] = frame.readField(rp,6); mBCCH_FREQ_NCELL[i] = frame.readField(rp,5); mBSIC_NCELL[i] = frame.readField(rp,6); } } void L3MeasurementResults::text(ostream& os) const { // GSM 04.08 10.5.2.20 os << "BA_USED=" << mBA_USED; os << " DTX_USED=" << mDTX_USED; os << " MEAS_VALID=" << mMEAS_VALID; // Note that the value of the MEAS-VALID bit is reversed // from what you might expect. if (mMEAS_VALID) return; os << " RXLEV_FULL_SERVING_CELL=" << mRXLEV_FULL_SERVING_CELL; os << " RXLEV_SUB_SERVING_CELL=" << mRXLEV_SUB_SERVING_CELL; os << " RXQUAL_FULL_SERVING_CELL=" << mRXQUAL_FULL_SERVING_CELL; os << " RXQUAL_SUB_SERVING_CELL=" << mRXQUAL_SUB_SERVING_CELL; os << " NO_NCELL=" << mNO_NCELL; // no measurements? if (mNO_NCELL==0) return; // no neighbor list? if (mNO_NCELL==7) return; for (unsigned i=0; i