mirror of https://gerrit.osmocom.org/osmo-tetra
adding dmo support
Change-Id: Ifa5521d7313595384e74dd790a56550755b93fe9
This commit is contained in:
parent
2928504e94
commit
69da8c5e61
2
AUTHORS
2
AUTHORS
|
@ -1,3 +1,5 @@
|
|||
Harald Welte <laforge@gnumonks.org>
|
||||
Sylvain Munaut <tnt@246tNt.com>
|
||||
Holger Hans Peter Freyther <holger@freyther.de>
|
||||
Jan-Pascal Kwiotek <info@igis.biz>
|
||||
Jannik Jürgens <jjuergens@seemoo.tu-darmstadt.de>
|
||||
|
|
|
@ -49,6 +49,11 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned
|
|||
{
|
||||
}
|
||||
|
||||
/* 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];
|
||||
|
|
|
@ -103,6 +103,38 @@ static const struct tetra_blk_param tetra_blk_param[] = {
|
|||
.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_cell_data {
|
|||
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 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned
|
|||
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 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned
|
|||
|
||||
/* 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 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned
|
|||
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 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned
|
|||
}
|
||||
/* 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 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 @@ static const uint8_t f_bits[80] = {
|
|||
[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 P_bits[33] = { 1,0,1, 0,1,1, 1,1,1, 1,0,1, 0,1,0, 1,0,1, 1,
|
|||
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 build_norm_c_d_burst(uint8_t *buf, const uint8_t *bkn1, const uint8_t *bb, c
|
|||
}
|
||||
|
||||
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 @@ int tetra_find_train_seq(const uint8_t *in, unsigned int end_of_in,
|
|||
*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 @@ int tetra_find_train_seq(const uint8_t *in, unsigned int end_of_in,
|
|||
*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 @@ void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_
|
|||
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 @@ void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ static void make_bitbuf_space(struct tetra_rx_state *trs, unsigned int len)
|
|||
}
|
||||
|
||||
/* 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 @@ int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int
|
|||
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 @@ int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int
|
|||
} 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 @@ int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,6 @@ struct tetra_rx_state {
|
|||
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -117,6 +117,7 @@ int main(int argc, char **argv)
|
|||
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 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
}
|
||||
tetra_burst_sync_in(trs, buf, len);
|
||||
tetra_burst_sync_in(trs, buf, len, &scounter);
|
||||
|
||||
if (accept_float) {
|
||||
ccounter++;
|
||||
|
|
|
@ -36,6 +36,10 @@ enum tetra_log_chan {
|
|||
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);
|
||||
|
|
|
@ -25,6 +25,9 @@ static const uint8_t lchan2gsmtap[] = {
|
|||
[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,
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue