diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index 8bcd417..42c97c4 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -1244,6 +1244,12 @@ static bool rtppayload_is_octet_aligned(const uint8_t *rtp_pl, uint8_t payload_l
 
 static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg)
 {
+	/* Discard Themyscira BFI packets - because we have our own
+	 * TDMA timing, there is no difference for us between receiving
+	 * an explicit BFI packet vs receiving nothing at all. */
+	if (resp_msg->len == 2 && resp_msg->data[0] == 0xBF)
+		return false;
+
 	/* Avoid sending bw-efficient AMR to lower layers, most bts models
 	 * don't support it. */
 	if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR &&
@@ -1574,6 +1580,7 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
 	struct gsm_lchan *lchan;
 	uint8_t  chan_nr;
 	uint32_t fn;
+	uint8_t bfi[2];
 
 	chan_nr = tch_ind->chan_nr;
 	fn = tch_ind->fn;
@@ -1619,13 +1626,19 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
 		/* Only clear the marker bit once we have sent a RTP packet with it */
 		lchan->rtp_tx_marker = false;
 	} else {
-		DEBUGPGT(DRTP, &g_time, "Skipping RTP frame with lost payload (chan_nr=0x%02x)\n",
-			 chan_nr);
-		if (lchan->abis_ip.osmux.use)
-			lchan_osmux_skipped_frame(lchan, fn_ms_adj(fn, lchan));
-		else if (lchan->abis_ip.rtp_socket)
-			osmo_rtp_skipped_frame(lchan->abis_ip.rtp_socket, fn_ms_adj(fn, lchan));
-		lchan->rtp_tx_marker = true;
+		/* Themyscira change: send explicit BFI packets instead of
+		 * gaps in the RTP stream. */
+		bfi[0] = 0xBF;
+		bfi[1] = (fn % 104 == 52);	/* TAF */
+		if (lchan->abis_ip.osmux.use) {
+			lchan_osmux_send_frame(lchan, bfi, 2,
+					       fn_ms_adj(fn, lchan), lchan->rtp_tx_marker);
+		} else if (lchan->abis_ip.rtp_socket) {
+			osmo_rtp_send_frame_ext(lchan->abis_ip.rtp_socket,
+				bfi, 2, fn_ms_adj(fn, lchan), lchan->rtp_tx_marker);
+		}
+		/* clear the marker like in the regular code path */
+		lchan->rtp_tx_marker = false;
 	}
 
 	lchan->tch.last_fn = fn;
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 5c99824..e35fc2e 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -981,6 +981,10 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
 		return rc;
 	}
 
+	/* Themyscira addition: empty RTP "ticks" on FACCH */
+	if (data_ind->sapi == GsmL1_Sapi_FacchF)
+		l1if_tch_rx_facch(trx, chan_nr, l1p_msg);
+
 	/* fill L1SAP header */
 	sap_msg = l1sap_msgb_alloc(data_ind->msgUnitParam.u8Size);
 	l1sap = msgb_l1sap_prim(sap_msg);
diff --git a/src/osmo-bts-sysmo/l1_if.h b/src/osmo-bts-sysmo/l1_if.h
index 8691eef..5b2da04 100644
--- a/src/osmo-bts-sysmo/l1_if.h
+++ b/src/osmo-bts-sysmo/l1_if.h
@@ -129,6 +129,8 @@ int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len,
 		    const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn,
 		    bool use_cache, bool marker);
 int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg);
+int l1if_tch_rx_facch(struct gsm_bts_trx *trx, uint8_t chan_nr,
+		      struct msgb *l1p_msg);
 int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer);
 struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn);
 
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index a390c8c..f38d9fe 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -131,12 +131,16 @@ static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload,
 
 	cur[0] |= 0xC0;
 #endif /* USE_L1_RTP_MODE */
+
+/* this code is a bogon: osmo_amr_rtp_dec() won't grok EFR RTP format! */
+#if 0
 	enum osmo_amr_type ft;
 	enum osmo_amr_quality bfi;
 	uint8_t cmr;
 	int8_t sti, cmi;
 	osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti);
 	lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan);
+#endif
 
 	return msg;
 }
@@ -630,6 +634,38 @@ err_payload_match:
 	return -EINVAL;
 }
 
+/*
+ * The following function is a Themyscira Wireless addition: we want to have
+ * an RTP packet sent out on *every* 20 ms "tick", even during times when
+ * TCH was stolen for FACCH.  During FACCH stealing times, it appears that
+ * sysmoBTS PHY sends GsmL1_Sapi_FacchF and no GsmL1_Sapi_TchF, and with
+ * the original code l1if_tch_rx(), the function that feeds "ticks" to the
+ * RTP output mechanism, was never called.  Our added l1if_tch_rx_facch()
+ * function sends an empty payload to the upper layers, and we call it
+ * from the GsmL1_Sapi_FacchF code path.
+ */
+int l1if_tch_rx_facch(struct gsm_bts_trx *trx, uint8_t chan_nr,
+		      struct msgb *l1p_msg)
+{
+	GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg);
+	GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd;
+	struct msgb *rmsg = NULL;
+	struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)];
+
+	if (is_recv_only(lchan->abis_ip.speech_mode))
+		return -EAGAIN;
+
+	LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "chan_nr %d Rx FACCH\n", chan_nr);
+	/* Push empty payload to upper layers */
+	rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
+	return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
+				data_ind->measParam.fBer * 10000,
+				data_ind->measParam.fLinkQuality * 10,
+				0,	/* suppress RSSI like in osmo-bts-trx */
+				data_ind->measParam.i16BurstTiming * 64,
+				0);
+}
+
 struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn)
 {
 	struct msgb *msg;
