[PATCH] osmo-tetra[laforge/sq5bpf-rebase-20161218]: adding dmo support:

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

allesklar2 gerrit-no-reply at lists.osmocom.org
Sat Jul 15 14:35:13 UTC 2017


Hello Harald Welte,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/2817

to look at the new patch set (#2).

adding dmo support:

physical layer: If DMO preamble bits are present, burst are send to DMO SAPs

lower mac layer: Decoding DMO Bursts and adding a new SAP for DMO. This SAP forwards all requests to the TMO SAP because the processing is quite similar. Nevertheless this SAP is important because in further developments you can change the lower mac without addopting the physical layer.

Change-Id: Ifa5521d7313595384e74dd790a56550755b93fe9
---
M AUTHORS
M src/conv_enc_test.c
M src/lower_mac/tetra_lower_mac.c
M src/lower_mac/tetra_scramb.c
M src/lower_mac/tetra_scramb.h
M src/phy/tetra_burst.c
M src/phy/tetra_burst_sync.c
M src/phy/tetra_burst_sync.h
M src/tetra-rx.c
M src/tetra_common.h
M src/tetra_gsmtap.c
11 files changed, 464 insertions(+), 25 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/17/2817/2

diff --git a/AUTHORS b/AUTHORS
index a0c987b..7702664 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,5 @@
 Harald Welte <laforge at gnumonks.org>
 Sylvain Munaut <tnt at 246tNt.com>
 Holger Hans Peter Freyther <holger at freyther.de>
+Jan-Pascal Kwiotek <info at igis.biz>
+Jannik Jürgens <jjuergens at seemoo.tu-darmstadt.de>
diff --git a/src/conv_enc_test.c b/src/conv_enc_test.c
index 303ef31..e714ec6 100644
--- a/src/conv_enc_test.c
+++ b/src/conv_enc_test.c
@@ -49,6 +49,11 @@
 {
 }
 
+/* incoming DP-SAP UNITDATA.ind  from PHY into lower MAC */
+void dp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned int len, void *priv)
+{
+}
+
 static void decode_schf(const uint8_t *bits)
 {
 	uint8_t type4[1024];
diff --git a/src/lower_mac/tetra_lower_mac.c b/src/lower_mac/tetra_lower_mac.c
index 53fe73a..b0f95ed 100644
--- a/src/lower_mac/tetra_lower_mac.c
+++ b/src/lower_mac/tetra_lower_mac.c
@@ -103,6 +103,42 @@
 		.type2_bits	= 30,
 		.type1_bits	= 14,
 	},
+  	/* DMO Synchronization Burst Block 1 */
+	[DPSAP_SCH_S] = {
+		.name		= "SCH/S",
+		.type345_bits 	= 120,
+		.type2_bits	= 80,
+		.type1_bits	= 60,
+		.interleave_a	= 11,
+		.have_crc16	= 1,
+	},
+  	/* DMO Synchronization Burst Block 2 */
+	[DPSAP_SCH_H] = {
+		.name		= "SCH/H",
+		.type345_bits	= 216,
+		.type2_bits	= 144,
+		.type1_bits	= 124,
+		.interleave_a	= 101,
+		.have_crc16	= 1,
+	},
+  	/* DMO Normal Burst Block 1+2 */
+	[DPSAP_SCH_F] = {
+		.name		= "SCH/F",
+		.type345_bits	= 432,
+		.type2_bits	= 288,
+		.type1_bits	= 268,
+		.interleave_a	= 103,
+		.have_crc16	= 1,
+	},
+  	/* DMO Normal Burst with Slot Flag */
+	[DPSAP_STCH] = {
+		.name		= "STCH",
+		.type345_bits	= 216,
+		.type2_bits	= 144,
+		.type1_bits	= 124,
+		.interleave_a	= 101,
+		.have_crc16	= 1,
+	},
 };
 
 struct tetra_cell_data {
@@ -112,6 +148,7 @@
 	struct tetra_tdma_time time;
 
 	uint32_t scramb_init;
+	uint32_t textmessage_length;
 };
 
 static struct tetra_cell_data _tcd, *tcd = &_tcd;
@@ -151,6 +188,7 @@
 	uint8_t type3dp[512*4];
 	uint8_t type3[512];
 	uint8_t type2[512];
+	uint8_t frag_offset; 	/* for variable fields in DPSAP_SCH_H */
 
 	const struct tetra_blk_param *tbp = &tetra_blk_param[type];
 	struct tetra_mac_state *tms = priv;
@@ -181,7 +219,7 @@
 
 	/* De-scramble, pay special attention to SB1 pre-defined scrambling */
 	memcpy(type4, bits, tbp->type345_bits);
-	if (type == TPSAP_T_SB1) {
+	if (type == TPSAP_T_SB1 || type == DPSAP_SCH_S  || type == DPSAP_SCH_H) {
 		tetra_scramb_bits(SCRAMB_INIT, type4, tbp->type345_bits);
 		tup->scrambling_code = SCRAMB_INIT;
 	} else {
@@ -235,7 +273,7 @@
 		printf("MN %s(%2u) ", osmo_ubit_dump(type2+17, 6), bits_to_uint(type2+17, 6));
 		printf("MCC %s(%u) ", osmo_ubit_dump(type2+31, 10), bits_to_uint(type2+31, 10));
 		printf("MNC %s(%u)\n", osmo_ubit_dump(type2+41, 14), bits_to_uint(type2+41, 14));
-		/* obtain information from SYNC PDU */
+		/* obtain information from SYNC PDU - 21.4.4.2 */
 		tcd->colour_code = bits_to_uint(type2+4, 6);
 		tcd->time.tn = bits_to_uint(type2+10, 2);
 		tcd->time.fn = bits_to_uint(type2+12, 5);
@@ -296,6 +334,294 @@
 		}
 			/* sq5bpf: koniec */
 		break;
+	case DPSAP_SCH_F:
+		/* 396-3 9.2 */
+		if (bits_to_uint(type2, 2) == 0) {
+			printf("MAC PDU type: DMAC-DATA PDU %s(%2u) ", osmo_ubit_dump(type2, 2), bits_to_uint(type2, 2));
+
+		} else if(bits_to_uint(type2, 2) == 3) {
+			printf("MAC PDU type: DMAC-U-Signal PDU %s(%2u) ", osmo_ubit_dump(type2, 2), bits_to_uint(type2, 2));
+		} else if(bits_to_uint(type2, 2) == 1) {
+			if(bits_to_uint(type2+2, 1) == 0) {
+				printf("MAC PDU type: DMAC-FRAG PDU %s(%2u) ", osmo_ubit_dump(type2, 2), bits_to_uint(type2, 2));
+			} else {
+				printf("MAC PDU type: DMAC-END PDU %s(%2u) ",
+						osmo_ubit_dump(type2, 2), bits_to_uint(type2, 2));
+				printf("MAC PDU subtype: %s(%2u) ",
+						osmo_ubit_dump(type2 + 2, 1),
+						bits_to_uint(type2 + 2, 1));
+				/* 392-2 29.4.2.4 and 29.5.2.3 */
+				printf("Protocol identifier: %s(%2u) ",
+						osmo_ubit_dump(type2 + 4, 8),
+						bits_to_uint(type2 + 4, 8));
+				printf("Message type: %s(%2u) ", osmo_ubit_dump(type2 + 12, 4),
+						bits_to_uint(type2 + 12, 4));
+				if (bits_to_uint(type2 + 12, 4) == 0) {
+					/* SDS TRANSFER */
+					printf("Delivery report request: %s(%2u) ",
+							osmo_ubit_dump(type2 + 16, 2),
+							bits_to_uint(type2 + 16, 2));
+					printf("Encoding: %s(%2u) ", osmo_ubit_dump(type2 + 28, 7),
+							bits_to_uint(type2 + 28, 7));
+					printf("Message: ");
+					int i = 0;
+					while (i + 28 + 7 < tcd->textmessage_length) {
+						char message = bits_to_uint(type2 + 28 + 7 + i, 8);
+						printf("%c", message);
+						i += 8;
+						if (i + 28 + 7 > 29 * 8)
+							break;
+					}
+				}
+			}
+		}
+		printf("\n");
+		tup->lchan = TETRA_LC_DMO_SCH_F;	/* FIXME: Implement LC DMO Channel */
+		break;
+	case DPSAP_SCH_S:
+		/* 396-3 9.1.1 Table 21 */
+		printf(" System code: %s(%2u)", osmo_ubit_dump(type2, 4),
+				bits_to_uint(type2, 4));
+		printf(" PDU type: %s(%u)", osmo_ubit_dump(type2 + 4, 2),
+				bits_to_uint(type2 + 4, 2));
+		printf(" Comm type: %s(%u)", osmo_ubit_dump(type2 + 6, 2),
+				bits_to_uint(type2 + 6, 2));
+		printf(" AB Channel: %s(%u)", osmo_ubit_dump(type2 + 10, 2),
+				bits_to_uint(type2 + 10, 2));
+		printf(" Slot Num: %s(%u)", osmo_ubit_dump(type2 + 12, 2),
+				bits_to_uint(type2 + 12, 2));
+		printf(" FN: %s(%u)", osmo_ubit_dump(type2 + 14, 5),
+				bits_to_uint(type2 + 14, 5));
+		printf(" Encr: %s(%u)", osmo_ubit_dump(type2 + 19, 2),
+				bits_to_uint(type2 + 19, 2));
+		printf("\n");
+
+		/* obtain information from SYNC PDU - 21.4.4.2 */
+		tcd->time.tn = bits_to_uint(type2+12, 2);
+		tcd->time.fn = bits_to_uint(type2+14, 5);
+
+		/* update the PHY layer time */
+		memcpy(&t_phy_state.time, &tcd->time, sizeof(t_phy_state.time));
+
+		tup->lchan = TETRA_LC_DMO_SCH_S;	/* FIXME: Implement LC DMO Channel */
+		break;
+	case DPSAP_SCH_H:
+		/* 396-3 9.1.1 Table 22 */
+		frag_offset = 0;
+		uint8_t scrambling[32];
+
+		printf(" Fill bit: %s(%u)", osmo_ubit_dump(type2 + 10, 1),
+				bits_to_uint(type2 + 10, 1));
+		printf(" Frag flag: %s(%u)", osmo_ubit_dump(type2 + 11, 1),
+				bits_to_uint(type2 + 11, 1));
+
+		if (bits_to_uint(type2 + 11, 1) == 1) {
+			frag_offset = 4;
+			printf(" Num of SCH/F: %s(%2u)", osmo_ubit_dump(type2 + 12, 4),
+					bits_to_uint(type2 + 12, 4));
+		}
+		printf(" Frame countdown: %s(%2u)",
+				osmo_ubit_dump(type2 + 12 + frag_offset, 2),
+				bits_to_uint(type2 + 12 + frag_offset, 2));
+		printf("\n");
+
+		printf(" Dest Addr Type: %s(%2u)",
+				osmo_ubit_dump(type2 + 14 + frag_offset, 2),
+				bits_to_uint(type2 + 14 + frag_offset, 2));
+		printf(" Dest Addr: %s(%2u)",
+				osmo_ubit_dump(type2 + 16 + frag_offset, 24),
+				bits_to_uint(type2 + 16 + frag_offset, 24));
+		printf("\n");
+
+		printf(" Src Addr Type: %s(%2u)",
+				osmo_ubit_dump(type2 + 40 + frag_offset, 2),
+				bits_to_uint(type2 + 40 + frag_offset, 2));
+		printf(" Src addr: %s(%2u)",
+				osmo_ubit_dump(type2 + 42 + frag_offset, 24),
+				bits_to_uint(type2 + 42 + frag_offset, 24));
+		printf("\n");
+		printf(" MNI: %s(%2u)", osmo_ubit_dump(type2 + 66 + frag_offset, 24),
+				bits_to_uint(type2 + 66 + frag_offset, 24));
+		printf(" Message Type: %s(%2u)",
+				osmo_ubit_dump(type2 + 90 + frag_offset, 5),
+				bits_to_uint(type2 + 90 + frag_offset, 5));
+		printf("\n");
+		uint8_t mess_type = bits_to_uint(type2 + 90 + frag_offset, 5);
+
+		memcpy(scrambling, type2 + 66 + frag_offset + 18, 6); /* last 6 of mni */
+		memcpy(scrambling + 6, type2 + 42 + frag_offset, 24); /* src addr */
+		uint32_t scramb_init1 = bits_to_uint(scrambling, 32);
+		scramb_init1 = scramb_init1 | 3; /* last 2 bits have to be 1 */
+
+		printf("scrambling seq: %s %u\n", osmo_ubit_dump(scrambling, 32),
+				scramb_init1);
+		tcd->scramb_init = scramb_init1;
+
+		printf("\n");
+		switch (mess_type) {
+		case 8:
+			printf("DM-SETUP PDU:: Timing flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset, 1));
+			printf(" LCH in frame 3 flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 1, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 1, 1));
+			printf(" Pre-emption flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 2, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 2, 1));
+			printf("\n");
+			printf("Power class: %s(%2u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 3, 3),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 3, 3));
+			printf(" Power control flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 6, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 6, 1));
+			printf(" Dual watch synchronization flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 9, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 9, 1));
+			printf("\n");
+			printf("Two-frequency call flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 10, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 10, 1));
+			printf(" Circuit mode type: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 11, 4),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 11, 4));
+			printf(" Priority level: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 19, 2),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 19, 2));
+			printf("\n");
+			printf("DM-SDU elements:: End-to-end encryption flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21, 1));
+			printf(" Call type flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21 + 1, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21 +1, 1));
+			printf(" External source flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21 + 2, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21 + 2, 1));
+			break;
+		case 9:
+			printf("DM-SETUP PRES PDU:: Power class: %s(%2u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 3, 3),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 3, 3));
+			printf(" Power control flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 6, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 6, 1));
+			printf(" Dual watch synchronization flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 9, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 9, 1));
+			printf("\n");
+			printf("Two-frequency call flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 10, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 10, 1));
+			printf(" Circuit mode type: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 11, 4),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 11, 4));
+			printf(" Priority level: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 19, 2),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 19, 2));
+			printf("\n");
+			printf("DM-SDU elements:: Ent-to-end encryption flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21, 1));
+			printf(" Call type flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 22, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 22, 1));
+			printf(" External source flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 23, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 23, 1));
+			break;
+		case 10:
+			printf("DM-CONNECT PDU:: Circuit mode type: %s(%2u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset, 4),
+					bits_to_uint(type2 + 90 + 5 + frag_offset, 4));
+			break;
+		case 12:
+			printf("DM-CONNECT ACK PDU:: Timing flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset, 1));
+			printf(" LCH in frame 3 flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 1, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 1, 1));
+			printf(" Pre-emption flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 2, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 2, 1));
+			printf("\n");
+			printf("Power class: %s(%2u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 3, 3),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 3, 3));
+			printf(" Power control flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 6, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 6, 1));
+			printf(" Dual watch synchronization flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 9, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 9, 1));
+			printf("\n");
+			printf("Two-frequency call flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 10, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 10, 1));
+			printf(" Circuit mode type: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 11, 4),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 11, 4));
+			printf(" Priority level: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 19, 2),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 19, 2));
+			printf("\n");
+			printf("DM-SDU elements:: End-to-end encryption flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21, 1));
+			printf(" Call type flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21 + 1, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21 +1, 1));
+			printf(" External source flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 21 + 2, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 21 + 2, 1));
+			break;
+		case 22:
+			printf("DM-SDS UDATA PDU:: SDS time remaining: %s(%2u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset, 4),
+					bits_to_uint(type2 + 90 + 5 + frag_offset, 4));
+			printf(" DMSDS transaction type: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 4, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 4, 1));
+			printf(" Priority level: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 4 + 1, 2),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 4 + 1, 2));
+			printf("\n");
+			printf(" FCS flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 4 + 1 + 2, 1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 4 + 1 + 2, 1));
+			printf(" Additional addressing flag: %s(%u)",
+					osmo_ubit_dump(type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1,
+							1),
+					bits_to_uint(type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1,
+							1));
+			printf(" Short Data Type Identifier: %s(%u)",
+					osmo_ubit_dump(
+							type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1 + 1,
+							4),
+					bits_to_uint(
+							type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1 + 1,
+							4));
+			printf("\n");
+			printf(" Length indicator: %s(%u)",
+					osmo_ubit_dump(
+							type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1 + 1
+									+ 4, 11),
+					bits_to_uint(
+							type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1 + 1
+									+ 4, 11));
+
+			tcd->textmessage_length = bits_to_uint(
+					type2 + 90 + 5 + frag_offset + 4 + 1 + 2 + 1 + 1 + 4, 11);
+			break;
+		default:
+			printf("Message type is not implemented");
+			break;
+		}
+		printf("\n");
+		tup->lchan = TETRA_LC_DMO_SCH_H;	/* FIXME: Implement LC DMO Channel */
+		break;
 	default:
 		/* FIXME: do something */
 		break;
@@ -306,4 +632,9 @@
 	upper_mac_prim_recv(&ttp->oph, tms);
 }
 
-
+/* incoming DP-SAP UNITDATA.ind  from PHY into lower MAC */
+void dp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned int len, void *priv)
+{
+	/* call TMO Physical Layer SAP because the code is almost identical */
+	tp_sap_udata_ind(type, bits, len, priv);
+}
diff --git a/src/lower_mac/tetra_scramb.c b/src/lower_mac/tetra_scramb.c
index c83165a..9a7c691 100644
--- a/src/lower_mac/tetra_scramb.c
+++ b/src/lower_mac/tetra_scramb.c
@@ -20,6 +20,7 @@
  *
  */
 
+#include <inttypes.h>
 #include <stdint.h>
 #include <lower_mac/tetra_scramb.h>
 
diff --git a/src/lower_mac/tetra_scramb.h b/src/lower_mac/tetra_scramb.h
index 9729ac2..534563a 100644
--- a/src/lower_mac/tetra_scramb.h
+++ b/src/lower_mac/tetra_scramb.h
@@ -12,8 +12,10 @@
 		* p(k) = 1	for k = -31, -30
  */
 #define SCRAMB_INIT	3
+#define SCRAMB_ZERO	0
 
 uint32_t tetra_scramb_get_init(uint16_t mcc, uint16_t mnc, uint8_t colour);
+uint32_t tetra_scramb_get_init_dmo(uint8_t mni, uint32_t src);
 
 int tetra_scramb_get_bits(uint32_t lfsr_init, uint8_t *out, int len);
 
diff --git a/src/phy/tetra_burst.c b/src/phy/tetra_burst.c
index 62efb72..2406471 100644
--- a/src/phy/tetra_burst.c
+++ b/src/phy/tetra_burst.c
@@ -31,6 +31,7 @@
 #define SB_BLK1_OFFSET	((6+1+40)*DQPSK4_BITS_PER_SYM)
 #define SB_BBK_OFFSET	((6+1+40+60+19)*DQPSK4_BITS_PER_SYM)
 #define SB_BLK2_OFFSET	((6+1+40+60+19+15)*DQPSK4_BITS_PER_SYM)
+#define SB_BLK2_DMO_OFFSET	((6+1+40+60+19)*DQPSK4_BITS_PER_SYM)
 
 #define SB_BLK1_BITS	(60*DQPSK4_BITS_PER_SYM)
 #define SB_BBK_BITS	(15*DQPSK4_BITS_PER_SYM)
@@ -46,6 +47,10 @@
 #define NDB_BLK_BITS	(108*DQPSK4_BITS_PER_SYM)
 #define NDB_BBK_BITS	SB_BBK_BITS
 
+#define DNB_BLK_BITS 	(108*DQPSK4_BITS_PER_SYM)
+
+#define DNB_BLK1_OFFSET ((6+1)*DQPSK4_BITS_PER_SYM)
+#define DNB_BLK2_OFFSET ((6+1+108+11)*DQPSK4_BITS_PER_SYM)
 
 /* 9.4.4.3.1 Frequency Correction Field */
 static const uint8_t f_bits[80] = {
@@ -55,7 +60,12 @@
 	[72] = 1, [73] = 1, [74] = 1, [75] = 1,
 	[76] = 1, [77] = 1, [78] = 1, [79] = 1 };
 
-/* 9.4.4.3.2 Normal Training Sequence */
+/* 9.4.3.3.3 DMO Radio Aspects preambe */
+static const uint8_t dmo_pre1_bits[12] = { 0,0,1,1,0,0,1,0,0,0,1,1 };
+static const uint8_t dmo_pre2_bits[12] = { 1,0,0,1,1,0,1,0,1,0,0,1 };
+static const uint8_t dmo_pre3_bits[12] = { 0,0,0,1,0,1,0,0,0,1,1,1 };
+
+/* 9.4.4.3.2 Normal Training Sequence (first and second are also for DMO - 9.4.3.3.3 */
 static const uint8_t n_bits[22] = { 1,1, 0,1, 0,0, 0,0, 1,1, 1,0, 1,0, 0,1, 1,1, 0,1, 0,0 };
 static const uint8_t p_bits[22] = { 0,1, 1,1, 1,0, 1,0, 0,1, 0,0, 0,0, 1,1, 0,1, 1,1, 1,0 };
 static const uint8_t q_bits[22] = { 1,0, 1,1, 0,1, 1,1, 0,0, 0,0, 0,1, 1,0, 1,0, 1,1, 0,1 };
@@ -66,7 +76,7 @@
 static const uint8_t x_bits[30] = { 1,0, 0,1, 1,1, 0,1, 0,0, 0,0, 1,1, 1,0, 1,0, 0,1, 1,1, 0,1, 0,0, 0,0, 1,1 };
 static const uint8_t X_bits[45] = { 0,1,1,1,0,0,1,1,0,1,0,0,0,0,1,0,0,0,1,1,1,0,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,0 };
 
-/* 9.4.4.3.4 Synchronization training sequence */
+/* 9.4.4.3.4 Synchronization training sequence (also for DMO - 9.4.3.3.4) */
 static const uint8_t y_bits[38] = { 1,1, 0,0, 0,0, 0,1, 1,0, 0,1, 1,1, 0,0, 1,1, 1,0, 1,0, 0,1, 1,1, 0,0, 0,0, 0,1, 1,0, 0,1, 1,1 };
 
 /* 9.4.4.3.5 Tail bits */
@@ -267,11 +277,11 @@
 }
 
 int tetra_find_train_seq(const uint8_t *in, unsigned int end_of_in,
-			 uint32_t mask_of_train_seq, unsigned int *offset)
+			 uint32_t mask_of_train_seq, unsigned int *offset, unsigned int skip)
 {
 	const uint8_t *cur;
 
-	for (cur = in; cur < in + end_of_in; cur++) {
+	for (cur = in+skip; cur < in + end_of_in; cur++) {
 		int remain_len = (in + end_of_in) - cur;
 
 		if (mask_of_train_seq & (1 << TETRA_TRAIN_SYNC) &&
@@ -292,6 +302,7 @@
 			*offset = (cur - in);
 			return TETRA_TRAIN_NORM_2;
 		}
+#if 0	/* not used */
 		if (mask_of_train_seq & (1 << TETRA_TRAIN_NORM_3) &&
 		    remain_len >= sizeof(q_bits) &&
 		    !memcmp(cur, q_bits, sizeof(q_bits))) {
@@ -304,10 +315,43 @@
 			*offset = (cur - in);
 			return TETRA_TRAIN_EXT;
 		}
+#endif
 	}
 	return -1;
 }
 
+int check_tmo_or_dmo(const uint8_t *in, enum tetra_train_seq type)
+{
+	switch (type) {
+	case TETRA_TRAIN_SYNC:
+		/* if it is a DMO sync burst, it should contain preamble P3 */
+		if (!memcmp(in, dmo_pre3_bits, sizeof(dmo_pre3_bits)))
+			return TETRA_TRAIN_SYNC_DMO;
+		else
+			return TETRA_TRAIN_SYNC;
+		break;
+	case TETRA_TRAIN_NORM_1:
+		/* if it is a DMO normal 1 burst, it should contain preamble P1 */
+		if (!memcmp(in, dmo_pre1_bits, sizeof(dmo_pre1_bits)))
+			return TETRA_TRAIN_NORM_1_DMO;
+		else
+			return TETRA_TRAIN_NORM_1;
+		break;
+	case TETRA_TRAIN_NORM_2:
+		/* if it is a DMO normal 2 burst, it should contain preamble P2 */
+		if (!memcmp(in, dmo_pre2_bits, sizeof(dmo_pre2_bits)))
+			return TETRA_TRAIN_NORM_2_DMO;
+		else
+			return TETRA_TRAIN_NORM_2;
+		break;
+	default:
+		/* There aren't any other DMO burst types, so it must be TMO */
+		return type;
+		break;
+	}
+}
+
+/* splits the bursts in relevant blocks (depending on the type) and sends them to the upper layer */
 void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_seq type, void *priv)
 {
 	uint8_t bbk_buf[NDB_BBK_BITS];
@@ -320,6 +364,12 @@
 		tp_sap_udata_ind(TPSAP_T_SB1, burst+SB_BLK1_OFFSET, SB_BLK1_BITS, priv);
 		tp_sap_udata_ind(TPSAP_T_BBK, burst+SB_BBK_OFFSET, SB_BBK_BITS, priv);
 		tp_sap_udata_ind(TPSAP_T_SB2, burst+SB_BLK2_OFFSET, SB_BLK2_BITS, priv);
+		break;
+	case TETRA_TRAIN_SYNC_DMO:
+		/* Split SB1 and SB2 */
+		/* send two parts of the burst via TP-SAP into lower MAC */
+		dp_sap_udata_ind(DPSAP_SCH_S, burst+SB_BLK1_OFFSET, SB_BLK1_BITS, priv);
+		dp_sap_udata_ind(DPSAP_SCH_H, burst+SB_BLK2_DMO_OFFSET, SB_BLK2_BITS, priv);
 		break;
 	case TETRA_TRAIN_NORM_2:
 		/* re-combine the broadcast block */
@@ -341,5 +391,16 @@
 		tp_sap_udata_ind(TPSAP_T_BBK, bbk_buf, NDB_BBK_BITS, priv);
 		tp_sap_udata_ind(TPSAP_T_SCH_F, ndbf_buf, 2*NDB_BLK_BITS, priv);
 		break;
+	case TETRA_TRAIN_NORM_2_DMO:
+		/* TODO: send parts of the burst via TP-SAP into lower MAC */
+		fprintf(stderr, "#### TETRA_TRAIN_NORM_2_DMO bursts are not implemented\n");
+		break;
+	case TETRA_TRAIN_NORM_1_DMO:
+		/* re-combine the two parts */
+		memcpy(ndbf_buf, burst+DNB_BLK1_OFFSET, DNB_BLK_BITS);
+		memcpy(ndbf_buf+DNB_BLK_BITS, burst+DNB_BLK2_OFFSET, DNB_BLK_BITS);
+		/* send part of the burst via TP-SAP into lower MAC */
+		dp_sap_udata_ind(DPSAP_SCH_F, ndbf_buf, DNB_BLK_BITS*2, priv);
+		break;
 	}
 }
diff --git a/src/phy/tetra_burst_sync.c b/src/phy/tetra_burst_sync.c
index e363c74..9cf3710 100644
--- a/src/phy/tetra_burst_sync.c
+++ b/src/phy/tetra_burst_sync.c
@@ -51,7 +51,7 @@
 }
 
 /* input a raw bitstream into the tetra burst synchronizaer */
-int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len)
+int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len, int *scounter)
 {
 	int rc;
 	unsigned int train_seq_offs;
@@ -74,11 +74,13 @@
 		DEBUGP("-> trying to find training sequence between bit %u and %u\n",
 			trs->bitbuf_start_bitnum, trs->bits_in_buf);
 		rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf,
-					  (1 << TETRA_TRAIN_SYNC), &train_seq_offs);
+					  (1 << TETRA_TRAIN_SYNC), &train_seq_offs, 0);
 		if (rc < 0)
 			return rc;
 		printf("found SYNC training sequence in bit #%u\n", train_seq_offs);
 		trs->state = RX_S_KNOW_FSTART;
+		/* for DMO image that the 34 bits guard at the beginning of a burst */
+		/* belongs to the previous burst */
 		trs->next_frame_start_bitnum = trs->bitbuf_start_bitnum + train_seq_offs + 296;
 #if 0
 		if (train_seq_offs < 214) {
@@ -112,7 +114,7 @@
 		} else {
 			/* we have successfully received (at least) one frame */
 			tetra_tdma_time_add_tn(&t_phy_state.time, 1);
-			printf("\nBURST");
+			printf("\n\nBURST: ");
 			DEBUGP(": %s", osmo_ubit_dump(trs->bitbuf, TETRA_BITS_PER_TS));
 			printf("\n");
 
@@ -120,31 +122,58 @@
 			sprintf(tmpstr,"TETMON_begin FUNC:BURST RX:%i TETMON_end",tetra_hack_rxid);
 			sendto(tetra_hack_live_socket, (char *)&tmpstr, 128, 0, (struct sockaddr *)&tetra_hack_live_sockaddr, tetra_hack_socklen);
 
-
+			/* skip the first 200 bits, because normally the first training sequence can be found in bit 214 */
 			rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf,
 						  (1 << TETRA_TRAIN_NORM_1)|
 						  (1 << TETRA_TRAIN_NORM_2)|
-						  (1 << TETRA_TRAIN_SYNC), &train_seq_offs);
+						  (1 << TETRA_TRAIN_SYNC), &train_seq_offs, 200);
 			switch (rc) {
 			case TETRA_TRAIN_SYNC:
-				if (train_seq_offs == 214)
-					tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
-				else {
-					fprintf(stderr, "#### SYNC burst at offset %u?!?\n", train_seq_offs);
+				if (train_seq_offs == 214) {
+					*scounter = 0;
+					rc = check_tmo_or_dmo(trs->bitbuf, rc);
+					if (rc == TETRA_TRAIN_SYNC) {
+						printf("TETRA_TRAIN_SYNC_TMO\n");
+						tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, TETRA_TRAIN_SYNC, trs->burst_cb_priv);
+					} else {
+						printf("TETRA_TRAIN_SYNC_DMO\n");
+						tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, TETRA_TRAIN_SYNC_DMO, trs->burst_cb_priv);
+					}
+				} else {
+					fprintf(stderr, "\n#### SYNC burst at offset %u?!?\n", train_seq_offs);
 					trs->state = RX_S_UNLOCKED;
 				}
 				break;
-			case TETRA_TRAIN_NORM_1:
+			case TETRA_TRAIN_NORM_1: /* fall through */
 			case TETRA_TRAIN_NORM_2:
-			case TETRA_TRAIN_NORM_3:
-				if (train_seq_offs == 244)
+				if (train_seq_offs == 230) {
+					*scounter = 0;
+					rc = check_tmo_or_dmo(trs->bitbuf, rc);
+					if (rc == TETRA_TRAIN_NORM_1_DMO || rc == TETRA_TRAIN_NORM_2_DMO) {
+						printf("TETRA_TRAIN_NORM_%u_DMO\n", rc);
+						tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
+						break;
+					} else {
+						fprintf(stderr, "#### TRAIN NORM %u DMO burst at offset %u?!?\n", rc, train_seq_offs);
+						trs->state = RX_S_UNLOCKED;
+					}
+				} else if (train_seq_offs == 244) {
+					*scounter = 0;
+					printf("TETRA_TRAIN_NORM_%u\n", rc);
 					tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
-				else
-					fprintf(stderr, "#### SYNC burst at offset %u?!?\n", train_seq_offs);
+				} else {
+					fprintf(stderr, "\n#### TRAIN NORM %u burst at offset %u?!?\n", rc, train_seq_offs);
+					trs->state = RX_S_UNLOCKED;
+				}
 				break;
 			default:
-				fprintf(stderr, "#### could not find successive burst training sequence\n");
-				trs->state = RX_S_UNLOCKED;
+				(*scounter)++;
+				if (*scounter >= 4) {
+					fprintf(stderr, "#### could not find successive burst training sequence\n");
+					trs->state = RX_S_UNLOCKED;
+				} else {
+					fprintf(stderr, "#### slot is empty, checking next %d slots before searching a new synchronization burst\n", 4-(*scounter));
+				}
 				break;
 			}
 
diff --git a/src/phy/tetra_burst_sync.h b/src/phy/tetra_burst_sync.h
index 7862461..11f6224 100644
--- a/src/phy/tetra_burst_sync.h
+++ b/src/phy/tetra_burst_sync.h
@@ -21,6 +21,6 @@
 
 
 /* input a raw bitstream into the tetra burst synchronizaer */
-int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len);
+int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len, int *scounter);
 
 #endif /* TETRA_BURST_SYNC_H */
diff --git a/src/tetra-rx.c b/src/tetra-rx.c
index 42045b5..e4b88ad 100644
--- a/src/tetra-rx.c
+++ b/src/tetra-rx.c
@@ -117,6 +117,7 @@
 	float filter_goal=0;
 	int ccounter=0;
 	char tmpstr2[64];
+	int scounter = 0;	/* slot counter */-
 
 	tetra_hack_reassemble_fragments=0;
 	tetra_hack_all_sds_as_text=0;
@@ -260,7 +261,7 @@
 				break;
 			}
 		}
-		tetra_burst_sync_in(trs, buf, len);
+		tetra_burst_sync_in(trs, buf, len, &scounter);
 
 		if (accept_float) {	
 			ccounter++;
diff --git a/src/tetra_common.h b/src/tetra_common.h
index 98327ba..2ba110b 100644
--- a/src/tetra_common.h
+++ b/src/tetra_common.h
@@ -36,6 +36,10 @@
 	TETRA_LC_BSCH,
 	TETRA_LC_BNCH,
 
+	TETRA_LC_DMO_SCH_S,
+	TETRA_LC_DMO_SCH_H,
+	TETRA_LC_DMO_SCH_F,
+
 	/* FIXME: QAM */
 };
 uint32_t bits_to_uint(const uint8_t *bits, unsigned int len);
diff --git a/src/tetra_gsmtap.c b/src/tetra_gsmtap.c
index f575c20..df6b8fd 100644
--- a/src/tetra_gsmtap.c
+++ b/src/tetra_gsmtap.c
@@ -25,6 +25,9 @@
 	[TETRA_LC_TCH]		= GSMTAP_TETRA_TCH_F,
 	[TETRA_LC_BSCH]		= GSMTAP_TETRA_BSCH,
 	[TETRA_LC_BNCH]		= GSMTAP_TETRA_BNCH,
+	[TETRA_LC_DMO_SCH_S]	= GSMTAP_TETRA_DMO_SCH_S,
+	[TETRA_LC_DMO_SCH_H]	= GSMTAP_TETRA_DMO_SCH_H,
+	[TETRA_LC_DMO_SCH_F]	= GSMTAP_TETRA_DMO_SCH_F,
 };
 
 

-- 
To view, visit https://gerrit.osmocom.org/2817
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ifa5521d7313595384e74dd790a56550755b93fe9
Gerrit-PatchSet: 2
Gerrit-Project: osmo-tetra
Gerrit-Branch: laforge/sq5bpf-rebase-20161218
Gerrit-Owner: allesklar2 <jjuergens at seemoo.tu-darmstadt.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>
Gerrit-Reviewer: allesklar2 <jjuergens at seemoo.tu-darmstadt.de>



More information about the gerrit-log mailing list