aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-02-15 13:29:29 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2014-04-06 08:57:15 +0200
commit32c1bb1b4d842cf17633fe4c71c59710f704674d (patch)
treeb5bca9d9f009bb07bd99d9631d71ec4e5e93e86a
parent142d81077bd2bad30db42fe25d892412ce377992 (diff)
TRX: PDTCH (GPRS) works now
Detection and transcoding of all four coding schemes are supported.
-rw-r--r--src/osmo-bts-trx/pxxch.c140
-rw-r--r--src/osmo-bts-trx/pxxch.h2
-rw-r--r--src/osmo-bts-trx/scheduler.c117
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",