Review at  https://gerrit.osmocom.org/2817

adding dmo support

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, 465 insertions(+), 26 deletions(-)


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

diff --git a/AUTHORS b/AUTHORS
index a0c987b..7702664 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,5 @@
 Harald Welte <[email protected]>
 Sylvain Munaut <[email protected]>
 Holger Hans Peter Freyther <[email protected]>
+Jan-Pascal Kwiotek <[email protected]>
+Jannik Jürgens <[email protected]>
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..040de7b 100644
--- a/src/lower_mac/tetra_lower_mac.c
+++ b/src/lower_mac/tetra_lower_mac.c
@@ -103,6 +103,38 @@
                .type2_bits     = 30,
                .type1_bits     = 14,
        },
+       [DPSAP_SCH_S] = {               //DMO Synchronization Burst Block 1
+               .name           = "SCH/S",
+               .type345_bits   = 120,
+               .type2_bits     = 80,
+               .type1_bits     = 60,
+               .interleave_a   = 11,
+               .have_crc16     = 1,
+       },
+       [DPSAP_SCH_H] = {               //DMO Synchronization Burst Block 2
+               .name           = "SCH/H",
+               .type345_bits   = 216,
+               .type2_bits     = 144,
+               .type1_bits     = 124,
+               .interleave_a   = 101,
+               .have_crc16     = 1,
+       },
+       [DPSAP_SCH_F] = {               //DMO Normal Burst Block 1+2
+               .name           = "SCH/F",
+               .type345_bits   = 432,
+               .type2_bits     = 288,
+               .type1_bits     = 268,
+               .interleave_a   = 103,
+               .have_crc16     = 1,
+       },
+       [DPSAP_STCH] = {                //DMO Normal Burst with Slot Flag
+               .name           = "STCH",
+               .type345_bits   = 216,
+               .type2_bits     = 144,
+               .type1_bits     = 124,
+               .interleave_a   = 101,
+               .have_crc16     = 1,
+       },
 };
 
 struct tetra_cell_data {
@@ -112,6 +144,7 @@
        struct tetra_tdma_time time;
 
        uint32_t scramb_init;
+       uint32_t textmessage_length;
 };
 
 static struct tetra_cell_data _tcd, *tcd = &_tcd;
@@ -151,6 +184,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 +215,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 +269,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 +330,295 @@
                }
                        /* 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");
+               //printBits(32,tcd->scramb_init);
+               tup->lchan = TETRA_LC_DMO_SCH_H;        /* FIXME: Implement LC 
DMO Channel */
+               break;
        default:
                /* FIXME: do something */
                break;
@@ -306,4 +629,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..f35123b 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>
 
@@ -30,6 +31,9 @@
 #define GL(x)          (1<<(x-1))
 #define GALOIS_LFSR    
(GL(32)|GL(26)|GL(23)|GL(22)|GL(16)|GL(12)|GL(11)|GL(10)|GL(8)|GL(7)|GL(5)|GL(4)|GL(2)|GL(1))
 
+#define SCRAMB_INIT    3
+#define SCRAMB_ZERO    0
+
 #if 1
 static uint8_t next_lfsr_bit(uint32_t *lf)
 {
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..8654b4c 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..5acd0ba 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_2:
-                       case TETRA_TRAIN_NORM_3:
-                               if (train_seq_offs == 244)
+                       case (TETRA_TRAIN_NORM_1): /* fall through */
+                       case (TETRA_TRAIN_NORM_2):
+                               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..2387b4d 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: newchange
Gerrit-Change-Id: Ifa5521d7313595384e74dd790a56550755b93fe9
Gerrit-PatchSet: 1
Gerrit-Project: osmo-tetra
Gerrit-Branch: laforge/sq5bpf-rebase-20161218
Gerrit-Owner: allesklar2 <[email protected]>

Reply via email to