/* * OpenBTS provides an open source alternative to legacy telco protocols and * traditionally complex, proprietary hardware systems. * * 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. */ #ifndef URRCTRCH_H #define URRCTRCH_H 1 #include "UMTSCommon.h" #include "Logger.h" #include "ScalarTypes.h" #include "URRCDefs.h" #include #include "asn_system.h" // Dont let other includes land in namespace ASN. namespace ASN { #include "TransportFormatSet.h" #include "TFCS.h" #include "RB-MappingInfo.h" }; namespace UMTS { class TrChInfo; class RACHFEC; class FACHFEC; class DCHFEC; // 3GPP 25.331 RRC protocol spec. Messages and IEs below are transmitted to the UE using ANS. // sec 10.2.40: Message RRC Connection Setup. // sec 10.2.33: Message Radio Bearer Setup // sec 10.3.4.24 Signalling RB Info to setup. // (pat) RB (Radio Bearer) setup. The programming options for the RB is huge, with tons of stuff // we will never use, and additional complication is inserted into the specs to more closely match // the constraints imposed by using ANS. // To attack this, I am pulling out those parts of RB setup that we will use into C++ classes. // Our job is to program our own RLC+MAC+L1+PHY with these directly, and the UE with // matching (though not identical, because uplink and downlink are assymetric) parameters using ANS. // We will probably not create generic "write" routines to convert these classes // into ANS structures to send to the UE for two reasons: // 1. We will use pre-defined UE setups (sec 13.7) as much as possible, and we dont // need to transmit those, we only need to program our own RRC to match. // 2. The ANS complexity is high, we only program a tiny subset of it, // and we will only make a couple of Radio Bearer setups (maybe only 1), ever. // It will be easier to custom program the ANS for the few that we use, using // the info in these C++ classes. // RB Information Elements // TrCH Information Elements // UL Transport Channel Info common for all Transport Channels 10.3.5.24 // Added or Reconfigured UL TrCH info 10.3.5.2 // DL Transport Channel Info common for all Transport Channels 10.3.5.6 // Added or Reconfigured DL TrCH info 10.3.5.1 // PhyCH Info Elements // ... // typedef unsigned RBIdentity; // 1..32. 1-4 reserved for SRB1 - SRB4. struct TrChList; struct RrcTfsRlcSize { //unsigned mValue; Used to do it this way. static void toAsnBitMode(ASN::BitModeRLC_SizeInfo*result,unsigned rlcsize); // Used for dedciated ch (DCH) static void toAsnOctetMode1(ASN::OctetModeRLC_SizeInfoType1 *result,unsigned rlcsize); static void toAsnOctetMode2(ASN::OctetModeRLC_SizeInfoType2*result,unsigned rlcsize); // Used for common ch (RACH/FACH) }; struct RrcTfsNumberOfTransportBlocks { //unsigned mValue; // 0 .. 51 static ASN::NumberOfTransportBlocks *toAsn(unsigned numtb); }; struct RrcSemiStaticTFInfo : public virtual RrcDefs // 10.3.5.11 { // Note: The ASN encodes the static TTI in the tti CHOICE in the enclosing // CommonTransChTfs or DedicatedTransChTfs. Note that it is still a single tti choice, // it is just a non-obvious place to put it. unsigned mTTI; // 10, 20, 40, 80, or "dynamic" which we dont use CodingType mTypeOfChannelCoding; CodingRate mCodingRate; unsigned mRateMatchingAttribute; unsigned mCRCSize; void toAsnSSTF(ASN::SemistaticTF_Information *result); void text(std::ostream &os) { os < mMaxTbSize) mMaxTbSize = tmp; } } return mMaxTbSize; } unsigned getMaxTfSize() { // Return max number of bytes in any single TF. if (mMaxTfSize == 0) { for (unsigned i = 0; i < mDynamic.mNumTF; i++) { unsigned tmp = getTfTotalSize(i); if (tmp > mMaxTfSize) mMaxTfSize = tmp; //LOG(NOTICE) << format("getMaxTfSize i=%d tmp=%d max=%d",i,tmp,(int)mMaxTfSize); } } return mMaxTfSize; }; // Configuration Functions: RrcTfs *setSemiStatic(unsigned tti,CodingType ct, CodingRate cr, unsigned rm, unsigned crcSize) { mSemiStaticTFInfo.mTTI = tti; mSemiStaticTFInfo.mTypeOfChannelCoding = ct; mSemiStaticTFInfo.mCodingRate = cr; mSemiStaticTFInfo.mRateMatchingAttribute = rm; mSemiStaticTFInfo.mCRCSize = crcSize; return this; } // Note: We specify the Transport Block Size, not 'rlc-size' used in the TFS IE. // If you transcribe these from an RRC spec, you may have to adjust the size. RrcTfs *addTF(unsigned tbsize, unsigned numBlocks) { mDynamic.addTF(tbsize,numBlocks); return this; } void toAsnTfs(ASN::TransportFormatSet *result, bool isDownlink = false); unsigned getNumTF() { return mDynamic.mNumTF; } void text(std::ostream &os) { os <getNumTB(mTfi); } unsigned getTBSize() { // in bits if (mTfs == 0) { return 0; } return mTfs->getTBSize(mTfi); } unsigned getTfTotalSize() { return getTBSize() * getNumTB(); } RrcSemiStaticTFInfo *getSemiStaticInfo() { if (mTfs == 0) { return 0; } return mTfs->getSemiStatic(); } // Cheap iterator for TF in TFS. Does not iterate TF in TFCS: // Return the first TF. #if CURRENTLYUNUSED void firstTf(RrcTfs *tfs) { mTfs = tfs; mTfi = 0; } bool valid() { return mTfs && mTfi < mTfs->getNumTf(); } // Advance to the next TF in the TFS. void nextTf() { mTfi++; // May be rendered invalid; caller must check. } #endif }; struct PowerOffset { // 10.3.5.8 Bool_z mPresent; // Has this been specified? unsigned char mGainFactorBetaC; PowerOffset() { mPresent = false; } PowerOffset(unsigned char val) { mPresent = true; mGainFactorBetaC = val; } }; // One Transport Format Combination, saves info for one CTFC. class RrcTfc : public virtual RrcDefs { // Each TrCh [Transport Channel] has a TFS [Transport Format Set] which specifies // the legal TF [Transport Formats] allowed for that TrCh. // The physical channel encodes CCTrCh consisting of 1 or more TrCh. // The TFC specifies the complete set of TB [Tranport Block] that can be transmitted // for all TrCh simultaneously for the PHY by picking one TF from each TrCh. // The spec compresses this info into the CTFC, but we also keep a handle // to the TF specified for each TrCh, which is not part of the IE. TrChList *mTrChList; // Who owns us, same pointer duplicated in all TFC in this TFCS. // Note that it will be either a downlink or uplink one. // It is inited not by constructor, but when the RrcTf are. RrcTf mTfList[maxTrCh]; public: unsigned mCTFC; // This is what goes out over the PHY in the special spot in the RadioSlot. PowerOffset mPowerOffset; unsigned mTfcsIndex; // The index of this TFC in the TFCS. // A way to get back to the TrChInfo if you have a handle to the TFC, but // not to the TrChConfig or MasterChConfig in which it resides. TrChInfo *getTrChInfo(TrChId tcid); unsigned getTfcSize(); RrcTf *getTf(TrChId trchid); unsigned getTfcsIndex() { return mTfcsIndex; } unsigned getTfIndex(TrChId trchid) { return getTf(trchid)->mTfi; } void setTfc(TrChList *chlist, TfIndex tfa, TfIndex tfb=0, TfIndex tfc=0, TfIndex tfd=0); unsigned getSize(); unsigned getNumTrCh() const; }; // 10.3.5.15 TFCS Reconfiguration/Addition Information. // TFC set is a list where each element selects one of the pre-defined TF for each TrCh. // Therefore the TFCS is a matrix whose width is the // number of TrCh and whose length is the max number of TFC. // They compress the rows into a single number called CTFC as per 14.10. // Here is an example, L and P defined in 14.10: // L, P indexed by TrCh numbered 1..i, Transport Formats numbered 0..L(i)-1 // TrCh0: has tf0, tf1, tf2. L(1)=3; P(1)=1; // TrCh1: has tf0, tf1. L(2)=2; P(2)=3; // TrCh2: has tf0, tf1. L(3)=2; P(3)=6; // Each row here is a TFC, selecting one tf for each TrCh. // CTFC(tf0,tf0,tf0) = 0*1 + 0*3 + 0*6 = 0; // CTFC(tf2,tf0,tf0) = 2*1 + 0*3* + 0*6 = 2; // CTFC(tf1,tf1,tf1) = 1*1 + 1*3 + 1*6 = 10; struct RrcTfcs : public virtual RrcDefs // 10.3.5.15 Transport Format Combination Set { unsigned mCtfcSize; // number of bits, chosen from: 2,4,6,8,12,16. unsigned mNumTfc; RrcTfc mTfcList[maxTfc]; RrcTfcs() : mCtfcSize(0), mNumTfc(0) { for (unsigned i = 0; i < maxTfc; i++) { mTfcList[i].mTfcsIndex = i; } } //void setCTFCSize(unsigned val) { mCtfcSize = val; } // Add a new TFC and set to the specified TF Indicies for up to four TrChs. RrcTfcs *addTFC2(TrChList *chlist, TfIndex tfa, TfIndex tfb=0, TfIndex tfc=0, TfIndex tfd=0); // Set the PowerOffset for the most recently defined CTFC void setPower(PowerOffset po) { mTfcList[mNumTfc-1].mPowerOffset = po; } // If the spec gives a ctfc, make sure we calculate it properly: // Check the most recent CTFC to see if it matches ctfc. void checkCTFC(unsigned ctfc) { assert(mTfcList[mNumTfc-1].mCTFC == ctfc); } //void toAsnTfcs(ASN::TFCS *result, bool powerInfo = true); void toAsnTfcs(ASN::TFCS *result, TrChType tctype); RrcTfc *getTfc(unsigned tfci) { return &mTfcList[tfci]; } //unused: bool isTrivialTfcs(); unsigned getNumTfc() { return mNumTfc; } RrcTfc *iterBegin() { return &mTfcList[0]; } RrcTfc *iterEnd() { return &mTfcList[mNumTfc]; } /*** class iter { unsigned pos; iter(unsigned wpos) : pos(wpos) {} bool end() { return pos == mNumTfc; } iter operator++() { pos++; return *this; } }; ***/ }; // 10.3.5.13 TFCS Explicit Configuration. // also 10.3.5.20 - TFCS, which consists entirely of one TFCS struct. // All this contains is a TFCS to be reconfigured, added, removed or replaced //struct TfcsExplicitConfiguration { // 10.3.5.13, Explicit TFCS configuration //TFCS ...; //}; struct TfcSubset { // todo? }; // Container for DlTrChInfo or UlTrChInfo struct TrChInfo : public virtual RrcDefs { TrChType mTransportChType; UInt_z mTransportChannelIdentity; // We use TrCh id 1..4, so 0 means uninitialized. // Normally the RBMappingInfo specifies the mapping of rb->trch. // We do that statically, so the RBMappingInfo appears in two places: // The RBInfo specifies the trch and the TrChInfo (here) specifies // the multiplexing option, and if not multiplexed, the single rbid // to be sent on that channel. // The multiplexing is true if multiple logical channels (RBs) are mapped onto // this TrCh, and is used to specify if the MAC uses the CT field for logical channel mapping. // Multiplexing is almost always true. // The major exception is voice channels where the AMR codec data channels // are on rbid 1,2,3 mapped to non-multiplexed trch 1,2,3, and // everything else (SRB1,2,3) are mapped to multiplexed trch 4 // It would also be possible to use multiple trch for PS channels, // but we are not doing that in the initial implementation. // Normally, the RBMappingInfo also specifies the rbid to logical channel mapping, // (where the logical channel is what is sent in the TransportBlock to // indicate the rbid for multiplexed TrCh) but we just use 1-to-1 for that, // so the logical channel mapping appears nowhere in this code base. // Technically, the RBMappingInfo could reference the same TFS for different // underlying channel types (DCH, FACH) in which case the mMacMultiplexed flag could change, // but we would use a different TFS for each PhCh in that case. bool mTcIsMultiplexed; // If not multiplexed, this is the rbid. // 0 means undefined, as SRB0 is never one of the options here. RbId mTcRbId; void setTrCh(TrChType type, unsigned trchid1based, bool mMultiplexed, RbId rbid=0) { assert(mMultiplexed || rbid); mTransportChType = type; mTransportChannelIdentity = trchid1based; mTcIsMultiplexed = mMultiplexed; mTcRbId = rbid; } virtual RrcTfs *getTfs() = 0; //virtual TrChInfo *bler_QualityValue(double val); // Only in dl. //virtual RrcTfs *setSemiStatic(unsigned tti,CodingType ct, CodingRate cr, unsigned rm, unsigned crcSize); }; // 10.3.5.24: UL TrCh info common for all DCH transport channels. // By which they mean all the transport channels in this DCH. // (Because the TFCS selects a set of TFS for all TrCh simultaneously.) // I also use this structure for the PRACH TFC subset. // Note there is a PRACH Tfcs "omitted in this version of spec" // Rather the PRACH informaion is in SIB5 or SIB6 struct UlTrChInfoCommon { // CHOICE mode = FDD: struct RrcTfcs mTfcs; TfcSubset mTfcSubset; // MD - Mandatory with default value. (gotta love that) In different location for REL-4 or REL-10 struct RrcTfcs *getTfcs() { return &mTfcs; } }; struct DlTrChInfoCommon // 10.3.5.6: DL TrCh common for all TrCh { // SCCPCH TFCS - omitted in this version (v4-v10) of the spec. // CHOICE mode = FDD: //union DlParameters_t { This is a union, but C++ does not allow it, so oh well... enum ChoiceDlParameters { eExplicit, eSameAsUL } mChoiceDlParameters; struct Explicit { RrcTfcs mTfcs; } mExplicit; //} DlParameters; struct RrcTfcs *getTfcs() { return &mExplicit.mTfcs; } }; struct UlTrChInfo : TrChInfo // 10.3.5.2: Added or Reconfigured UL TrCh information { RrcTfs mTfs; RrcTfs *getTfs() { return &mTfs; } UlTrChInfo() : mTfs(this) { } }; class UlTrChList; struct DlTrChInfo : TrChInfo // 10.3.5.1: Added or Reconfigured DL TrCh information { //union { // C++ cant initialize unions. enum ChoiceDlParameters { eExplicit, eSameAsUL } mChoiceDlParameters; //struct { RrcTfs mTfs; // This is used for Explicit TFS. //} mExplicit; struct { // NOT IMPLEMENTED!!!! // And not going to be; this just saves room in the setup message, and who cares. TrChType mChType; unsigned mChId; } mSameAsUL; //} DlParameters; double mDCHQualityTarget; // Only in the DL TrChInfo // TODO: If it is not explicit, we would fish TFS out of the UL info. RrcTfs *getTfs() { return &mTfs; } DlTrChInfo *bler_QualityValue(double val); DlTrChInfo *copyUplink(UlTrChList *ul, unsigned trch1based); DlTrChInfo() : mTfs(this) {} }; #if URRC_IMPLEMENTATION DlTrChInfo *DlTrChInfo::bler_QualityValue(double val) { mDCHQualityTarget = val; return this; } #endif // Container for "TrCh Information Elements" part of 10.2.50: Transport Channel Reconfiguration. // or 10.2.33: Radio Bearer Setup. // It contains a list of transport channels. // Each channel has a RrcTfs; the TFCS applies to the entire list. struct TrChList : public virtual RrcDefs, public Text2Str { //virtual unsigned getNumTF(unsigned TrChNum0) =0; virtual RrcTfcs *getTfcs() =0; virtual RrcTfs *getTfs(TrChId tcid) =0; // If macMultiplexed is false, rbid must be specified, and not otherwise. virtual TrChInfo *defineTrCh(TrChType type, unsigned id, bool macMultiplexed, RbId rbid=0) =0; virtual unsigned getNumTrCh() const = 0; virtual TrChInfo *getTrChInfo(TrChId tcid) =0; void text(std::ostream &os) const { for (TrChId i = 0; i < getNumTrCh(); i++) { os << "TrCh "<(this)->getTfs(i)->text(os); // unconst foo bar. os << "\n"; } } // Return the maximum size in bits of any transport format on any single TrCh. // Note that the entire Transport Format Combination could be bigger. unsigned getMaxAnyTfSize() { unsigned maxtfsize = 0; for (TrChId tcid = 0; tcid < getNumTrCh(); tcid++) { unsigned tfsize = getTfs(tcid)->getMaxTfSize(); if (tfsize > maxtfsize) {maxtfsize = tfsize;} //LOG(NOTICE)<<"getMaxAnyTfSize"<addTFC2(this,tfa,tfb,tfc,tfd); return this; } TrChList *setCTFCSize(unsigned size) { getTfcs()->mCtfcSize = size; return this; } TrChList *checkCTFC(unsigned ctfc) { getTfcs()->checkCTFC(ctfc); return this; } TrChList *setPower(PowerOffset po) { getTfcs()->setPower(po); return this; } unsigned iterTrChBegin() { return 0; } unsigned iterTrChEnd() { return getNumTrCh(); } // Derived accessors: unsigned getTTINumFrames(TrChId tcid) { return getTfs(tcid)->getTTINumFrames(); } TTICodes getTTICode(TrChId tcid) { return getTfs(tcid)->getTTICode(); } unsigned getRM(TrChId tcid) { return getTfs(tcid)->getRM(); } //unsigned getTFCSize(TrChId tcid, TfcId j) { return getTfcs()->? } }; // ASC Access Service Class - included in RACH. // One ASC is assigned by RRC for initial channel assignment. // Related IEs: // 10.3.6.1 AC-to-ASC mapping // used in 10.3.6.55 PRACH system information list, // but default is PRACH System Information List in SIB5 // David set tfci to false in SIB5, implying no transport format set for RACH/FACH. // So where does the pdu size come from, then? // Note on FACH: it is carried on SCCPCH channel, whose Tfs and Tfcs may be set up via: // 10.3.6.70 SCCPCH Info for FACH // 10.3.6.72 Secondary CCPCH system information // 10.3.6.13 CPCH set info - may be broadcast in SIB or assigned by SRNC, but it is pseudo-static in a cell., // used in 10.2.8 Cell Update Confirm, 10.2.16a: Handover // 10.2.22 Physical Channel Reconfiguration, 10.2.27 Radio Bearer Reconfig // 10.2.40 RRC Connection Setup, 10.2.50 Transport Channel Reconfig // 10.2.48.8.11: SIB 8. // Also see 10.3.6.88: Uplink DPCH info 10.3.6.30: Downlink PDSCH info // The below does not correspond to a specific IE. // It represents the uplink TrCh Information Elements part // of 10.2.50: Transport Channel Reconfiguration. // or 10.2.33: Radio Bearer Setup. // or 10.2.40: RRC Connection Setup, which includes: // 10.3.4.24 Signalling RB info to setup. // 10.3.4.23 RLC Info // 10.3.4.0a Default config for CELL_FACH (rel-8) // If present use default config 0. // 10.3.5.24 UL TrChInfo common for all transport channels. // PRACH TFCS "should not be included in this version of spec" // TFC subset // DCH TFCS // 10.3.5.2 Added UL TrCh info (for DCH only, but mandatory - must be empty) // 10.3.4.6 DL TrChInfo common for all transport channels. // SCCPCH TFCS "should not be included in this version of spec" // DCH TFCS. // 10.3.5.1 Added DL TrCh info (for DCH only) // Default or preconfiguration options (rel-5) // 10.3.6.36 Freq Info // ARFCN // // NOTE: If SIB6 is present then: // SIB6 specifies PRACH and SCCPCH for UE in connected mode. // SIB5 specifies PRACH and SCCPCH for UE in idle mode. // Above discussed in 8.5.17 and 8.5.19. // SIB5 includes: // 10.3.6.72 Secondary CCPCH system information // includes FACH TFS and FACH TFCS. // 10.3.6.55 PRACH system information list // includes RACH TFS, RACH TFCS, // Additional RACH TFS for CCCH (rel-6). // Additional RACH TFCS for CCCH (rel-6) - includes only // PowerOffsetInformation 10.3.5.8. // // For DCH, they put the TFCS and TFC subset in: // UlTrChInfoCommon: "UL Tranport Channel Information for all Transport Channels", // which is used, for example, by 10.2.50: Transport Channel Reconfiguration. // For RACH/PRACH (or FACH/SCCPCH) the physical channels do not support // multiple transport channels, so the TFCS is in the main structure, // for example: 10.3.6.55: PRACH System Information list. // The MAC-d can route logical channels to the MAC-s/sh/m to be sent on RACH/FACH, but I suspect // that we are really only expected to use this facility for SRBs, not data RBs. Not sure. // Anyway, all the TrCh multiplexing stuff applies ONLY to DCH. // Note that 8.6.5: Transport Channel Information Setup starts out saying if the Tfcs is // received for a RACH channel in SIB5 or SIB6, but those are in IEs only applicable to TDD, // for example, there is a Tfcs buried in TDD only 10.3.6.46: PDSCH system info. struct UlTrChList : public TrChList, public UlTrChInfoCommon { UInt_z mNumTrCh; UlTrChInfo mChInfo[maxTrCh]; // Only 1 for RACH/PRACH // TODO CPCH set id ? OP optional // TODO: Added or Reconfigured TrCh information for DRAC list. OP optional // The TrChId is 0 based. RrcTfs *getTfs(TrChId tcid) { assert(tcid < getNumTrCh()); return mChInfo[tcid].getTfs(); } RrcTfcs *getTfcs() { return UlTrChInfoCommon::getTfcs(); } unsigned getNumTrCh() const { return mNumTrCh; } UlTrChInfo *getTrChInfo(TrChId tcid) { return &mChInfo[tcid]; } // This is the TrCh config function, which uses TrCh id numbered starting with 1. // The arrays where we save TrCh stuff are 0 based. // The complicated RBMappingInfo never changes for us, so we save // it in the TrChInfo and RBInfo, which must also be configured to refer // back to this TrCh. // The multiplexed variable is whether the MAC is going to multiplex multiple logical channels // on this TrCh. This is not in the TFS in the spec - normally you would have to // figure it out after applying the RBMappingInfo, but we dont do that, we // specify it statically when the TrChInfo is set up. // More comments at mRlcSize in DynamicTFInfo. // If macMultiplexed is false, rbid must be specified, and not otherwise. // The rbid is 1 for SRB1, etc, so 5 is the first available user rbid. UlTrChInfo *defineTrCh(TrChType type, unsigned trchid1based, bool macMultiplexed, RbId rbid=0) { UlTrChInfo *result = &mChInfo[trchid1based-1]; if (result->mTransportChannelIdentity) { assert(0); } // Already defined. result->setTrCh(type,trchid1based,macMultiplexed,rbid); if (trchid1based > mNumTrCh) { mNumTrCh = trchid1based; } return result; } }; // This does not correspond to a specific IE. // It represents the downlink TrCh Information Elements part of 10.2.50: Transport Channel Reconfiguration. struct DlTrChList : public TrChList, public DlTrChInfoCommon { UInt_z mNumTrCh; DlTrChInfo mChInfo[maxTrCh]; // Only one for FACH/SCCPCH RrcTfs *getTfs(TrChId tcid) { assert(tcid < getNumTrCh()); return mChInfo[tcid].getTfs(); } RrcTfcs *getTfcs() { return DlTrChInfoCommon::getTfcs(); } unsigned getNumTrCh() const { return mNumTrCh; } DlTrChInfo *getTrChInfo(TrChId tcid) { return &mChInfo[tcid]; } // See comments for identical function in UlTrChList. DlTrChInfo *defineTrCh(TrChType type, unsigned trchid1based, bool macMultiplexed,RbId rbid=0) { DlTrChInfo *result = &mChInfo[trchid1based-1]; if (result->mTransportChannelIdentity) { assert(0); } // Already defined. result->setTrCh(type,trchid1based,macMultiplexed,rbid); if (trchid1based > mNumTrCh) { mNumTrCh = trchid1based; } return result; } }; // This defines the set TrCh for one physical channel, either RACH, FACH, UL-DCH or DL-DCH. // It provides the info for the "TrCh Information Elements" part of // 10.2.50: Transport Channel Reconfiguration. // TODO: Simplify the ChList by getting rid of the Common struct. struct TrChConfig : public virtual RrcDefs { //todo? TfcSubset // How many transport formats defined for TrCh, numbered starting at 0. //unsigned getNumTF(unsigned TrChNum0) { return mChInfo[TrChNum0].getNumTF(); } UlTrChList mUlTrChs; DlTrChList mDlTrChs; // The following parameters are needed by MAC. // In a normal UMTS system they would be derived from the // RBMappingInfo as per 25.331 8.5.21, but we may just set them. // We are not using RLC subset. UlTrChList *ul() { return &mUlTrChs; } DlTrChList *dl() { return &mDlTrChs; } // It will be FACH or DCH. All the TrCh are the same type, so just return the first one. // unused... //TrChType getDlTrChType() { // return dl()->getTrChInfo(0)->mTransportChType; //} // Just dump TrCh 0. void tcdump() { TrChId chid = 0; std::cout << format("UL:%p tfcs=%p mNumTfc=%d numTF=%d\n",ul(),ul()->getTfcs(), ul()->getTfcs()->getNumTfc(),ul()->getTfs(chid)->getNumTf()); std::cout << format("DL:%p tfcs=%p mNumTfc=%d numTF=%d\n",dl(),dl()->getTfcs(), dl()->getTfcs()->getNumTfc(),dl()->getTfs(chid)->getNumTf()); } // TODO: this goes where now? // bool mSameAsUplink; // Only in downlink, means just use the uplink. // These are generic TrCh configuration. void configRachTrCh(int ulSF,TTICodes ulTTICode, int ulPB, int TBSize); void configFachTrCh(int ulSF,TTICodes ulTTICode, int ulPB, int TBSize); bool configDchPS(DCHFEC *dch, TTICodes tticode, unsigned pb, bool useTurbo, unsigned ulTBSize, unsigned dlTBSize); // From 25.331 13.7: Parameter values for default radio configurations. void defaultConfig3TrCh(); // Default config number 3, used for voice. //void defaultConfig1TrCh(); // Default config number 1 for low-rate signalling. }; // And I quote: "RB Mapping Info: A multiplexing option for each possible transport channel // this RB can be multiplexed on." // Pats opinion is that the primary purpose of this is to allow the DCCH and DTCH to be // sent over either FACH or DCH, so if the UE changes state to CELL_FACH // you can still send it messages. // It seems like quite alot of work to avoid just sending a new configuration when that happens. // This is not really in either layer 1 and layer 2, but defines a logical // mapping to hook them together. // It specifies the TrCh and mac logical channel to use for the RB. // We only use a small subset of this, and here it is: // From 25.331 6.3 and I quote: "Additionally, RBs whose identities shall be set // between 5 and 32 may be used as signalling radio bearer for the // RRC messages on the DCCH sent in RLC transparent mode (RLC-TM)." // Lets just leave the SRB mapping options out for now. // There can be two mappings: one for RACH or FACH and one for DCH. // For RACH/FACH you need: // LogicalChId, TFS index to use, mac priority. // For DCH you need: // TrCh id, logicalChId if multiplexed, mac priority. // optional list of TFSs // So we could specify this in the TrCh setup, by specifying the logical channels // that are allowed to use each TF in addTF(). #if USE_RBMAPPINGINFO // RBMappingInfo - see RBInfo and defaultRBMappingInfoToAsn // We can derive it all of the mapping info from the TrCh, the RbId, and these variables: // o mTcIsMultiplexed in the TrCh. // o mTrChAssigned in the RBInfo. // Which implies that we have to download new RBInfos when we change // the UE state from CELL_FACH to CELL_DCH or vice versa. And so what. // TODO: Are multiple mapping options necessary? // Which I think is the same question as: Does the phone change state without our orders? // I guess it would if it gets lost, but that should be ok because // it can just rach in again and reestablish channels from scratch. // But if it becomes necessary to support two RBMappingInfo options, all we have // to do is add two mTrChAssigned to RBInfo - one for RACH/FACH and one for DCH. // We dont need this messy confusing RBMappingInfo structure. struct RBMappingInfo : public virtual RrcDefs // 10.3.4.21 { // "ALL" means the entire TFS, "Configured" means the RLC sizes // configured for this logical channel in the TFS. // For RACH, it must be explicit, and the mRlcSizeIndex below // is the 1-based index of the TF in the TFS for the RACH TrCh. // Very easy to goof up the configuration here. enum ChoiceRlcSizeList { eAll, eConfigured, eExplicitList }; unsigned mNumberOfUplinkRlcLogicalChannels; // 1..2 This is unused historic nonsense. struct ulRBMappingInfo_s { // TODO // RLC logical channel mapping indicator is always TRUE, so not included here. TrChType mUplinkTransportChType; int mUlTransportChannelIdentity; // 1..31, sec 10.3.5.18 One-based, not Zero-based!! // logical channel 1..15. Used to distinguish logical chans by MAC on TrCh. // It is optional because if there is no logical channel mapping by MAC it is unneeded. int mUlLogicalChannelIdentity; enum ChoiceRlcSizeList mChoiceRlcSizeList; //union { struct ExplicitList_t { // This is always just one integer, so dont bother making it an array. //unsigned mRlcSizeIndex[maxTFS]; // If choice == ExplicitList. unsigned mRlcSizeIndex; // If choice == ExplicitList. Which it wont. } ExplicitList; //} RlcSizeList; // E-DCH stuff skipped. unsigned mMacLogicalChannelPriority; // 1..8 ulRBMappingInfo_s() : mUplinkTransportChType(TrChInvalid), // Must specify this mUlTransportChannelIdentity(1), // Default is almost always used mUlLogicalChannelIdentity(-1), // Must specify this. mChoiceRlcSizeList(eAll), // Default is ok. mMacLogicalChannelPriority(1) // Default is ok. {} } ul[maxRBMuxOptions]; unsigned mNumberOfDownlinkRlcLogicalChannels; // 1..2 This is unused nonsense. struct dlRBMappingInfo_s { TrChType mDownlinkTransportChType; unsigned mDlDchTransportChannelIdentity; // 1..31 int mDlLogicalChannelIdentity; // 1..15. Optional. Used to distinguish logical chans by MAC on transport chan dlRBMappingInfo_s() : mDownlinkTransportChType(TrChInvalid), // Must specify this. mDlDchTransportChannelIdentity(1), // Default is almost always used mDlLogicalChannelIdentity(-1) // Must specify this {} } dl[maxRBMuxOptions]; RBMappingInfo() : mNumberOfUplinkRlcLogicalChannels(1), mNumberOfDownlinkRlcLogicalChannels(1) {} // Write this IE out to an RRC Message: void toAsnRB_MappingOption(ASN::RB_MappingOption *thing); // Default Config setup methods: //bool parse_ul; void UL_LogicalChannelMappings(unsigned val) { mNumberOfUplinkRlcLogicalChannels = val; } // I'm not sure I have this option mapped properly, but it doesnt // matter because it is always just 1: void MappingOption(unsigned val) { mNumberOfDownlinkRlcLogicalChannels = val; } void ul_TransportChannelType(TrChType type) { /*parse_ul=true;*/ ul->mUplinkTransportChType = type; } void ul_transportChannelIdentity(unsigned id) {ul->mUlTransportChannelIdentity = id;} void dl_transportChannelIdentity(unsigned id) {dl->mDlDchTransportChannelIdentity = id;} void ul_logicalChannelIdentity(unsigned id) {ul->mUlLogicalChannelIdentity = id;} void dl_logicalChannelIdentity(unsigned id) {dl->mDlLogicalChannelIdentity = id;} //void transportChannelIdentity(unsigned id) { // if (parse_ul) mUlTransportChannelIdentity = id; // else mDlDchTransportChannelIdentity = id; //} //void logicalChannelIdentity(unsigned id) { // if (parse_ul) mUlLogicalChannelIdentity = id; // else mDlLogicalChannelIdentity = id; //} // rlc_SizeList(configured); void mac_LogicalChannelPriority(unsigned val) { ul->mMacLogicalChannelPriority = val; } void dl_TransportChannelType(TrChType type) { dl->mDownlinkTransportChType = type; } void rlc_SizeList(ChoiceRlcSizeList choice) { ul->mChoiceRlcSizeList = choice; } void rlc_SizeIndex(int val) { assert(ul->mChoiceRlcSizeList == eExplicitList); ul->ExplicitList.mRlcSizeIndex = val; } }; #endif // 10.3.4.22: RB with PDCP info, used in ActiveSetUpdate, ActiveSetUpdateComplete, // CellUpdateConfirm, PhysicalChannelReconfiguration, PhysicalChannelReconfigurationComplete, // RadioBearerSetup, RadioBearerSetupComplete, RadioBearerReconfigurationComplete, RadioBearerRelease, // TransportChannelReconfiguration, TransportChannelReconfigurationComplete, URAUpdateConfirm // todo? I dont think we will ever need this for anything because it has to do with SRRC handoff. void defaultRbMappingInfoToAsn(TrChInfo *tcul,TrChInfo *tcdl,RbId rbid,ASN::RB_MappingInfo_t *asnmsg); int quantizeRlcSize(bool common, int tbsize); }; // namespace UMTS #endif