// Common attributes (macros) used in this document
:bit-zero: '0\'B
:bit-one: '1\'B

[[trx_if]]
== TRX Manager UDP socket interface

This is the protocol used between `osmo-trx` (the transceiver) and
`osmo-bts-trx` (the BTS or core).

Each TRX Manager UDP socket interface represents a single transceiver (ARFCN).
Each of these channels is a pair of UDP sockets, one for control (`TRXC`) and
one for data (`TRXD`). Additionally, there's a separate global socket managing
the Master Clock Interface, shared among all channels.

Given a base port `B` (5700), and a set of channels `0..N`, the ports related to
a channel `0 <= X <= N` are:

* The Master clock interface is located on port `P=B`.
* The `TRXC` interface for channel `X` is located on port `P=B+2X+1`
* The `TRXD` interface for channel `X` is located on port `P=B+2X+2`.

The corresponding interface for every socket is at `P+100` on the BTS side.

NOTE: Starting from TRXDv2, it's possible to use only one socket for all
channels.  In this case, the global `TRXD` interface for all channels shall
be established on port `P=B+1`.  See <<trx_if_pdu_batching>> for more details.

[[trx_if_clock_ind]]
=== Indications on the Master Clock Interface

The master clock interface is output only (uplink, from the radio to the BTS).
Messages are "indications".

CLOCK gives the current value of the transceiver clock to be used by the BTS.
This message is usually sent around once per second (217 GSM frames), but can be
sent at any time. The clock value is NOT the current transceiver time. It is a
time setting that the BTS should use to give better packet arrival times. The
initial clock value is taken randomly, and then increased over time as the
transceiver submits downlink packets to the radio.
----
IND CLOCK <totalFrames>
----

[[trx_if_control]]
=== TRXC protocol

The per-ARFCN control interface uses a command-response protocol. Each command
has a corresponding response. Commands are sent in downlink direction (BTS ->
TRX), and responses are sent in uplink direction (TRX -> BTS). Commands and
responses are NULL-terminated ASCII strings.

Every command is structured this way:
----
CMD <cmdtype> [params]
----
The `<cmdtype>` is the actual command.
Parameters are optional depending on the commands type.

Every response is of the form:
----
RSP <cmdtype> <status> [result]
----
The `<status>` is 0 for success and a non-zero error code for failure.
Successful responses may include results, depending on the command type.

==== Power Control

`POWEROFF` shuts off transmitter power and stops the demodulator.
----
CMD POWEROFF
RSP POWEROFF <status>
----

`POWERON` starts the transmitter and starts the demodulator. Initial power level
is by default very low, unless set explicitly by `SETPOWER`/`ADJPOWER`
beforehand while in `POWEROFF` state. This command fails if the transmitter and
receiver are not yet tuned. This command fails if the transmit or receive
frequency creates a conflict with another ARFCN that is already running. If the
transceiver is already on, it answers successfully to this command.
----
CMD POWERON
RSP POWERON <status>
----

`NOMTXPOWER` is used by the BTS to retrieve the nominal output transmit power of
the transceiver. `SETPOWER/ADJPOWER` attenuations (dB) are expected to be
applied based on this value (dBm).
----
CMD NOMTXPOWER
RSP NOMTXPOWER <status> <dBm>
----

`SETPOWER` sets transmit power attenuation wrt the nominal transmit power of
the transceiver, in dB.
----
CMD SETPOWER <dB>
RSP SETPOWER <status> <dB>
----

`ADJPOWER` adjusts by the given dB the transmit power attenuation of the
transceiver.  Response returns resulting transmit power attenuation wrt the
nominal transmit power of the transceiver.
----
CMD ADJPOWER <dBStep>
RSP ADJPOWER <status> <dBLevel>
----

`RFMUTE` locks the RF transceiver, hence disabling emission and reception of
information on Air interface of the channel associated to the TRXC connection
the command is sent on. Parameter with value of `1` is used to mute, and value
of `0` is used to unmute.
----
CMD RFMUTE <1|0>
RSP RFMUTE <status> <1|0>
----

==== Tuning Control

`RXTUNE` tunes the receiver to a given frequency in kHz. This command fails if the
receiver is already running. (To re-tune you stop the radio, re-tune, and
restart.) This command fails if the transmit or receive frequency creates a
conflict with another ARFCN that is already running.
----
CMD RXTUNE <kHz>
RSP RXTUNE <status> <kHz>
----

`TXTUNE` tunes the transmitter to a given frequency in kHz. This command fails if
the transmitter is already running. (To re-tune you stop the radio, re-tune, and
restart.) This command fails if the transmit or receive frequency creates a
conflict with another ARFCN that is already running.
----
CMD TXTUNE <kHz>
RSP TXTUNE <status> <kHz>
----

==== Training Sequence configuration

The usual way to configure all timeslots at once involves sending of the `SETTSC`
command with a desired Training Sequence Code `<tsc>`:
----
CMD SETTSC <tsc>
CMD SETTSC <status> <tsc>
----

This command instructs the transceiver to use the given Training Sequence Code
from the TSC set 1 (see 3GPP TS 45.002, table 5.2.3a) for Normal Burst detection
on the receive path.  It does not affect the transmit path because bursts coming
from the BTS do contain the Training Sequence bits.

==== Timeslot Control

`SETSLOT` sets the format of a given uplink timeslot in the ARFCN.
The `<timeslot>` indicates the timeslot of interest.
The `<chantype>` indicates the type of channel that occupies the timeslot.
A chantype of zero indicates the timeslot is off.
----
CMD SETSLOT <timeslot> <chantype>
RSP SETSLOT <status> <timeslot> <chantype>
----

Here's the list of channel combinations and related values (`<chantype>`):

.List of channel combinations and related values (`<chantype>`)
[options="header"]
|===
| value | Channel Combination
|0| Channel is transmitted, but unused
|1| TCH/FS
|2| TCH/HS, idle every other slot
|3| TCH/HS
|4| Downlink: FCCH + SCH + CCCH + BCCH, Uplink: RACH
|5| Downlink: FCCH + SCH + CCCH + BCCH + SDCCH/4 + SACCH/4, Uplink: RACH+SDCCH/4
|6| Downlink: CCCH+BCCH, Uplink: RACH
|7| SDCCH/8 + SACCH/8
|8| TCH/F + FACCH/F + SACCH/M
|9| TCH/F + SACCH/M
|10| TCH/FD + SACCH/MD
|11| PBCCH+PCCCH+PDTCH+PACCH+PTCCH
|12| PCCCH+PDTCH+PACCH+PTCCH
|13| PDTCH+PACCH+PTCCH
|===

===== Multiple Training Sequences (optional)

For some setups it's insufficient to have a single Training Sequence Code assigned
to all timeslots of a transceiver.  It may be required to use different TSCs for
some (or even all) timeslots.  This can be achieved by sending `SETSLOT` command
with additional arguments:
----
CMD SETSLOT <timeslot> <chantype> [ C<c>/S<s> ]
RSP SETSLOT <status> <timeslot> <chantype> [ C<c>/S<s> ]
----

where `<c>` is a Training Sequence Code from TSC set `<s>`.

NOTE: The numbering of both Training Sequence Code and set shall be the same as in
3GPP TS 45.002, e.g. `C0S1` corresponds to the first sequence in the first TSC set
for a chosen modulation type.  TSC Set number 0 (`S0`) does not exist in the specs.

.Example: configuring timeslot 4 to use TCH/F and TSC 7 from set 1
----
CMD SETSLOT 4 1 C7/S1
RSP SETSLOT 0 4 1 C7/S1
----

Unless explicitly configured as described above, all timeslots will be using the
default Training Sequence Code and set configured with the `SETTSC` command.

===== VAMOS enabled channel combinations (optional)

The BTS may at any time re-configure channel combination of a timeslot (primarily
during channel activation) to activate or deactivate VAMOS mode in the transceiver.
For this purpose, the following additional channel combinations shall be used:

.List of VAMOS enabled channel combinations and related values
[options="header"]
|===
| value | Channel Combination
|VFF| V0(TCH/F) & V1(TCH/F), 2 channels total
|VHH| V0(TCH/H0) & V1(TCH/H0) + V0(TCH/H1) & V1(TCH/H1), 4 channels total
|VFH| V0(TCH/F) & V1(TCH/H0) + V0(TCH/F) & V1(TCH/H1), 3 channels total
|HVHH| TCH/H0 + V0(TCH/H1) & V1(TCH/H1), 3 channels total (mixed)
|===

where both `V0` and `V1` define a _VAMOS pair_.  Symbols `&` and `+` indicate
simultaneous and sequential transmission in the TDMA domain respectively.
Therefore a combination `V0(a) & V1(b)` indicates that both channels `a`
and `b` are simultaneously active during a timeslot period.

.Example: `VFF` in time domain (2 channels)
----
 MS1: | V0(TCH/F) | V0(TCH/F) | V0(TCH/F) | V0(TCH/F) | ...
 -----+-----------+-----------+-----------+-----------+------------> TDMA frames
 MS2: | V1(TCH/F) | V1(TCH/F) | V1(TCH/F) | V1(TCH/F) | ...
----

.Example: `VHH` in time domain (4 channels)
----
 MS1: | V0(TCH/H0) |            | V0(TCH/H0) |            | ...
 MS2: |            | V0(TCH/H1) |            | V0(TCH/H1) | ...
 -----+------------+------------+------------+------------+--------> TDMA frames
 MS3: | V1(TCH/H0) |            | V1(TCH/H0) |            | ...
 MS4: |            | V1(TCH/H1) |            | V1(TCH/H1) | ...
----

.Example: `VFH` in time domain (3 channels)
----
 MS1: |  V0(TCH/F) |  V0(TCH/F) |  V0(TCH/F) |  V0(TCH/F) | ...
 -----+------------+------------+------------+------------+--------> TDMA frames
 MS2: | V1(TCH/H0) |            | V1(TCH/H0) |            | ...
 MS3: |            | V1(TCH/H1) |            | V1(TCH/H1) | ...
----

.Example: `HVHH` in time domain (3 channels)
----
 MS1: |    TCH/H0  |            |    TCH/H0  |            | ...
 MS2: |            | V0(TCH/H1) |            | V0(TCH/H1) | ...
 -----+------------+------------+------------+------------+--------> TDMA frames
 MS3: |            | V1(TCH/H1) |            | V1(TCH/H1) | ...
----

NOTE: Combination `HVHH` is special, because it allows the network to multiplex
a legacy user device (`MS1`) with a pair of VAMOS capable devices (`MS2` and `MS3`)
on the same timeslot, so the former (`MS1`) is neither required to support the new
orthogonal TSC sets nor conform to DARP phase I or II (SAIC support).

For all VAMOS enabled channel combinations, it's *required* to specify Training
Sequence Code and the TSC set values for all multiplexed subscribers.  See 3GPP
TS 45.002, table 5.2.3e for more details on TSC set selection.

.Example: configuring a timeslot to use `VFF` combination
----
CMD SETSLOT <timeslot> VFF C0/S1 <1> C0/S2 <2>
RSP SETSLOT <status> <timeslot> VFF C0/S1 C0/S2
----
<1> V0(TCH/F) is configured to use TSC 0 from set 1 (table 5.2.3a).
<2> V1(TCH/F) is configured to use TSC 0 from set 2 (table 5.2.3b).

.Example: configuring a timeslot to use `VFF` combination (legacy MS)
----
CMD SETSLOT <timeslot> VFF C7/S1 <1> C4/S1 <2>
RSP SETSLOT <status> <timeslot> VFF C7/S1 C4/S1
----
<1> V0(TCH/F) is configured to use TSC 7 from set 1 (table 5.2.3a).
<2> V1(TCH/F) is configured to use TSC 4 from set 1 (table 5.2.3a).

NOTE: Using Training Sequences from the same set for a _VAMOS pair_ (in this example,
`C7/S1 C4/S1`) is not recommended because of their bad cross-correlation properties.
The only exception is when two legacy non-VAMOS capable phones are paired together
and neither of them does support additional TSC sets.

.Example: configuring a timeslot to use `VHH` combination
----
CMD SETSLOT <timeslot> VHH C1/S3 <1> C1/S4 <2>
RSP SETSLOT <status> <timeslot> VHH C1/S3 C1/S4
----
<1> V0(TCH/H0) and V0(TCH/H1) are configured to use TSC 1 from set 3 (table 5.2.3c).
<2> V1(TCH/H0) and V1(TCH/H1) are configured to use TSC 1 from set 4 (table 5.2.3d).

.Example: configuring a timeslot to use `VFH` combination
----
CMD SETSLOT <timeslot> VFH C2/S1 <1> C2/S4 <2>
RSP SETSLOT <status> <timeslot> VFH C2/S1 C2/S4
----
<1> V0(TCH/F) is configured to use TSC 2 from set 1 (table 5.2.3a).
<2> V1(TCH/H0) and V1(TCH/H1) are configured to use TSC 2 from set 4 (table 5.2.3d).

.Example: configuring a timeslot to use `HVHH` combination
----
CMD SETSLOT <timeslot> HVHH C0/S1 <1> C0/S1 <2> C0/S2 <3>
RSP SETSLOT <status> <timeslot> HVHH C0/S1 C0/S1 C0/S2
----
<1> Legacy TCH/H0 is configured to use TSC 0 from set 1 (table 5.2.3a).
<2> V0(TCH/H1) is configured to use TSC 0 from set 1 (table 5.2.3a).
<3> V1(TCH/H1) is configured to use TSC 0 from set 2 (table 5.2.3b).

NOTE: In the example for `HVHH`, legacy TCH/H0 does not belong to a _VAMOS pair_,
so it can be configured to use any Training Sequence Code without restrictions.

[[trx_if_pdu_version_nego]]
==== TRXD header version negotiation

Messages on DATA interface may have different formats, defined by a version number,
which can be negotiated on the control interface.  By default, the Transceiver will
use the legacy header version (0).  See <<trx_if_pdu_versioning>>.

The format negotiation can be initiated by the BTS using `SETFORMAT` command.
If the requested version is not supported by the transceiver, status code of
the response message should indicate a preferred (basically, the latest)
version. The format of this message is the following:
----
CMD SETFORMAT <ver_req>
RSP SETFORMAT <ver_resp> <ver_req>
----

where:

* `<ver_req>` is the requested version (suggested by the BTS),
* `<ver_rsp>` is either the applied version if matches `<ver_req>`, or a
  preferred version if `<ver_req>` is not supported.

If the transceiver indicates `<ver_rsp>` different than `<ver_req>`, the BTS is
supposed to re-initiate the version negotiation using the suggested `<ver_rsp>`.
For example:

----
  BTS -> TRX: CMD SETFORMAT 2
  BTS <- TRX: RSP SETFORMAT 1 2

  BTS -> TRX: CMD SETFORMAT 1
  BTS <- TRX: RSP SETFORMAT 1 1
----

If no suitable `<ver_rsp>` is found, or the `<ver_req>` is incorrect, the status
code in the response shall be `-1`.

As soon as `<ver_rsp>` matches `<ver_req>` in the response, the process of
negotiation is complete. Changing the header version is supposed to be done
before `POWERON`, but can be also done afterwards.

=== TRXD protocol

Messages on the data interface carry one or optionally multiple radio bursts
(see <<trx_if_pdu_batching>>) per one UDP datagram.  Two kinds of TRXD PDU exist:

* `TRX -> L1` (from transceiver to the L1): Uplink messages received from the MS,
* `L1 -> TRX` (from the L1 to transceiver): Downlink messages sent to the MS.

Depending on the origin and the version indicator, PDUs may have different structure.

[[trx_if_pdu_versioning]]
==== PDU versioning

The format of a PDU, i.e. presence and ordering of certain fields, is determined by
the version number indicated in the first octet.  This is usually referred as
`TRXDvN`, where `N` is the version number (e.g. TRXDv0 or TRXDv1).  A version number
indicates the message format to be used for both directions: `TRX -> L1` and
`L1 -> TRX`.  The same version shall be used for all messages in both directions,
mixing in any way is not permitted.

The version negotiation is optionally initiated by the `L1` on the control interface,
and expected to be performed before starting the transceiver (i.e. sending `POWERON`
command).  See <<trx_if_pdu_version_nego>>.

The current header allows to distinguish up to 16 different versions.
The following versions are defined so far:

* TRXDv0 - initial version of TRXD protocol, inherited as-is from OpenBTS project.
* TRXDv1 (proposed in July 2019):
** Introduced the concept of protocol versioning;
** Introduced NOPE / IDLE indications;
** New field: MTS (Modulation and Training Sequence);
** New field: C/I (Carrier-to-interface) ratio;
** Downlink messages mostly unchanged.
* TRXDv2 (proposed in January 2021):
** Introduced the concept of burst batching (many bursts in one message);
** Changed the field ordering (facilitating aligned access);
** New field: batching indicator;
** New field: shadow indicator;
** New field: TRX number;
** New field: SCPIR for VAMOS.

==== Uplink PDU format

An Uplink TRXD PDU contains a demodulated burst with the associated measurements
(signal strength, timing delay, etc.) and TDMA frame/timeslot number.  Starting
from TRXDv1, a PDU may contain no payload, indicating the upper layers that the
transceiver was not able to demodulate a burst (e.g. due to bad signal quality
or the lack of signal during IDLE TDMA frames).

.TRXDv0 Uplink data burst message structure
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-3:	VER(0)
	4:	RFU
	5-7:	TN
	8-39:	FN
	40-47:	RSSI
	48-63:	TOA256
	64-95:	Soft-bits
	96-111:	PAD
}
----

.TRXDv1 Uplink data burst message structure
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-3:	VER(1)
	4:	RFU
	5-7:	TN
	8-39:	FN
	40-47:	RSSI
	48-63:	TOA256
	64-71:	MTS
	72-87:	C/I
	88-127:	Soft-bits
}
----

.TRXDv1 NOPE / IDLE indication message structure
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-3:	VER(1)
	4:	RFU
	5-7:	TN
	8-39:	FN
	40-47:	RSSI
	48-63:	TOA256
	64-71:	MTS (NOPE.ind)
	72-87:	C/I
}
----

.TRXDv2 Uplink message structure
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-3:	VER(2)
	4:	RFU
	5-7:	TN
	8:	BATCH
	9:	RFU
	10-15:	TRXN
	16-23:	MTS
	24-31:	RSSI
	32-47:	TOA256
	48-63:	C/I
	64-95:	FN
	96-127:	Soft-bits
}
----

.TRXDv2 Uplink message structure (batched part)
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-4:	RFU
	5-7:	TN
	8:	BATCH
	9:	SHADOW
	10-15:	TRXN
	16-23:	MTS
	24-31:	RSSI
	32-47:	TOA256
	48-63:	C/I
	64-95:	Soft-bits
}
----

VER: 4 bits::
TRXD header version, common for both `TRX -> L1` and `L1 -> TRX` directions.

TN: 3 bits::
Timeslot number.

RFU: variable bit-length::
Reserved for Future Use.  The sending side of the PDU shall set all bits to
{bit-zero};  the receiving side shall ignore `RFU` fields.

BATCH: 1 bit::
This bit indicates whether a batched PDU follows (see <<trx_if_pdu_batching>>).

SHADOW: 1 bit::
This bit indicates whether this is a _shadow PDU_ (see <<trx_if_pdu_vamos>>).

TRXN: 6 bits::
The transceiver (PHY channel) number this PDU is coming from.

FN: 32 bits (4 bytes)::
GSM frame number, big endian.

RSSI: 8 bits (1 byte)::
Received Signal Strength Indication in -dBm, encoded without the negative sign.

TOA256: 16 bits (2 bytes)::
Timing of Arrival in units of 1/256 of symbol, big endian.

MTS: 8 bits (1 byte)::
Contains the Modulation and Training Sequence information. See <<coding-mts>>
for more information on the encoding.

C/I: 16 bits (2 bytes)::
Contains the Carrier-to-Interference ratio in centiBels, big endian. The C/I
value is computed from the training sequence of each burst, where the "ideal"
training sequence is compared to the actual training sequence and the result
expressed in centiBels.

Soft-bits: 148 x N bytes (variable length, N defined by modulation type)::
Contains the uplink burst. Unlike the downlink bursts, the uplink bursts are
designated using the soft-bits notation, so the receiver can indicate its
assurance from 0 to -127 that a given bit is 1, and from 0 to +127 that a given
bit is 0. The Viterbi algorithm allows to approximate the original sequence of
hard-bits (1 or 0) using these values. Each soft-bit (-127..127) of the burst is
encoded as an unsigned value in range (0..255) respectively using the constant
shift. This way:
* 0 -> definite "0"
* 255 -> definite "1".

PAD: 2 bytes (optional)::
Padding at the end, historical reasons (OpenBTS inheritance). Bits can take any
value, but 0 is preferred. Only expected on TRXDv0 headers.

[[coding-mts]]
===== Coding of MTS: Modulation and Training Sequence info

3GPP TS 45.002 version 15.1.0 defines several modulation types, and a few sets
of training sequences for each type. The most common are GMSK and 8-PSK (which
is used in EDGE).

.MTS field structure
----
+-----------------+---------------------------------------+
| 7 6 5 4 3 2 1 0 | bit numbers (value range)             |
+-----------------+---------------------------------------+
| X . . . . . . . | NOPE / IDLE frame indication (0 or 1) |
+-----------------+---------------------------------------+
| . X X X X . . . | Modulation, TS set number (see below) |
+-----------------+---------------------------------------+
| . . . . . X X X | Training Sequence Code (0..7)         |
+-----------------+---------------------------------------+
----

NOPE / IDLE frame indication (referred to as NOPE.ind)::
The bit number 7 (MSB) shall be set to {bit-one} by the transceiver when either
nothing has been detected, so the BTS scheduler keeps processing bursts without
gaps, or during IDLE frames, so the current noise levels can be delivered.  In
this case the remaining bits become meaningless and shall be set to {bit-zero}.
The payload (`Soft-bits` or `Hard-bits`) is omited.

Modulation and TS set number::
GMSK has 4 sets of training sequences (see tables 5.2.3a-d), while 8-PSK (see
tables 5.2.3f-g) and the others have 2 sets. Access and Synchronization bursts
also have several synchronization sequences.

.Modulation and TS set number
----
+-----------------+---------------------------------------+--------------+
| 7 6 5 4 3 2 1 0 | Description                           | Burst length |
+-----------------+---------------------------------------+--------------+
| . 0 0 X X . . . | GMSK, 4 TS sets (0..3)                |   148 x 1    |
+-----------------+---------------------------------------+--------------+
| . 0 1 0 X . . . | 8-PSK, 2 TS sets (0..1)               |   148 x 3    |
+-----------------+---------------------------------------+--------------+
| . 0 1 1 0 . . . | GMSK, Access Burst (see note)         |   148 x 1    |
+-----------------+---------------------------------------+--------------+
| . 0 1 1 1 . . . | RFU (Reserved for Future Use)         |   -------    |
+-----------------+---------------------------------------+--------------+
| . 1 0 0 X . . . | 16QAM, 2 TS sets (0..1)               |   148 x 4    |
+-----------------+---------------------------------------+--------------+
| . 1 0 1 X . . . | 32QAM, 2 TS sets (0..1)               |   148 x 5    |
+-----------------+---------------------------------------+--------------+
| . 1 1 X X . . . | AQPSK (Downlink), 4 TS sets (0..3)    |   148 x 2    |
+-----------------+---------------------------------------+--------------+
----

NOTE: A radio block on PDCH is carried by the sequence of four Normal Bursts.
The one exception is a special radio block occasionally used on the Uplink
consisting of a sequence of four Access Bursts (see 3GPP TS 44.060).  The
transceiver shall use `0110` as the modulation type to indicate that.

Training Sequence Code::
The Training Sequence Code identifies the Training Sequence of a received
burst.  The value of this field corresponds to one of the sequences defined
in 3GPP TS 45.002, section 5.2, and depends on the actual modulation and
the TSC set indicated by the preceding bits.

==== Downlink Data Burst

.TRXDv0 and TRXDv1 Downlink data burst message structure
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-3:	VER
	4:	RFU
	5-7:	TN
	8-39:	FN
	40-47:	PWR
	48-95:	Hard-bits
}
----

.TRXDv2 Downlink data burst message structure
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-3:	VER(2)
	4:	RFU
	5-7:	TN
	8:	BATCH
	9:	RFU
	10-15:	TRXN
	16-23:	MTS
	24-31:	PWR
	32-39:	SCPIR
	40-63:	RFU
	64-95:	FN
	96-127:	Hard-bits
}
----

.TRXDv2 Downlink PDU structure (batched part)
[packetdiag]
----
{
	colwidth = 32
	node_height = 40

	0-4:	RFU
	5-7:	TN
	8:	BATCH
	9:	RFU
	10-15:	TRXN
	16-23:	MTS
	24-31:	PWR
	32-39:	SCPIR
	40-63:	RFU
	64-95:	Hard-bits
}
----

VER: 4 bits::
TRXD header version, common for both `TRX -> L1` and `L1 -> TRX` directions.

TN: 3 bits::
Timeslot number.

RFU: variable bit-length::
Reserved for Future Use.  The sending side of the PDU shall set all bits to
{bit-zero};  the receiving side shall ignore `RFU` fields.

BATCH: 1 bit::
This bit indicates whether a batched PDU follows (see <<trx_if_pdu_batching>>).

TRXN: 6 bits::
The transceiver (PHY channel) number this PDU is addressed to.

MTS: 8 bits (1 byte)::
Contains the Modulation and Training Sequence information. See <<coding-mts>>
for more information on the encoding.

FN: 32 bits (4 bytes)::
GSM frame number, big endian.

PWR: 8 bits (1 byte)::
Contains the relative (to the full-scale amplitude) transmit power *reduction*
in dB.  The absolute value is set on the control interface, so the resulting
power is calculated as follows: `full_scale - (absolute_red + relative_red)`.

SCPIR: 8 bits (1 byte)::
SCPIR (Subchannel Power Imbalance Ratio) - the ratio of power between Q and I
channels for a VAMOS pair.  This field shall be present when `MTC` field
indicates the use of `AQPSK` modulation.  Otherwise, all bits shall be set
to {bit-zero}.  The value is a signed integer with a valid range: -10..10 dB.

Hard-bits: 148 x N bytes (variable length, N defined by modulation type)::
Contains the downlink burst. Each hard-bit (1 or 0) of the burst is represented
using one byte (0x01 or 0x00 respectively).

[[trx_if_pdu_batching]]
==== PDU batching

Starting from TRXDv2, it's possible to combine several PDUs into a single
datagram - this is called _PDU batching_.  The purpose of _PDU batching_
is to reduce socket load and eliminate possible PDU reordering, especially
in a multi-TRX setup.

All _batched PDUs_ in a datagram must belong to the same TDMA frame number
indicated in the first part.  The ordering of PDUs in a datagram may be
different from the examples below, however it's recommended to batch PDUs
in ascending order determined by TDMA timeslot number and/or `TRXN`.

The following PDU combinations in a datagram are possible:

* `a)` one datagram contains PDUs with the same TDMA timeslot number for all
transceivers (total N PDUs per a TDMA timeslot);
* one datagram contains complete TDMA frame with PDUs for all 8 timeslots:
** `b)` either for a single transceiver (total 8 PDUs per a TDMA frame),
** `c)` or for all transceivers (total 8 x N PDUs per a TDMA frame).

None of these combinations are mandatory to support.

NOTE: Automatic negotiation of the batching algorithm(s) is not yet specified.
Currently both sides need to be manually configured to use _PDU batching_.

NOTE: Size of the biggest possible TRXD datagram should be less than the
_MTU (Maximum Transmission Unit)_ of the network interface connecting
both BTS and the transceiver.  Otherwise the datagram is split across
multiple IP packets, which may negatively affect performance.

.Example: datagram structure for combination a)
----
+--------+----------------+---------+------------------------+
| TRXN=0 | TDMA FN=F TN=T | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=1 | TDMA FN=F TN=T | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=2 | TDMA FN=F TN=T | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=T | BATCH=0 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
----

.Example: datagram structure for combination b)
----
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=0 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=1 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=2 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=7 | BATCH=0 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
----

.Example: datagram structure for combination c)
----
+--------+----------------+---------+------------------------+
| TRXN=0 | TDMA FN=F TN=0 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=0 | TDMA FN=F TN=1 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=0 | TDMA FN=F TN=2 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=6 | BATCH=1 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
| TRXN=N | TDMA FN=F TN=7 | BATCH=0 | Hard-/Soft-bits        |
+--------+----------------+---------+------------------------+
----

[[trx_if_pdu_vamos]]
==== Coding of VAMOS PDUs

In VAMOS mode, the throughput of a cell is increased by multiplexing two subscribers
on a single TDMA timeslot.  Basically, *two* bursts are getting transmitted during
one TDMA timeslot period, and both of them need delivered over the TRXD interface.

In the Downlink direction, the two bursts belonging to a _VAMOS pair_ shall be
concatenated together and sent in one TRXD PDU.  The resulting hard-bit sequence
shall *not* be interleaved: `V0(0..147) + V1(0..147)` (296 hard-bits total), i.e.
one complete burst for subscriber `V0` takes the first 148 bytes, and another
complete burst for subscriber `V1` takes the remaining 148 bytes.  The `MTS` field
shall indicate the use of `AQPSK` modulation, and the `SCPIR` field shall indicate
the Power Imbalance Ratio between `V0` and `V1`.

.Example: Downlink datagram containing a VAMOS PDU
----
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------+----------------+-----------+---------------------------------------+
| TRXN=N | TDMA FN=F TN=T | Mod=AQPSK | Hard-bits: V0(0..147) + V1(0..147)    |
+--------+----------------+-----------+---------------------------------------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
----

In the Uplink direction though, one or even both of the two bursts may be lost
(e.g. due to high noise figures), so they shall always be sent in two separate
PDUs.  The missing bursts shall be substituted by NOPE indications, so it's
always a pair of _batched PDUs_.  First PDU in a pair is called _primary PDU_,
the second is called _shadow PDU_.  This is additionally indicated by the
`SHADOW` field, which is set to {bit-zero} and {bit-one}, respectively.  The
`MTS` field shall indicate the use of `GMSK` modulation if the burst is present.

.Example: Uplink datagram containing batched VAMOS PDUs (both present)
----
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------+----------------+----------+----------+------------------------------+
| TRXN=N | TDMA FN=F TN=T | SHADOW=0 | Mod=GMSK | Soft-bits for V0 (148 bytes) |
+--------+----------------+----------+----------+------------------------------+
| TRXN=N | TDMA FN=F TN=T | SHADOW=1 | Mod=GMSK | Soft-bits for V1 (148 bytes) |
+--------+----------------+----------+----------+------------------------------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
----

.Example: Uplink datagram containing batched VAMOS PDUs (one lost)
----
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------+----------------+----------+----------+------------------------------+
| TRXN=N | TDMA FN=F TN=T | SHADOW=0 | Mod=GMSK | Soft-bits for V0 (148 bytes) |
+--------+----------------+----------+----------+------------------------------+
| TRXN=N | TDMA FN=F TN=T | SHADOW=1 | NOPE.ind |
+--------+----------------+----------+----------+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
----
