This is for extracting a subset of TCI states defined in PDSCH-Config and activating / deactivating specific TCI States. The list (a subset) of TCI states to activate/deactivate is configured by the bitmap as shown below. If a bit in a specific location is set to be '1', it means that it activate the TCI state mapped to the position of the bit. If the bit is set to be '0', it means that it deactivates the TCI state mapped to the position of the bit.
The MAC CE exists to bridge a gap between two layers. RRC can configure as many as 128 TCI states in PDSCH-Config, which is far more than a scheduling grant could carry. The TCI field in DCI format 1_1 is three bits wide, so it can name only eight of them. This MAC CE is what chooses which eight.
It is a downlink MAC CE, sent by the gNB, and TS 38.321 identifies it with LCID 53. Its sibling for the control channel is the TCI State Indication for UE-specific PDCCH, at LCID 52. How does this MAC CE differ from the PDCCH one sets the two side by side.
- Structure of the MAC CE
- What does the first octet do, and how long is the MAC CE ?
- When does the DCI actually carry a TCI field ?
- What happens when the scheduling offset is too short ?
- How does this MAC CE differ from the PDCCH one ?
- Examples
- Reference
Structure of the MAC CE
The MAC CE is one octet of addressing followed by a bitmap. This section follows the bitmap, which is where the activation happens. What the first octet holds, and how far the bitmap runs, is covered in What does the first octet do.
< 38.321-Figure 6.1.3.14-1 > shows the layout. Octet 1 holds the addressing fields. Every octet after it carries eight bitmap bits, one per TCI state identity, counting upward from T0. The figure ends on a general octet rather than a fixed last one, because the bitmap stops once the configured identities run out.
For example, if T4 = 1, it activate the index 4 of tci-StatesToAddModList configured in PDSCH-Config.
< 38.321-Figure 6.1.3.14-1: TCI States Activation/Deactivation for UE-specific PDSCH MAC CE >

The list of bit position that are set to be '1' is assigned to a small table called codepoint and the max size of the codepoint is 8. It mean that only up to 8 bit fields in this MAC CE can be set to be '1'. The position of '1' bits are assigned to codepoint in increasing order.
For example, let's assume that following fields are set to be '1' and all other bits are set to be '0'.
T4 = 1
T10 = 1
T11 = 1
T19 = 1
T25 = 1
T40 = 1
T45 = 1
T50 = 1
Then the codepoint is set to be as follows.
codepoint 0 = 4
codepoint 1 = 10
codepoint 2 = 11
codepoint 3 = 19
codepoint 4 = 25
codepoint 5 = 40
codepoint 6 = 45
codepoint 7 = 50
The TCI(Transmission Configuration Index) in DCI 1_1 indicates this codepoint index. See here for further details.
One bit per TCI state identity : Ti set to 1 activates the state with identity i. Set to 0 it deactivates it.Activation is not selection : The bitmap says which states are available. Something else picks among them.Codepoints run in increasing order : The lowest activated identity becomes codepoint 0, the next becomes codepoint 1, and so on.At most eight can be activated : The DCI field that reads the codepoints is three bits wide.The bitmap is absolute, the codepoints are relative : Ti always means identity i. Codepoint n means whatever is nth in the current set.
What does the first octet do, and how long is the MAC CE ?
The description above concentrates on the bitmap, which is where the interesting work happens. Octet 1 carries no bitmap bits at all. It is worth a moment, because it decides where the activation lands.
Three fields share that octet. R is a reserved bit, set to 0. Serving Cell ID is five bits, so it addresses any of the 32 serving cells. BWP ID is two bits, naming one of the four bandwidth parts on that cell.
The BWP field is the one worth noticing. TCI states are configured inside PDSCH-Config, and PDSCH-Config belongs to a bandwidth part. An activation is therefore scoped to one bandwidth part of one serving cell. Switching bandwidth part brings the activation set of the new one into play.
The length is the other thing octet 1 does not tell you. Unlike the PDCCH indication, which is always two octets, this MAC CE is variable in size. Its bitmap runs over as many octets as the configured TCI state identities need. A UE with states only in the low numbers therefore receives a shorter MAC CE.
Being variable in size has a consequence one layer down. A variable-size MAC CE needs a length field. Its subheader is two or three octets, rather than the single octet a fixed-size one uses.
Figure 1. The bitmap gets all the attention. Octet 1 is what decides which cell and which bandwidth part the activation lands on.
Octet 1 scopes the activation : A five-bit Serving Cell ID and a two-bit BWP ID, plus one reserved bit.The activation belongs to a bandwidth part : TCI states live in PDSCH-Config, and PDSCH-Config belongs to a BWP.The MAC CE is variable in size : The bitmap runs only as far as the configured TCI state identities require.Variable size means a longer subheader : Two or three octets, because a length field is needed.T0 is the rightmost bit of its octet : Reading an octet left to right gives the states in descending order.
When does the DCI actually carry a TCI field ?
The description above ends by saying that the TCI field in DCI 1_1 indexes the codepoint. That is true when the field is present, and it is not always present. I spent a while assuming it always was.
Whether it appears is an RRC decision, taken per CORESET. ControlResourceSet carries tci-PresentInDCI. The field appears in DCI 1_1 only where that is enabled for the CORESET carrying the scheduling DCI.
When it is not configured, the UE does something quite different. It assumes the PDSCH uses the same TCI state as the CORESET that carried the scheduling PDCCH. In other words the PDSCH follows the beam that the PDCCH indication MAC CE set. The activated states on this page play no part.
Because the setting is per CORESET, two CORESETs on the same serving cell can behave differently. A PDSCH scheduled from one may follow a codepoint. One scheduled from the other may follow the CORESET beam.
Figure 2 puts that decision beside the other case where the activated set is bypassed, which the next section covers.
Figure 2. Activating eight states achieves nothing unless the scheduling CORESET has tci-PresentInDCI enabled. That single RRC field decides whether the codepoints are ever consulted.
The TCI field is not always present : It appears in DCI 1_1 only where tci-PresentInDCI is enabled for the scheduling CORESET.Without it the PDSCH follows the CORESET : The beam comes from the PDCCH indication, and the codepoints are never consulted.The setting is per CORESET : Two CORESETs on one cell can resolve the PDSCH beam by different routes.Activation alone changes nothing : Eight activated states have no effect until something selects among them.
What happens when the scheduling offset is too short ?
There is a second case where the activated set is bypassed, and it depends on timing rather than configuration.
Applying an indicated TCI state takes the UE some time. It has to read the DCI, resolve the codepoint, and steer its receive beam before the PDSCH arrives. The specification captures the time it needs in a UE capability called timeDurationForQCL, reported in symbols.
The offset between the scheduling DCI and its PDSCH may be smaller than that value. The UE then cannot honour the indication in time. It falls back to a default. TS 38.214 defines that default. It is the QCL of the CORESET with the lowest ControlResourceSetId monitored in the latest slot.
The practical shape of this is worth remembering. A gNB scheduling aggressively, with the PDSCH close behind the DCI, gets the default beam whatever the DCI asked for. Getting the indicated beam means leaving enough offset for the UE to act on it.
The threshold is a UE capability : timeDurationForQCL is reported in symbols, so its duration follows the subcarrier spacing.A short offset means the default beam : The UE cannot steer in time, so the indication is ignored.The default is the lowest CORESET ID : Its QCL, taken from the monitored CORESETs in the latest slot.Aggressive scheduling costs beam control : A PDSCH placed close behind its DCI will not use the indicated state.
How does this MAC CE differ from the PDCCH one ?
The two are often described together, and the differences are easier to hold as a table than as prose.
|
PDSCH, this page |
PDCCH, the sibling MAC CE |
|
|---|---|---|
|
|
53 |
52 |
|
|
Variable, so the subheader carries a length |
Fixed at 2 octets, so the subheader does not |
|
|
A bitmap, one bit per TCI state identity |
One 7-bit TCI State ID |
|
|
Up to 8, mapped to codepoints |
Exactly 1 |
|
|
A 3-bit TCI field in DCI 1_1, where present |
Nothing. The MAC CE is the final word |
|
|
One bandwidth part of one serving cell |
One CORESET of one serving cell |
|
|
Activation and Deactivation |
Indication |
Every row follows from one thing. PDSCH has a per-transmission selector and PDCCH does not, for the reason set out on the sibling page. A selector is what makes a set worth activating. It is also what makes a bitmap and a variable size worth paying for.
The bitmap exists because a selector exists : Activating a set is only useful when something can choose within it.Scope differs as well as size : This one covers a bandwidth part. The PDCCH one covers a single CORESET.The names are accurate : Activation and Deactivation for a set, Indication for a single choice.
Examples
Four cases cover the ordinary uses. Each one gives the RRC that has to exist, the fields the MAC CE carries, and what the UE ends with.
Each example gives two tables. The first says what the MAC CE means. The second shows how those values are packed, one bit per column, with bit 7 leftmost and bit 0 rightmost.
Example 1 : activating a set of four states
RRC has configured a list of TCI states in the PDSCH-Config of bandwidth part 1. None of them is active yet, so no codepoint exists.
PDSCH-Config ::= SEQUENCE {
tci-StatesToAddModList {
{ tci-StateId 2, qcl-Type1 { ssb : 0, typeC }, qcl-Type2 { ssb : 0, typeD } },
{ tci-StateId 5, qcl-Type1 { ssb : 1, typeC }, qcl-Type2 { ssb : 1, typeD } },
{ tci-StateId 9, qcl-Type1 { ssb : 2, typeC }, qcl-Type2 { ssb : 2, typeD } },
{ tci-StateId 14, qcl-Type1 { ssb : 3, typeC }, qcl-Type2 { ssb : 3, typeD } },
...
},
...
}
The gNB activates all four on serving cell 0, bandwidth part 1.
|
Serving Cell ID |
BWP ID |
Bitmap bits set to 1 |
Resulting codepoints |
|---|---|---|---|
|
0 |
1 |
T2, T5, T9, T14 |
0 to 3 map to TCI states 2, 5, 9 and 14 |
Reading the bits out gives the octets that actually travel. The MAC CE is 3 octets long, and it goes on the wire as 0x01 0x24 0x42.
|
Octet |
bit 7 |
bit 6 |
bit 5 |
bit 4 |
bit 3 |
bit 2 |
bit 1 |
bit 0 |
Hex |
|---|---|---|---|---|---|---|---|---|---|
|
Octet 1 |
R |
Serving Cell ID |
BWP ID |
0x01 |
|||||
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
||
|
Octet 2 |
T7 |
T6 |
T5 |
T4 |
T3 |
T2 |
T1 |
T0 |
0x24 |
|
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
||
|
Octet 3 |
T15 |
T14 |
T13 |
T12 |
T11 |
T10 |
T9 |
T8 |
0x42 |
|
0 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
||
Three octets are enough here. The highest activated identity is 14, so the bitmap needs two octets and stops there. A DCI carrying TCI field 2 now selects TCI state 9.
Example 2 : deactivating one state and activating another
The UE has moved. TCI state 2 is no longer useful and TCI state 20 has become the better choice. No RRC signalling is needed, because state 20 was already configured.
|
Serving Cell ID |
BWP ID |
Bitmap bits set to 1 |
Resulting codepoints |
|---|---|---|---|
|
0 |
1 |
T5, T9, T14, T20 |
0 to 3 map to TCI states 5, 9, 14 and 20 |
Reading the bits out gives the octets that actually travel. The MAC CE is 4 octets long, and it goes on the wire as 0x01 0x20 0x42 0x10.
|
Octet |
bit 7 |
bit 6 |
bit 5 |
bit 4 |
bit 3 |
bit 2 |
bit 1 |
bit 0 |
Hex |
|---|---|---|---|---|---|---|---|---|---|
|
Octet 1 |
R |
Serving Cell ID |
BWP ID |
0x01 |
|||||
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
||
|
Octet 2 |
T7 |
T6 |
T5 |
T4 |
T3 |
T2 |
T1 |
T0 |
0x20 |
|
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
||
|
Octet 3 |
T15 |
T14 |
T13 |
T12 |
T11 |
T10 |
T9 |
T8 |
0x42 |
|
0 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
||
|
Octet 4 |
T23 |
T22 |
T21 |
T20 |
T19 |
T18 |
T17 |
T16 |
0x10 |
|
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
||
The MAC CE has grown to four octets, because identity 20 needs a third bitmap octet. That much is expected. The part that catches people is what happened to the codepoints.
Codepoint 0 named TCI state 2 before this MAC CE, and it names TCI state 5 afterwards. Every codepoint above the removed identity has shifted down one place. A DCI that carries TCI field 0 in both cases selects a different beam in each, without any change to the DCI itself.
Figure 3. Deactivating a low identity renumbers every codepoint above it. This is the reason a beam can change without any DCI changing.
Example 3 : the same MAC CE where the DCI has no TCI field
The activation above only matters if something reads the codepoints. Whether anything does is decided per CORESET, by RRC.
ControlResourceSet ::= SEQUENCE {
controlResourceSetId 1,
duration 2,
tci-StatesPDCCH-ToAddList { 5, 9 },
-- tci-PresentInDCI is absent
...
}
The MAC CE from Example 2 is still valid, and the four codepoints still exist. They are simply never consulted. A PDSCH scheduled from CORESET 1 takes the TCI state that CORESET is using, which the PDCCH indication MAC CE set.
This is worth checking first when an activation appears to have no effect. The MAC CE can be entirely correct and still change nothing.
Example 4 : a single state on another serving cell
A secondary cell needs only one beam, and its states live in the PDSCH-Config of bandwidth part 0.
|
Serving Cell ID |
BWP ID |
Bitmap bits set to 1 |
Resulting codepoints |
|---|---|---|---|
|
3 |
0 |
T0 |
Only codepoint 0 exists, naming TCI state 0 |
Reading the bits out gives the octets that actually travel. The MAC CE is 2 octets long, and it goes on the wire as 0x0C 0x01.
|
Octet |
bit 7 |
bit 6 |
bit 5 |
bit 4 |
bit 3 |
bit 2 |
bit 1 |
bit 0 |
Hex |
|---|---|---|---|---|---|---|---|---|---|
|
Octet 1 |
R |
Serving Cell ID |
BWP ID |
0x0C |
|||||
|
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
||
|
Octet 2 |
T7 |
T6 |
T5 |
T4 |
T3 |
T2 |
T1 |
T0 |
0x01 |
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
||
Two octets is the shortest this MAC CE gets. The bitmap needs one octet because the highest activated identity is 0, and octet 1 is always present.
The DCI TCI field is still three bits wide here, because its width does not depend on how many states are active. Only codepoint 0 is meaningful, and the UE does not expect a DCI to name any other.
The MAC CE length follows the highest identity : Activating T14 needs two bitmap octets, and activating T20 needs three.Deactivating renumbers the codepoints above : The same DCI value can select a different beam after an activation change.Activation without a selector changes nothing : Where tci-PresentInDCI is absent, the codepoints exist and are never read.The DCI field is always three bits : Its width does not shrink when fewer than eight states are active.Each cell and bandwidth part is activated separately : Octet 1 scopes the MAC CE, so a second cell needs its own.
Reference
[1] 3GPP TS 38.321 - NR; Medium Access Control (MAC) protocol specification. Section 6.1.3.14 defines this MAC CE, and section 6.1.3.15 defines the PDCCH one.
[2] 3GPP TS 38.321 - Table 6.2.1-1 gives the DL-SCH LCID values, where this MAC CE is 53 and the PDCCH one is 52.
[3] 3GPP TS 38.331 - NR; Radio Resource Control (RRC) protocol specification. tci-PresentInDCI sits in ControlResourceSet, and the TCI states sit in PDSCH-Config.
[4] 3GPP TS 38.214 - NR; Physical layer procedures for data. Section 5.1.5 covers the TCI field, timeDurationForQCL and the default QCL assumption.
[5] TCI State Indication for UE-specific PDCCH - the sibling MAC CE, on this site.