diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-02-15 13:29:29 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-09-22 16:41:26 +0200 |
commit | 78b2080027d398c7242ae6e180b462e32f57a786 (patch) | |
tree | c4b1dba796547d4241d5ff13f75f2b9e629a446c /src | |
parent | 9de67ca9621deea3283b9f9c2bab99287a110e45 (diff) |
TRX: PDTCH (GPRS) works now
Detection and transcoding of all four coding schemes are supported.
Diffstat (limited to 'src')
-rw-r--r-- | src/osmo-bts-trx/pxxch.c | 140 | ||||
-rw-r--r-- | src/osmo-bts-trx/pxxch.h | 2 | ||||
-rw-r--r-- | src/osmo-bts-trx/scheduler.c | 117 |
3 files changed, 140 insertions, 119 deletions
diff --git a/src/osmo-bts-trx/pxxch.c b/src/osmo-bts-trx/pxxch.c index 17a7c947..07d011a9 100644 --- a/src/osmo-bts-trx/pxxch.c +++ b/src/osmo-bts-trx/pxxch.c @@ -6,6 +6,7 @@ #include <stdio.h> #include <stdint.h> +#include <stdlib.h> #include <string.h> #include <osmocom/core/bits.h> @@ -31,7 +32,7 @@ const struct osmo_crc64gen_code pxxch_crc40 = { /* - * GSM PDTCH CS-2, CS-3 parity + * GSM PDTCH CS-2, CS-3, CS-4 parity * * g(x) = x^16 + x^12 + x^5 + 1 */ @@ -189,35 +190,53 @@ pxxch_burst_map(ubit_t *iB, ubit_t *eB, ubit_t *hl, ubit_t *hn) eB[58] = *hn; } -static ubit_t pdtch_hl_hn[4][8] = { +static ubit_t pdtch_hl_hn_ubit[4][8] = { { 1,1, 1,1, 1,1, 1,1 }, { 1,1, 0,0, 1,0, 0,0 }, { 0,0, 1,0, 0,0, 0,1 }, { 0,0, 0,1, 0,1, 1,0 }, }; +static sbit_t pdtch_hl_hn_sbit[4][8] = { + { -127,-127, -127,-127, -127,-127, -127,-127 }, + { -127,-127, 127, 127, -127, 127, 127, 127 }, + { 127, 127, -127, 127, 127, 127, 127,-127 }, + { 127, 127, 127,-127, 127,-127, -127, 127 }, +}; + static ubit_t usf2six[8][6] = { { 0,0,0, 0,0,0 }, - { 0,0,1, 0,1,1 }, - { 0,1,0, 1,1,0 }, - { 0,1,1, 1,0,1 }, { 1,0,0, 1,0,1 }, - { 1,0,1, 1,1,0 }, + { 0,1,0, 1,1,0 }, { 1,1,0, 0,1,1 }, + { 0,0,1, 0,1,1 }, + { 1,0,1, 1,1,0 }, + { 0,1,1, 1,0,1 }, { 1,1,1, 0,0,0 }, }; -static ubit_t usf2twelve[8][12] = { +static ubit_t usf2twelve_ubit[8][12] = { { 0,0,0, 0,0,0, 0,0,0, 0,0,0 }, - { 0,0,0, 0,1,1, 0,1,1, 1,0,1 }, - { 0,0,1, 1,0,1, 1,1,0, 1,1,0 }, - { 0,0,1, 1,1,0, 1,0,1, 0,1,1 }, { 1,1,0, 1,0,0, 0,0,1, 0,1,1 }, - { 1,1,0, 1,1,1, 0,1,0, 1,1,0 }, + { 0,0,1, 1,0,1, 1,1,0, 1,1,0 }, { 1,1,1, 0,0,1, 1,1,1, 1,0,1 }, + { 0,0,0, 0,1,1, 0,1,1, 1,0,1 }, + { 1,1,0, 1,1,1, 0,1,0, 1,1,0 }, + { 0,0,1, 1,1,0, 1,0,1, 0,1,1 }, { 1,1,1, 0,1,0, 1,0,0, 0,0,0 }, }; +static sbit_t usf2twelve_sbit[8][12] = { + { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, + { -127,-127, 127, -127, 127, 127, 127, 127,-127, 127,-127,-127 }, + { 127, 127,-127, -127, 127,-127, -127,-127, 127, -127,-127, 127 }, + { -127,-127,-127, 127, 127,-127, -127,-127,-127, -127, 127,-127 }, + { 127, 127, 127, 127,-127,-127, 127,-127,-127, -127, 127,-127 }, + { -127,-127, 127, -127,-127,-127, 127,-127, 127, -127,-127, 127 }, + { 127, 127,-127, -127,-127, 127, -127, 127,-127, 127,-127,-127 }, + { -127,-127,-127, 127,-127, 127, -127, 127, 127, 127, 127, 127 }, +}; + static uint8_t puncture_cs2[588] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, @@ -267,23 +286,23 @@ static uint8_t puncture_cs3[676] = { }; int -pdch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p) +pdtch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p) { sbit_t iB[456], cB[676], hl_hn[8]; ubit_t conv[456]; - int i, j, k, rv, best, cs, usf; + int i, j, k, rv, best = 0, cs = 0, usf = 0; /* make GCC happy */ for (i=0; i<4; i++) pxxch_burst_unmap(&iB[i * 114], &bursts[i * 116], hl_hn + i*2, hl_hn + i*2 + 1); - for (i=0, best=0, cs=1; i<4; j++) { - for (j=0, k=0; j<4; j++) { - if (pdtch_hl_hn[i][j] == hl_hn[j]) - k++; - } - if (k > best) + for (i=0; i<4; i++) { + for (j=0, k=0; j<8; j++) + k += abs(((int)pdtch_hl_hn_sbit[i][j]) - ((int)hl_hn[j])); + if (i == 0 || k < best) { + best = k; cs = i+1; + } } pxxch_deinterleave(cB, iB); @@ -301,7 +320,7 @@ pdch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p) return 23; case 2: - for (i=587, j=455; i>=0; i++) + for (i=587, j=455; i>=0; i--) if (!puncture_cs2[i]) cB[i] = cB[j--]; else @@ -309,31 +328,31 @@ pdch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p) osmo_conv_decode(&conv_cs2, cB, conv); - for (i=0, best=0, usf=0; i<8; j++) { - for (j=0, k=0; j<6; j++) { - if (usf2six[i][j] == conv[j]) - k++; - } - if (k > best) + for (i=0; i<8; i++) { + for (j=0, k=0; j<6; j++) + k += abs(((int)usf2six[i][j]) - ((int)conv[j])); + if (i == 0 || k < best) { + best = k; usf = i; + } } - conv[3] = (usf >> 2) & 1; + conv[3] = usf & 1; conv[4] = (usf >> 1) & 1; - conv[5] = usf & 1; + conv[5] = (usf >> 2) & 1; if (usf_p) *usf_p = usf; - rv = osmo_crc64gen_check_bits(&pxxch_crc40, conv+3, 271, + rv = osmo_crc16gen_check_bits(&pdtch_crc16, conv+3, 271, conv+3+271); if (rv) return -1; - osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 271, 1); + osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 271, 1); return 34; case 3: - for (i=675, j=455; i>=0; i++) + for (i=675, j=455; i>=0; i--) if (!puncture_cs3[i]) cB[i] = cB[j--]; else @@ -341,54 +360,55 @@ pdch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p) osmo_conv_decode(&conv_cs3, cB, conv); - for (i=0, best=0, usf=0; i<8; j++) { - for (j=0, k=0; j<6; j++) { - if (usf2six[i][j] == conv[j]) - k++; - } - if (k > best) + for (i=0; i<8; i++) { + for (j=0, k=0; j<6; j++) + k += abs(((int)usf2six[i][j]) - ((int)conv[j])); + if (i == 0 || k < best) { + best = k; usf = i; + } } - conv[3] = (usf >> 2) & 1; + conv[3] = usf & 1; conv[4] = (usf >> 1) & 1; - conv[5] = usf & 1; + conv[5] = (usf >> 2) & 1; if (usf_p) *usf_p = usf; - rv = osmo_crc64gen_check_bits(&pxxch_crc40, conv+3, 315, + rv = osmo_crc16gen_check_bits(&pdtch_crc16, conv+3, 315, conv+3+315); if (rv) return -1; - osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 315, 1); + osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 315, 1); return 40; case 4: - for (i=0; i<456;i++) + for (i=12; i<456;i++) conv[i] = (cB[i] < 0) ? 1:0; - for (i=0, best=0, usf=0; i<8; j++) { - for (j=0, k=0; j<12; j++) { - if (usf2twelve[i][j] == conv[j]) - k++; - } - if (k > best) + for (i=0; i<8; i++) { + for (j=0, k=0; j<12; j++) + k += abs(((int)usf2twelve_sbit[i][j]) - + ((int)cB[j])); + if (i == 0 || k < best) { + best = k; usf = i; + } } - conv[9] = (usf >> 2) & 1; + conv[9] = usf & 1; conv[10] = (usf >> 1) & 1; - conv[11] = usf & 1; + conv[11] = (usf >> 2) & 1; if (usf_p) *usf_p = usf; - rv = osmo_crc64gen_check_bits(&pxxch_crc40, conv+9, 431, + rv = osmo_crc16gen_check_bits(&pdtch_crc16, conv+9, 431, conv+9+431); if (rv) return -1; - osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 431, 1); + osmo_ubit2pbit_ext(l2_data, 0, conv, 9, 431, 1); return 54; } @@ -411,12 +431,12 @@ pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len) osmo_conv_encode(&conv_cs1, conv, cB); - hl_hn = pdtch_hl_hn[0]; + hl_hn = pdtch_hl_hn_ubit[0]; break; case 34: osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 271, 1); - usf = (conv[3] << 2) | (conv[4] << 1) | conv[5]; + usf = l2_data[0] & 0x7; osmo_crc16gen_set_bits(&pdtch_crc16, conv+3, 271, conv+3+271); @@ -428,12 +448,12 @@ pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len) if (!puncture_cs2[i]) cB[j++] = cB[i]; - hl_hn = pdtch_hl_hn[1]; + hl_hn = pdtch_hl_hn_ubit[1]; break; case 40: osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 315, 1); - usf = (conv[3] << 2) | (conv[4] << 1) | conv[5]; + usf = l2_data[0] & 0x7; osmo_crc16gen_set_bits(&pdtch_crc16, conv+3, 315, conv+3+315); @@ -445,18 +465,18 @@ pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len) if (!puncture_cs3[i]) cB[j++] = cB[i]; - hl_hn = pdtch_hl_hn[2]; + hl_hn = pdtch_hl_hn_ubit[2]; break; case 54: osmo_pbit2ubit_ext(cB, 9, l2_data, 0, 431, 1); - usf = (cB[9] << 2) | (cB[10] << 1) | conv[11]; + usf = l2_data[0] & 0x7; osmo_crc16gen_set_bits(&pdtch_crc16, cB+9, 431, cB+9+431); - memcpy(cB, usf2twelve[usf], 12); + memcpy(cB, usf2twelve_ubit[usf], 12); - hl_hn = pdtch_hl_hn[3]; + hl_hn = pdtch_hl_hn_ubit[3]; break; default: diff --git a/src/osmo-bts-trx/pxxch.h b/src/osmo-bts-trx/pxxch.h index 313fbf59..990bd36d 100644 --- a/src/osmo-bts-trx/pxxch.h +++ b/src/osmo-bts-trx/pxxch.h @@ -1,7 +1,7 @@ #ifndef _PXXCH_H #define _PXXCH_H -int pdch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p); +int pdtch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p); int pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len); #endif /* _PXXCH_H */ diff --git a/src/osmo-bts-trx/scheduler.c b/src/osmo-bts-trx/scheduler.c index 629f8788..f44df519 100644 --- a/src/osmo-bts-trx/scheduler.c +++ b/src/osmo-bts-trx/scheduler.c @@ -138,6 +138,7 @@ static const ubit_t sch_train[64] = { */ struct trx_chan_desc { + int pdch; enum trx_chan_type chan; uint8_t chan_nr; uint8_t link_id; @@ -148,44 +149,44 @@ struct trx_chan_desc { int auto_active; }; struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = { - { TRXC_IDLE, 0, 0, "IDLE", NULL, tx_idle_fn, NULL, 1 }, - { TRXC_FCCH, 0, 0, "FCCH", NULL, tx_fcch_fn, NULL, 1 }, - { TRXC_SCH, 0, 0, "SCH", NULL, tx_sch_fn, NULL, 1 }, - { TRXC_BCCH, 0x80, 0x00, "BCCH", rts_data_fn, tx_data_fn, NULL, 1 }, - { TRXC_RACH, 0x88, 0x00, "RACH", NULL, NULL, rx_rach_fn, 1 }, - { TRXC_CCCH, 0x90, 0x00, "CCCH", rts_data_fn, tx_data_fn, NULL, 1 }, - { TRXC_TCHF, 0x08, 0x00, "TCH/F", rts_tch_fn, tx_tchf_fn, rx_tchf_fn, 0 }, - { TRXC_TCHH_0, 0x10, 0x00, "TCH/H(0)", rts_tch_fn, tx_tchh_fn, rx_tchh_fn, 0 }, - { TRXC_TCHH_1, 0x18, 0x00, "TCH/H(1)", rts_tch_fn, tx_tchh_fn, rx_tchh_fn, 0 }, - { TRXC_SDCCH4_0, 0x20, 0x00, "SDCCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH4_1, 0x28, 0x00, "SDCCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH4_2, 0x30, 0x00, "SDCCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH4_3, 0x38, 0x00, "SDCCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_0, 0x40, 0x00, "SDCCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_1, 0x48, 0x00, "SDCCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_2, 0x50, 0x00, "SDCCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_3, 0x58, 0x00, "SDCCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_4, 0x60, 0x00, "SDCCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_5, 0x68, 0x00, "SDCCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_6, 0x70, 0x00, "SDCCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SDCCH8_7, 0x78, 0x00, "SDCCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCHTF, 0x08, 0x40, "SACCH/TF", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCHTH_0, 0x10, 0x40, "SACCH/TH(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCHTH_1, 0x18, 0x40, "SACCH/TH(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH4_0, 0x20, 0x40, "SACCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH4_1, 0x28, 0x40, "SACCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH4_2, 0x30, 0x40, "SACCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH4_3, 0x38, 0x40, "SACCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_0, 0x40, 0x40, "SACCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_1, 0x48, 0x40, "SACCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_2, 0x50, 0x40, "SACCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_3, 0x58, 0x40, "SACCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_4, 0x60, 0x40, "SACCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_5, 0x68, 0x40, "SACCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_6, 0x70, 0x40, "SACCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_SACCH8_7, 0x68, 0x40, "SACCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, - { TRXC_PDTCH, 0x08, 0x00, "PDTCH", rts_data_fn, tx_pdtch_fn, rx_pdtch_fn, 0 }, - { TRXC_PTCCH, 0x08, 0x00, "PTCCH", rts_data_fn, tx_pdtch_fn, rx_pdtch_fn, 0 }, + { 0, TRXC_IDLE, 0, 0, "IDLE", NULL, tx_idle_fn, NULL, 1 }, + { 0, TRXC_FCCH, 0, 0, "FCCH", NULL, tx_fcch_fn, NULL, 1 }, + { 0, TRXC_SCH, 0, 0, "SCH", NULL, tx_sch_fn, NULL, 1 }, + { 0, TRXC_BCCH, 0x80, 0x00, "BCCH", rts_data_fn, tx_data_fn, NULL, 1 }, + { 0, TRXC_RACH, 0x88, 0x00, "RACH", NULL, NULL, rx_rach_fn, 1 }, + { 0, TRXC_CCCH, 0x90, 0x00, "CCCH", rts_data_fn, tx_data_fn, NULL, 1 }, + { 0, TRXC_TCHF, 0x08, 0x00, "TCH/F", rts_tch_fn, tx_tchf_fn, rx_tchf_fn, 0 }, + { 0, TRXC_TCHH_0, 0x10, 0x00, "TCH/H(0)", rts_tch_fn, tx_tchh_fn, rx_tchh_fn, 0 }, + { 0, TRXC_TCHH_1, 0x18, 0x00, "TCH/H(1)", rts_tch_fn, tx_tchh_fn, rx_tchh_fn, 0 }, + { 0, TRXC_SDCCH4_0, 0x20, 0x00, "SDCCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH4_1, 0x28, 0x00, "SDCCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH4_2, 0x30, 0x00, "SDCCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH4_3, 0x38, 0x00, "SDCCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_0, 0x40, 0x00, "SDCCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_1, 0x48, 0x00, "SDCCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_2, 0x50, 0x00, "SDCCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_3, 0x58, 0x00, "SDCCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_4, 0x60, 0x00, "SDCCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_5, 0x68, 0x00, "SDCCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_6, 0x70, 0x00, "SDCCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SDCCH8_7, 0x78, 0x00, "SDCCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCHTF, 0x08, 0x40, "SACCH/TF", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCHTH_0, 0x10, 0x40, "SACCH/TH(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCHTH_1, 0x18, 0x40, "SACCH/TH(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH4_0, 0x20, 0x40, "SACCH/4(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH4_1, 0x28, 0x40, "SACCH/4(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH4_2, 0x30, 0x40, "SACCH/4(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH4_3, 0x38, 0x40, "SACCH/4(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_0, 0x40, 0x40, "SACCH/8(0)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_1, 0x48, 0x40, "SACCH/8(1)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_2, 0x50, 0x40, "SACCH/8(2)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_3, 0x58, 0x40, "SACCH/8(3)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_4, 0x60, 0x40, "SACCH/8(4)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_5, 0x68, 0x40, "SACCH/8(5)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_6, 0x70, 0x40, "SACCH/8(6)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 0, TRXC_SACCH8_7, 0x68, 0x40, "SACCH/8(7)", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, + { 1, TRXC_PDTCH, 0x08, 0x00, "PDTCH", rts_data_fn, tx_pdtch_fn, rx_pdtch_fn, 0 }, + { 1, TRXC_PTCCH, 0x08, 0x00, "PTCCH", rts_data_fn, tx_data_fn, rx_data_fn, 0 }, }; @@ -926,7 +927,7 @@ static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, return -ENOMEM; } - /* store frame number of first burst */ + /* clear burst & store frame number of first burst */ if (bid == 0) { memset(*bursts_p, 0, 464); *mask = 0x0; @@ -980,7 +981,6 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, { struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan]; sbit_t *burst, **bursts_p = &chan_state->ul_bursts; - uint32_t *first_fn = &chan_state->ul_first_fn; uint8_t *mask = &chan_state->ul_mask; uint8_t l2[54+1]; int rc; @@ -995,11 +995,10 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, return -ENOMEM; } - /* store frame number of first burst */ + /* clear burst */ if (bid == 0) { memset(*bursts_p, 0, 464); *mask = 0x0; - *first_fn = fn; } /* update mask */ @@ -1018,29 +1017,26 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, /* check for complete set of bursts */ if ((*mask & 0xf) != 0xf) { - LOGP(DL1C, LOGL_NOTICE, "Received incomplete PDTCH block at " - "fn=%u (%u/%u) for %s\n", *first_fn, - (*first_fn) % l1h->mf_period[tn], l1h->mf_period[tn], + LOGP(DL1C, LOGL_NOTICE, "Received incomplete PDTCH block " + "ending at fn=%u (%u/%u) for %s\n", fn, + fn % l1h->mf_period[tn], l1h->mf_period[tn], trx_chan_desc[chan].name); - /* we require first burst to have correct FN */ - if (!(*mask & 0x1)) { - *mask = 0x0; - return 0; - } } *mask = 0x0; /* decode */ - rc = pdch_decode(l2 + 1, *bursts_p, NULL); + rc = pdtch_decode(l2 + 1, *bursts_p, NULL); if (rc <= 0) { - LOGP(DL1C, LOGL_NOTICE, "Received bad PDTCH block at fn=%u for " - "%s\n", *first_fn, trx_chan_desc[chan].name); - l2[0] = 0; /* bad frame */ - rc = 0; - } else - l2[0] = 7; /* valid frame */ + LOGP(DL1C, LOGL_NOTICE, "Received bad PDTCH block ending at " + "fn=%u (%u/%u) for %s\n", fn, fn % l1h->mf_period[tn], + l1h->mf_period[tn], trx_chan_desc[chan].name); + return 0; + } - return compose_ph_data_ind(l1h, tn, *first_fn, chan, l2, rc + 1); + l2[0] = 7; /* valid frame */ + + return compose_ph_data_ind(l1h, tn, (fn + 2715648 -3) % 2715648, chan, + l2, rc + 1); } static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, @@ -1927,6 +1923,11 @@ int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id, /* look for all matching chan_nr/link_id */ for (i = 0; i < _TRX_CHAN_MAX; i++) { + /* skip if pchan type does not match pdch flag */ + if ((trx_sched_multiframes[l1h->mf_index[tn]].pchan + == GSM_PCHAN_PDCH) + != trx_chan_desc[i].pdch) + continue; if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8) && trx_chan_desc[i].link_id == link_id) { LOGP(DL1C, LOGL_NOTICE, "%s %s %s on trx=%d ts=%d\n", |