= AMR-RTP in Combination with DTX The purpose of this document is to describe the sometimes quite intricate interactions between a MS, the BTS-PHY and the BTS software in case of AMR (Adaptive Multi Rate) codec and DTX (Discontinuous Transmission). It is written with the OsmoBTS implementation and the Nutaq GSM PHY API in mind, but should more or less be applicable to any GSM BTS PHY or any BTS software implementation, assuming it uses RTP on the back-haul towards the MGW. == Full-Rate (TCH/AFS) === TCH/AFS Uplink (MS to Network) ==== TCH/AFS Uplink: Initial Assumptions When a call is established, the BTS expects PH-DATA.ind (TCH) events to be triggered by BTS-PHY at regular intervals and none of them being lost, even if the MS is not transmitting at that time due to DTX. This requirement is important as upper layers rely on this timing to update the RTP source clock at a correct pace. Given an event from BTS-PHY is lost, the RTP source clock will drift and this may be seen as steady increase of delay over time from the receiver point of view. In the case of Nutaq GSM PHY and API, option fBFILevel is set to a ridiculously low value -200 to ensure all indications are notified to upper layers, even if no meaningful payload is available at that time. In this case, an empty payload is delivered from PHY-BTS to BTS, which updates the clock without sending any RTP packet. ==== TCH/AFS Uplink: During Talk-Spurt During a talk-spurt, the system behaves identical to a system without DTX enabled: Every four radio bursts, the BTS-PHY has one AMR frame ready and hands it up to the BTS process, which creates an RTP AMR frame from it and sends that to the MGW. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Regular AMR Speech (has been ongoing for some time)"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N-1 + sub-block 1 of speech frame N)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N-1 + sub-block 2 of speech frame N)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N-1 + sub-block 3 of speech frame N)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N-1 + sub-block 4 of speech frame N)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N-1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N + sub-block 1 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N + sub-block 2 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N + sub-block 3 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N + sub-block 4 of speech frame N+1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; } ---- ==== TCH/AFS Uplink: End of Voice; Start of Silence When the voice encoder in the MS detects no voice activity anymore, it signals towards the MS-PHY that SID_FIRST shall be transmitted. The BTS-PHY reports the following primitives to the BTS after all four related bursts have been received: The BTS sends an RTP frame with AMR Frame Type SID, in which the STI is set to indicate a SID_FIRST message. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Last AMR Speech (end of talk-spurt) and SID"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N, sub-block 1 of SID_FIRST)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N, sub-block 2 of SID_FIRST)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N, sub-block 3 of SID_FIRST)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N, sub-block 4 of SID_FIRST)", id="ULSF2"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)", id="ULSU2"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; } ---- ULSF2:: As per 3GPP TS 05.03 section 3.9.2.4 The last 4 bursts shall not be transmitted unless the SID_FIRST frame is immediately followed by a speech frame. It has been observed that some phone does not transmit the last 4 bursts even if it is not followed by a speech frame. ULSU2:: There must be exactly two suppressed voice frames between the SID_FIRST and the SID_UPDATE, i.e. there's 60ms between SID_FIRST and SID_UPDATE. ==== TCH/AFS Uplink: During Silence While the period of silence is ongoing, the MS pauses all transmissions, except the periodic scheduling of SID_UPDATE every 8 voice frames (160ms). NOTE:: Silence can also be interrupted at any time by ONSET, see <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Every 8 voice frames (160ms)", id="8VF"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; } ---- 8VF:: This happens every 8 *voice frames* (160ms), not every 8 GSM TDMA frames! [[afs-ul-onset]] ==== TCH/AFS Uplink: End of Silence; Start of Voice Once the voice encoder in the MS detects voice activity again, it asks its transmitter to perform transmission of SID_ONSET, which is a special frame whose information is encoded only in sub-blocks 3+4, and sub-blocks 1+2 are discarded before transmission. A set of four radio bursts is sent, containing * the only four transmitted sub-blocks of the SID_ONSET frame * all four sub-blocks of the first voice codec frame * the first two blocks of the second voice codec frame The BTS-PHY informs the BTS using two primitives: * PH-DATA.ind GsmL1_TchPlType_Amr_Onset indicates the presence of SID_ONSET, including the Channel Mode Indication (irrespective of CMI Phase) * PH-DATA.ind GsmL1_TchPlType_Amr indicates the first voice frame The BTS transmits an RTP frame with AMR payload of the corresponding speech frame type, and sets the RTP MARKER bit to indicate the ONSET condition. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Once voice is active again"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of speech frame N)", id="ULSO2"]; ms => phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of speech frame N)"]; ms => phy [label="L1 burst (block 3 of SID_ONSET + sub-block 3 of speech frame N)"]; ms => phy [label="L1 burst (block 4 of SID_ONSET + sub-block 4 of speech frame N)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N + sub-block 1 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N + sub-block 2 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N + sub-block 3 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N + sub-block 4 of speech frame N+1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_Onset"]; bts => bts [label="lchan_set_marker() and store CMI"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N+1 + sub-block 1 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N+1 + sub-block 2 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N+1 + sub-block 3 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N+1 + sub-block 4 of speech frame N+2)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N+1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ...; } ---- ULSO2:: sub-blocks 1..4 of SID_ONSET are never transmitted as all information is contained in blocks 5..8. ==== TCH/AFS Uplink: Speech Frame Following a SID_FIRST frame The four last bursts of a SID_FIRST frame can be replaced by an ONSET frame in order to quickly resume speech. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Speech Frame Following a SID_FIRST"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N, sub-block 1 of SID_FIRST)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N, sub-block 2 of SID_FIRST)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N, sub-block 3 of SID_FIRST)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N, sub-block 4 of SID_FIRST)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of speech frame N+1)"]; ms => phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of speech frame N+1)"]; ms => phy [label="L1 burst (block 3 of SID_ONSET + sub-block 3 of speech frame N+1)"]; ms => phy [label="L1 burst (block 4 of SID_ONSET + sub-block 4 of speech frame N+1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; ms => phy [label="L1 burst (sub-block 5 of speech frame N+1 + sub-block 1 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 6 of speech frame N+1 + sub-block 2 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 7 of speech frame N+1 + sub-block 3 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 8 of speech frame N+1 + sub-block 4 of speech frame N+2)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_Onset"]; bts => bts [label="lchan_set_marker() and store CMI"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N+1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; ...; } ---- ==== TCH/AFS Uplink: FACCH/F Frame During DTX Operation As mentioned in section A.5.1.2.1 of 3GPP TS 26.093 : * If the frame preceding the FACCH frame is not of TX_TYPE='SPEECH_GOOD', then an ONSET frame shall be signalled to the CHE, followed by the FACCH frame(s). * If the frame following the FACCH frame is not of TX_TYPE='SPEECH_GOOD', then a SID_FIRST shall be signalled to the CHE. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="FACCH/F Frame During DTX"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of FACCH frame)"]; ms => phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of FACCH frame)"]; ms => phy [label="L1 burst (block 3 of SID_ONSET + sub-block 3 of FACCH frame)"]; ms => phy [label="L1 burst (block 4 of SID_ONSET + sub-block 4 of FACCH frame)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 5 of FACCH frame + sub-block 1 of SID First frame)"]; ms => phy [label="L1 burst (sub-block 6 of FACCH frame + sub-block 2 of SID First frame)"]; ms => phy [label="L1 burst (sub-block 7 of FACCH frame + sub-block 3 of SID First frame)"]; ms => phy [label="L1 burst (sub-block 8 of FACCH frame + sub-block 4 of SID First frame)", id="Note"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_Onset"]; bts => bts [label="lchan_set_marker() and store CMI"]; phy => bts [label="PH-DATA.ind FACCH/F"]; bts => mgw [label="FACCH/F"]; ms -x phy [label="Suppressed L1 burst", id="ULSF2"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_FIRST)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; ...; } ---- ULSF2:: The sub-blocks 5-8 of SID_FIRST are not transmitted, as all information bits are contained in sub-blocks 1-4 only Note:: It has been observed with some phones that the SID_FIRST is not sent following the FACCH/F frame. If this case occurs the No Data Frame and SID_UPDATE order resumes. === TCH/AFS Downlink (Network to MS) [[afs-dl-talk]] ==== TCH/AFS Downlink: During Talk-Spurt During a talk-spurt, the system behaves identical to a system without DTX enabled: an RTP frame arrives every 20ms. The PHY sends a PH-RTS.ind in similar intervals, to which the BTS responds with a PH-DATA.req containing GsmL1_TchPlType_Amr. The BTS-PHY then encodes and interleaves the codec frame into eight sub-blocks. Due to the interleaving, one new PH-RTS.ind is issued every four bursts. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Regular AMR Speech (has been ongoing for some time)"]; mgw => bts [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (sub-block 5 of speech frame N-1 + sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (sub-block 6 of speech frame N-1 + sub-block 2 of speech frame N)"]; ms <= phy [label="L1 burst (sub-block 7 of speech frame N-1 + sub-block 3 of speech frame N)"]; ms <= phy [label="L1 burst (sub-block 8 of speech frame N-1 + sub-block 4 of speech frame N)"]; mgw => bts [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 5 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 6 of speech frame N + sub-block 2 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 7 of speech frame N + sub-block 3 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 8 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AFS Downlink: End of Voice; Start of Silence When the BTS receives the first RTP frame with Frame Type SID, it will generate a SID_FIRST AMR frame. The AMR frame is interleaved in a way that all information is contained in the first four sub-blocks, with the latter four sub-blocks being dropped and not transmitted. Three codec frames (60ms) later, the BTS needs to transmit a SID_UPDATE AMR frame, which should consist of comfort noise parameters received in either the first AMR SID frame, or a subsequent AMR SID frame received meanwhile. In between SID_FIRST and SID_UPDATE, and after the SID_UPDATE, the BTS sends PH-EMPTY-FRAME.req to all PH-RTS.ind, causing the BTS-PHY to cease transmission in those periods. NOTE:: At any time, the BTS can end the silence period by issuing ONSET (in case of a new downlink talk-spurt or a FACCH downlink frame). See <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Last AMR Speech (end of talk-spurt) and SID First"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_FIRST)"]; bts => bts [label="Store SID frame in case it contains comfort noise parameters"]; ms <= phy [label="L1 burst (sub-block 5 of speech frame N-1 + sub-block 1 of SID_FIRST)"]; ms <= phy [label="L1 burst (sub-block 6 of speech frame N-1 + sub-block 2 of SID_FIRST)"]; ms <= phy [label="L1 burst (sub-block 7 of speech frame N-1 + sub-block 3 of SID_FIRST)"]; ms <= phy [label="L1 burst (sub-block 8 of speech frame N-1 + sub-block 4 of SID_FIRST)", id="DLSF2"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; bts => bts [label="Store SID frame in case it contains comfort noise parameters"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_UPDATE)", id="DLSU2"]; ms <= phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; } ---- DLSF2:: sub-frames 5..8 of SID_FIRST are not transmitted, as all information is contained in sub-frames 1..4 DLSU2:: The SID_UPDATE must be sent exactly three voice frames (60ms) after the SID_FIRST, resulting in two suppressed voice frame periods of empty bursts in-between. ==== TCH/AFS Downlink: During Silence During Silence periods, the BTS may at any time receive RTP AMR SID frames, and keep a copy of the last received frame around. Every eight voice frames (160ms), the BTS shall respond to the PH-RTS.ind with a PH-DATA.req containing a GsmL1_TchPlType_Amr with SID_UPDATE frame. At all other times, the BTS sends PH-EMPTY-FRAME.req to any received PH-RTS.ind, causing the BTS-PHY to cease transmission in those periods. NOTE:: At any time, the BTS can end the silence period by issuing ONSET (in case of a new downlink talk-spurt or a FACCH downlink frame). See <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Every 8 voice frames (160ms)", id="8VF"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; bts => bts [label="Store SID frame in case it contains comfort noise parameters"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; } ---- 8VF:: This happens every 8 *voice frames* (160ms), not every 8 GSM TDMA frames! [[afs-dl-onset]] ==== TCH/AFS Downlink: End of Silence; Start of Voice Once the BTS receives a non-SID AMR RTP frame (which should also have the MARKER bit set to 1, but let's not take that for granted), the contained AMR voice data is passed to the BTS-PHY in the next PH-DATA.req (GsmL1_TchPlType_Amr_Onset). From that point onwards, regular transmission resumes, see <> ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Once voice is active again"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_Onset"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of speech frame N)"]; ms <= phy [label="L1 burst (block 3 of SID_ONSET + sub-block 3 of speech frame N)"]; ms <= phy [label="L1 burst (block 4 of SID_ONSET + sub-block 4 of speech frame N)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 5 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 6 of speech frame N + sub-block 2 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 7 of speech frame N + sub-block 2 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 8 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AFS Downlink: Inhibiting a SID_FIRST frame Here is the procedure to inhibit a SID_FIRST frame in order to quickly resume speech. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Inhibiting a SID_FIRST frame"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_FIRST)"]; bts => bts [label="Store SID frame in case it contains comfort noise parameters"]; ms <= phy [label="L1 burst (sub-block 5 of speech frame N-1 + sub-block 1 of SID_FIRST)"]; ms <= phy [label="L1 burst (sub-block 6 of speech frame N-1 + sub-block 2 of SID_FIRST)"]; ms <= phy [label="L1 burst (sub-block 7 of speech frame N-1 + sub-block 3 of SID_FIRST)"]; ms <= phy [label="L1 burst (sub-block 8 of speech frame N-1 + sub-block 4 of SID_FIRST)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_Onset"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of speech frame N)"]; ms <= phy [label="L1 burst (block 3 of SID_ONSET + sub-block 3 of speech frame N)"]; ms <= phy [label="L1 burst (block 4 of SID_ONSET + sub-block 4 of speech frame N)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 5 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 6 of speech frame N + sub-block 2 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 7 of speech frame N + sub-block 2 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 8 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AFS Downlink: FACCH/F During DTX Operation The following procedure must be observed if a FACCH/F frame must be transmitted during DTX operation. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="FACCH/F Frame During DTX"]; bts <= mgw [label="FACCH/F"]; phy => bts [label="PH-RTS.ind (FACCH/F)"]; phy => bts [label="PH-RTS.ind (TCH/F)"]; phy <= bts [label="PH-DATA.req (FACCH/F)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_Onset(TCH/F)", id="NOTE"]; ms <= phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of FACCH/F)"]; ms <= phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of FACCH/F)"]; ms <= phy [label="L1 burst (block 3 of SID_ONSET + sub-block 3 of FACCH/F)"]; ms <= phy [label="L1 burst (block 4 of SID_ONSET + sub-block 4 of FACCH/F)"]; phy => bts [label="PH-RTS.ind (FACCH)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req (FACCH/F)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_FIRST)"]; ms x- phy [label="L1 burst (sub-block 5 of FACCH/F + sub-block 1 of SID_FIRST)"]; ms x- phy [label="L1 burst (sub-block 6 of FACCH/F + sub-block 2 of SID_FIRST)"]; ms x- phy [label="L1 burst (sub-block 7 of FACCH/F + sub-block 3 of SID_FIRST)"]; ms x- phy [label="L1 burst (sub-block 8 of FACCH/F + sub-block 4 of SID_FIRST)"]; phy => bts [label="PH-RTS.ind (FACCH)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req (FACCH/F)"]; phy <= bts [label="PH-EMPTY-FRAME.req (TCH/F)"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; } ---- NOTE:: The ONSET and the FACCH/F PH-DATA requests must both be sent to the PHY. == Half-Rate (TCH/AHS) === TCH/AHS Uplink (MS to Network) ==== TCH/AHS Uplink: During Talk-Spurt During a talk-spurt, the system behaves identical to a system without DTX enabled: Every two radio bursts, the BTS-PHY has one AMR frame ready and hands it up to the BTS process, which creates an RTP AMR frame from it and sends that to the MGW. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Regular AMR Speech (has been ongoing for some time)"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N-1 + sub-block 1 of speech frame N)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N-1 + sub-block 2 of speech frame N)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N-2)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N-1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N+1 + sub-block 1 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N+1 + sub-block 2 of speech frame N+2)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; } ---- ==== TCH AHS Uplink: End of Voice; Start of Silence When the voice encoder in the MS detects no voice activity anymore, it signals towards the MS-PHY that SID_FIRST_P1 and SID_FIRST_P2 shall be transmitted. The BTS-PHY reports the following primitives to the BTS after all four related bursts have been received: * PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1 * PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP2 The BTS sends an RTP frame with AMR Frame Type SID, in which the STI is set to indicate a SID_FIRST message. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Last AMR Speech (end of talk-spurt) and SID P1/P2"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N, sub-block 1 of SID_FIRST_P1)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N, sub-block 2 of SID_FIRST_P1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N-1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (sub-block 3 of SID_FIRST_P1, sub-block 1 of SID_FIRST_P2)"]; ms => phy [label="L1 burst (sub-block 4 of SID_FIRST_P1, sub-block 2 of SID_FIRST_P2)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1", id="ULSF1"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)", id="ULSU1"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP2", id="NOTE"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; } ---- ULSF1:: Only SID_FIRST_P1 contains information so it must be the only one transmitted over RTP. NOTE:: It has been observed that not all phones transmit SID_FIRST_P2 so the PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP2 is not guaranteed to be sent to the BTS. ULSU1:: There must be exactly two suppressed voice frames between the SID_FIRST and the SID_UPDATE, i.e. there's 60ms between SID_FIRST and SID_UPDATE. ==== TCH/AFS Uplink: During Silence While the period of silence is ongoing, the MS pauses all transmissions, except the periodic scheduling of SID_UPDATE every 8 voice frames (160ms). NOTE:: Silence can also be interrupted at any time by ONSET, see <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Every 8 voice frames (160ms)", id="8VF"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (SID_UPDATE)"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; } ---- 8VF:: This happens every 8 *voice frames* (160ms), not every 8 GSM TDMA frames! [[ahs-ul-onset]] ==== TCH/AHS Uplink: End of Silence; Start of Voice Once the voice encoder in the MS detects voice activity again, it asks its transmitter to perform transmission of SID_ONSET, which is a special frame which has information encoded only in sub-blocks 3+4, and sub-blocks 1+2 are discarded before transmission. A set of four radio bursts is sent, containing * the only two transmitted sub-blocks of the SID_ONSET frame * all four sub-blocks of the first voice codec frame * the first two blocks of the second voice codec frame The BTS-PHY informs the BTS using two primitives: * PH-DATA.ind GsmL1_TchPlType_Amr_Onset indicates the presence of SID_ONSET, including the Channel Mode Indication (irrespective of CMI Phase) * PH-DATA.ind GsmL1_TchPlType_Amr indicates the first voice frame The BTS transmits a RTP frame with AMR payload of the corresponding speech frame type, and sets the RTP MARKER bit to indicate the ONSET condition. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Once voice is active again"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of speech frame N)"]; ms => phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of speech frame N)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N+1 + sub-block 1 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N+1 + sub-block 2 of speech frame N+2)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_Onset"]; bts => bts [label="lchan_set_marker() and store CMI"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; ...; } ---- ==== TCH/AHS Uplink: Inhibited SID_FIRST In case voice activity is detected again while the SID_FIRST_P1 transmission is ongoing or completed, but the SID_FIRST_P2 has not been transmitted yet, SID_FIRST can be inhibited by means of a SID_FIRST_INH frame. This allows the first voice frame to be transmitted with minimal delay, compared to first completing the regular SID_FIRTS_P2 and SID_ONSET procedure. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ms .. mgw [label="End of talk-spurt with inhibited SID_FIRST"]; ms => phy [label="L1 burst (sub-block 3 of last speech frame N + sub-block 1 of SID_FIRST_P1)"]; ms => phy [label="L1 burst (sub-block 4 of last speech frame N + sub-block 2 of SID_FIRST_P1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N-1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (block 1 of SID_FIRST_INH and sub-block 1 of speech frame N+1", id="SFI1"]; ms => phy [label="L1 burst (block 2 of SID_FIRST_INH and sub-block 2 of speech frame N+1"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1)"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N+1 + sub-block 1 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N+1 + sub-block 2 of speech frame N+2)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N+2 + sub-block 1 of speech frame N+3)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N+2 + sub-block 2 of speech frame N+3)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidInh", id="SFI2"]; bts => bts [label="store CMI from SID_FIRST_INH"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N+1)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; } ---- ==== TCH/AHS Uplink: Inhibited SID_UPDATE In case voice activity is detected again while the SID_UPDATE transmission of the first two sub-blocks is ongoing or completed, but the second two sub-blocks have not been transmitted yet, SID_UPDATE can be inhibited by means of a SID_UPDATE_INH frame. This allows the first voice frame to be transmitted with minimal delay, compared to first completing the regular SID_UPDATE and SID_ONSET procedure. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; ms .. mgw [label="Inhibited SID Update (during silence period)"]; ms => phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms => phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (block 1 of SID_UPD_INH + sub-block 1 of speech frame N)", id="SFU1"]; ms => phy [label="L1 burst (block 2 of SID_UPD_INH + sub-block 2 of speech frame N)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 3 of speech frame N+1 + sub-block 1 of speech frame N+2)"]; ms => phy [label="L1 burst (sub-block 4 of speech frame N+1 + sub-block 2 of speech frame N+2)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidUpdateInH", id="SFU2"]; bts => bts [label="lchan_set_marker() and store CMI from SID_UPD_INH"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr (N)"]; bts => mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; } ---- ==== TCH/AHS Uplink: FACCH/H During DTX operation The following procedure must be observed if a FACCH/H frame must be transmitted during DTX operation. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; ms .. mgw [label="FACCH/H during DTX operation"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (block 1 of SID_ONSET + sub-block 1 of FACCH/H)"]; ms => phy [label="L1 burst (block 2 of SID_ONSET + sub-block 2 of FACCH/H)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 3+4 of FACCH/H)"]; ms => phy [label="L1 burst (sub-block 5+6 of FACCH/H)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms => phy [label="L1 burst (sub-block 7 of FACCH/H + sub-block 1 of SID_FIRST_P1)"]; ms => phy [label="L1 burst (sub-block 8 of FACCH/H + sub-block 2 of SID_FIRST_P1)"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_Onset"]; bts => bts [label="lchan_set_marker() and store CMI"]; phy => bts [label="PH-DATA.ind FACCH/H"]; bts => mgw [label="FACCH/H"]; ms => phy [label="L1 burst (sub-block 3 of SID_FIRST_P1 + block 1 of SID_FIRST_P2)"]; ms => phy [label="L1 burst (sub-block 4 of SID_FIRST_P1 + block 2 of SID_FIRST_P2)"]; phy => bts [label="PH-DATA.ind with empty payload"]; bts -x mgw [label="Suppressed RTP frame"]; ms -x phy [label="Suppressed L1 burst"]; ms -x phy [label="Suppressed L1 burst"]; phy => bts [label="PH-DATA.ind GsmL1_TchPlType_Amr_SidFirstP1"]; bts => mgw [label="RTP (AMR FT=SID,Q=1)"]; } ---- === TCH/AHS Downlink (Network to MS) [[ahs-dl-talk]] ==== TCH/AHS Downlink: During Talk-Spurt During a talk-spurt, the system behaves identically to a system without DTX enabled: an RTP frame arrives every 20ms. The PHY sends a PH-RTS.ind in similar intervals, to which the BTS responds with a PH-DATA.req containing GsmL1_TchPlType_Amr. The BTS-PHY then encodes and interleaves the codec frame into four sub-blocks. Due to the interleaving, one new PH-RTS.ind is issued every two bursts. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Regular AMR Speech (has been ongoing for some time)"]; mgw => bts [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N-1 + sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N-1 + sub-block 2 of speech frame N)"]; mgw => bts [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AHS Downlink: End of Voice; Start of Silence When the BTS receives the first RTP frame with Frame Type SID, it will first issue a GsmL1_TchPlType_Amr_SidFirstP1 primitive towards the BTS-PHY, followed by a GsmL1_TchPlType_Amr_SidFirstP2 primitive. The SID_FIRST_P2 is interleaved in a way that all information is contained in the first two sub-blocks, with the latter two sub-blocks being dropped and not transmitted. Three codec frames (60ms) later, the BTS needs to transmit a SID_UPDATE AMR frame, which should consist of comfort noise parameters received in either the first RTP AMR SID frame, or a subsequent RTP AMR SID frame received meanwhile. In between SID_FIRST_P2 and SID_UPDATE, and after the SID_UPDATE, the BTS sends PH-EMPTY-FRAME.req to all PH-RTS.ind, causing the BTS-PHY to cease transmission in those periods. NOTE:: At any time, the BTS can end the silence period by issuing ONSET (in case of a new downlink talk-spurt or a FACCH downlink frame). See Section <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Last AMR Speech (end of talk-spurt) and SID P1/P2"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidFirstP1"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N-1 + sub-block 1 of SID_FIRST_P1)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N-1 + sub-block 2 of SID_FIRST_P1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidFirstP2"]; ms <= phy [label="L1 burst (sub-block 3 of SID_FIRST_P1, sub-block 1 of SID_FIRST_P2)"]; ms <= phy [label="L1 burst (sub-block 4 of SID_FIRST_P1, sub-block 2 of SID_FIRST_P2)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_UPDATE)", id="ULSU2"]; ms <= phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms <= phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms x- phy [label="Suppressed burst"]; ms x- phy [label="Suppressed burst"]; } ---- ULSU2:: The SID_UPDATE must be sent exactly three voice frames (60ms) after the SID_FIRST, resulting in two suppressed voice frame periods of empty bursts in between. ==== TCH/AHS Downlink: During Silence During Silence periods, the BTS may at any time receive RTP AMR SID frames and keep a copy of the last received frame around. Every eight voice frames (160ms), the BTS shall respond to the PH-RTS.ind with a PH-DATA.req containing a GsmL1_TchPlType_Amr with SID_UPDATE frame. At all other times, the BTS sends PH-EMPTY-FRAME.req to any received PH-RTS.ind, causing the BTS-PHY to cease transmission in those periods. NOTE:: At any time, the BTS can end the silence period by issuing ONSET (in case of a new downlink talk-spurt or a FACCH downlink frame). See Section <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Every 8 voice frames (160ms)", id="8VF"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms <= phy [label="L1 burst (sub-block 5+6 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 7+8 of SID_UPDATE)"]; } ---- 8VF:: This happens every 8 *voice frames* (160ms), not every 8 GSM TDMA frames! [[ahs-dl-onset]] ==== TCH/AHS Downlink: End of Silence; Start of Voice Once the BTS receives a non-SID AMR RTP frame (which should also have the MARKER bit set to 1, but let’s not take that for granted), the contained AMR voice data is passed to the BTS-PHY in the next PH-DATA.req (GsmL1_TchPlType_Amr_Onset). From that point onwards, regular transmission resumes, see <>. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Once voice is active again"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_Onset"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (sub-block 3 of SID_ONSET + sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (sub-block 4 of SID_ONSET + sub-block 2 of speech frame N)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AHS Downlink: Inhibited SID_FIRST_P1 The following procedure must be observed in case of a SID_FIRST must be inhibited. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Inhibited SID_FIRST_P1"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidFirstP1"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N-1 + sub-block 1 of SID_FIRST_P1)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N-1 + sub-block 2 of SID_FIRST_P1)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidFirstInh"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (block 1 of SID_FIRST_INH, sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (block 2 of SID_FIRST_INH, sub-block 2 of speech frame N)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AHS Downlink: Inhibited SID_UPDATE The following procedure must be observed in case of a SID_UPDATE must be inhibited. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="Inhibited SID_UPDATE"]; bts <= mgw [label="RTP (AMR FT=SID,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; bts => phy [label="PH-DATA.req GsmL1_TchPlType_Amr (SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 1+2 of SID_UPDATE)"]; ms <= phy [label="L1 burst (sub-block 3+4 of SID_UPDATE)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1) MARKER=1"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidUpdateInh"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N)"]; ms <= phy [label="L1 burst (block 1 of SID_UPDATE_INH, sub-block 1 of speech frame N)"]; ms <= phy [label="L1 burst (block 2 of SID_UPDATE_INH, sub-block 2 of speech frame N)"]; bts <= mgw [label="RTP (AMR FT=0..7,Q=1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr (N+1)"]; ms <= phy [label="L1 burst (sub-block 3 of speech frame N + sub-block 1 of speech frame N+1)"]; ms <= phy [label="L1 burst (sub-block 4 of speech frame N + sub-block 2 of speech frame N+1)"]; } ---- ==== TCH/AHS Downlink: FACCH/H During DTX Operation The following procedure must be observed in case of a FACCH/H frame must be inserted during DTX operation. ["mscgen"] ---- msc { hscale = 2; ms [label="MS"], phy [label="BTS-PHY"], bts [label="BTS"], mgw [label="MGW"]; ...; --- [label="FACCH/H During DTX Operation"]; bts <= mgw [label="FACCH/H"]; phy => bts [label="PH-RTS.ind (FACCH/H)"]; phy => bts [label="PH-RTS.ind (TCH/H)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_Onset"]; phy <= bts [label="PH-DATA.req FACCH/H"]; ms <= phy [label="L1 burst (block 1 of SID_ONSET, sub-block 1 of FACCH/H frame)"]; ms <= phy [label="L1 burst (block 2 of SID_ONSET, sub-block 2 of FACCH/H frame)"]; phy => bts [label="PH-RTS.ind (TCH/H)"]; phy <= bts [label="PH-EMPTY-FRAME.req"]; ms <= phy [label="L1 burst (sub-block 3+4 of FACCH/H frame)"]; ms <= phy [label="L1 burst (sub-block 5+6 of FACCH/H frame)"]; phy => bts [label="PH-RTS.ind (FACCH/H)"]; phy => bts [label="PH-RTS.ind (TCH/H)"]; phy <= bts [label="PH-EMPTY-FRAME.req (FACCH/H)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidFirstP1"]; ms <= phy [label="L1 burst (sub-block 7 of FACCH/H frame + sub-block 1 of SID_FIRST_P1)"]; ms <= phy [label="L1 burst (sub-block 8 of FACCH/H frame + sub-block 2 of SID_FIRST_P1)"]; phy => bts [label="PH-RTS.ind (TCH)"]; phy <= bts [label="PH-DATA.req GsmL1_TchPlType_Amr_SidFirstP2"]; ms <= phy [label="L1 burst (sub-block 3 of SID_FIRST_P1, sub-block 1 of SID_FIRST_P2)"]; ms <= phy [label="L1 burst (sub-block 4 of SID_FIRST_P1, sub-block 2 of SID_FIRST_P2)"]; } ---- == Implementation details There is FSM implementing all the necessary states and transitions for DTX DL. [[dtx_dl_fsm]] [graphviz] ---- include::{srcdir}/dtx.dot[] ---- The idea is that each state corresponds to the particular message type which have to be send to L1 next while state transition happens on incoming events like FACCH or Voice frames. There are 3 different classes of of events driving this FSM: * Voice frame types: E_VOICE, E_SID_U, E_SID_F * Incoming FACCH: E_FACCH * Internal: E_ONSET, E_INHIB, E_COMPL They represent different types of incoming RTP frames (Voice, SID UPDATE and SID FIRST correspondingly), incoming FACCH events or important events internal to DTX operations. The latter are Onset (interruption of silence period), Inhibition (of currently transmitted SID FIRST or UPDATE) and Completion (of silence initiation). The double-circled states are "stationary" meaning that FSM can stay for longer periods in them. Other states are "transient" - the FSM have to switch away during next step. In practice this is implemented using E_COMPL signal which is issued in corresponding RTS handler or internal function (in case of SID First P1 -> P2 transition). The FSM states are grouped as follows: * ST_VOICE: talkspurt, normal voice transmission * ST_FACCH: transmission of higher-priority FACCH frame, interrupting current DTX state * ST_ONSET*: handling of Onset event (interruption of silence period) * ST_SID_F*: silence initiation * ST_*_REC: sending of 2nd event for L1 during the same FN * ST_*_INH: handling of Inhibition event (interruption of transmission of previous event) The latter are specific to AMR HR where transmission of particular message by L1 takes longer so it can be aborted due to another incoming event. Note that for AMR FR only subset of this FSM is active (ST_SID_F2 and *INH states are never reached). This is implemented by signal emitting functions. Note that the FSM states describe only the situation when we got to send something to L1, the transmission of Empty frames suppressing the actual radio transmission is done by other code.