summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2020-03-09 15:42:33 +0700
committerlaforge <laforge@osmocom.org>2020-04-01 10:18:54 +0000
commit67c49ba664f7d7d7f07986a20e6d6363a27e3fc4 (patch)
tree44dec5cef6cf114b6f0c264b38bf3fe1e58a4653
parent930d7240bf1ead9a7759bc98713c2ef75a1d3ef3 (diff)
firmware/layer1: introduce experimental PDCH support
This change implements basic (receive only) support of the PDCH channels that are used in GPRS. Several coding schemes are defined by 3GPP TS 45.003, however we can only do CS-1 for now, since it's basically an equivalent of xCCH. In order to support the other schemes (CS2-4), we would need to know how to configure the DSP (look at Freecalypso code?). Change-Id: I44531bbe8743c188cc5d4a6ca2a63000e41d6189
-rw-r--r--src/target/firmware/include/layer1/mframe_sched.h4
-rw-r--r--src/target/firmware/include/layer1/sync.h1
-rw-r--r--src/target/firmware/layer1/l23_api.c12
-rw-r--r--src/target/firmware/layer1/mframe_sched.c53
-rw-r--r--src/target/firmware/layer1/prim_rx_nb.c2
5 files changed, 71 insertions, 1 deletions
diff --git a/src/target/firmware/include/layer1/mframe_sched.h b/src/target/firmware/include/layer1/mframe_sched.h
index 74e2d271..9434fc69 100644
--- a/src/target/firmware/include/layer1/mframe_sched.h
+++ b/src/target/firmware/include/layer1/mframe_sched.h
@@ -31,6 +31,9 @@ enum mframe_task {
MF_TASK_TCH_H_0,
MF_TASK_TCH_H_1,
+ MF_TASK_GPRS_PDTCH,
+ MF_TASK_GPRS_PTCCH,
+
MF_TASK_NEIGH_PM51_C0T0,
MF_TASK_NEIGH_PM51,
MF_TASK_NEIGH_PM26E,
@@ -42,6 +45,7 @@ enum mframe_task {
enum mf_sched_item_flag {
MF_F_SACCH = (1 << 0),
+ MF_F_PTCCH = (1 << 1),
};
/* The scheduler itself */
diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h
index daf998b0..6ed3890c 100644
--- a/src/target/firmware/include/layer1/sync.h
+++ b/src/target/firmware/include/layer1/sync.h
@@ -124,6 +124,7 @@ struct l1s_state {
GSM_DCHAN_SDCCH_8_CBCH,
GSM_DCHAN_TCH_H,
GSM_DCHAN_TCH_F,
+ GSM_DCHAN_PDCH,
GSM_DCHAN_UNKNOWN,
} type;
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index f55e6706..e0fee840 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -78,6 +78,7 @@ static uint32_t chan_nr2mf_task_mask(uint8_t chan_nr, uint8_t neigh_mode)
uint8_t tn = chan_nr & 0x7;
uint8_t lch_idx;
enum mframe_task master_task = 0;
+ enum mframe_task second_task = 0;
uint32_t neigh_task = 0;
enum mf_type multiframe = 0;
@@ -97,6 +98,12 @@ static uint32_t chan_nr2mf_task_mask(uint8_t chan_nr, uint8_t neigh_mode)
lch_idx = cbits & 0x7;
master_task = MF_TASK_SDCCH8_0 + lch_idx;
multiframe = MF51;
+ } else if ((cbits & 0x1f) == 0x18) {
+ /* Osmocom specific extension for PDTCH and PTCCH */
+ master_task = MF_TASK_GPRS_PDTCH;
+ second_task = MF_TASK_GPRS_PTCCH;
+ /* FIXME: PDCH has different multiframe structure */
+ multiframe = MFNONE;
} else if ((cbits & 0x1f) == 0x19) {
/* Osmocom specific extension for CBCH on SDCCH/4 */
master_task = MF_TASK_SDCCH4_CBCH;
@@ -129,7 +136,7 @@ static uint32_t chan_nr2mf_task_mask(uint8_t chan_nr, uint8_t neigh_mode)
}
break;
}
- return (1 << master_task) | neigh_task;
+ return (1 << master_task) | (1 << second_task) | neigh_task;
}
static int chan_nr2dchan_type(uint8_t chan_nr)
@@ -144,6 +151,9 @@ static int chan_nr2dchan_type(uint8_t chan_nr)
return GSM_DCHAN_SDCCH_4;
} else if ((cbits & 0x18) == 0x08) {
return GSM_DCHAN_SDCCH_8;
+ } else if ((cbits & 0x1f) == 0x18) {
+ /* Osmocom-specific extension for PDCH */
+ return GSM_DCHAN_PDCH;
} else if ((cbits & 0x1f) == 0x19) {
/* Osmocom-specific extension for CBCH on SDCCH/4 */
return GSM_DCHAN_SDCCH_4_CBCH;
diff --git a/src/target/firmware/layer1/mframe_sched.c b/src/target/firmware/layer1/mframe_sched.c
index 9c2954c3..fac84b43 100644
--- a/src/target/firmware/layer1/mframe_sched.c
+++ b/src/target/firmware/layer1/mframe_sched.c
@@ -311,6 +311,52 @@ static const struct mframe_sched_item mf_neigh_pm26_odd[] = {
{ .sched_set = NULL }
};
+/* See 3GPP TS 45.002, table 6 */
+static const struct mframe_sched_item mf_gprs_pdtch[] = {
+ { .sched_set = NB_QUAD_DL, .modulo = 13, .frame_nr = 0 },
+ { .sched_set = NB_QUAD_DL, .modulo = 13, .frame_nr = 4 },
+ { .sched_set = NB_QUAD_DL, .modulo = 13, .frame_nr = 8 },
+ /* NOTE: receive only task */
+ { .sched_set = NULL }
+};
+
+static const struct mframe_sched_item mf_gprs_ptcch[] = {
+ /* TODO: implement AB_PTCCH_UL for PTCCH/U */
+ /* TODO: implement NB_PTCCH_DL for PTCCH/D */
+#if 0
+ /* PTCCH/D */
+ { .sched_set = NB_PTCCH_DL, .modulo = 104, .frame_nr = 12, .flags = MF_F_PTCCH },
+ { .sched_set = NB_PTCCH_DL, .modulo = 104, .frame_nr = 38, .flags = MF_F_PTCCH },
+ { .sched_set = NB_PTCCH_DL, .modulo = 104, .frame_nr = 64, .flags = MF_F_PTCCH },
+ { .sched_set = NB_PTCCH_DL, .modulo = 104, .frame_nr = 90, .flags = MF_F_PTCCH },
+
+ /* PTCCH/U for TAI 0 .. 3 */
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 12 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 38 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 64 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 90 },
+
+ /* PTCCH/U for TAI 4 .. 7 */
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 116 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 142 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 168 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 194 },
+
+ /* PTCCH/U for TAI 8 .. 11 */
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 220 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 246 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 272 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 298 },
+
+ /* PTCCH/U for TAI 12 .. 15 */
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 324 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 350 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 376 },
+ { .sched_set = AB_PTCCH_UL, .modulo = 416, .frame_nr = 402 },
+#endif
+ { .sched_set = NULL }
+};
+
/* Test TX */
static const struct mframe_sched_item mf_tx_all_nb[] = {
{ .sched_set = NB_QUAD_FH_UL, .modulo = 4, .frame_nr = 0 },
@@ -345,6 +391,9 @@ static const struct mframe_sched_item *sched_set_for_task[32] = {
[MF_TASK_TCH_H_0] = mf_tch_h_0,
[MF_TASK_TCH_H_1] = mf_tch_h_1,
+ [MF_TASK_GPRS_PDTCH] = mf_gprs_pdtch,
+ [MF_TASK_GPRS_PTCCH] = mf_gprs_ptcch,
+
[MF_TASK_NEIGH_PM51_C0T0] = mf_neigh_pm51_c0t0,
[MF_TASK_NEIGH_PM51] = mf_neigh_pm51,
[MF_TASK_NEIGH_PM26E] = mf_neigh_pm26_even,
@@ -415,6 +464,10 @@ uint8_t mframe_task2chan_nr(enum mframe_task mft, uint8_t ts)
break;
/* Osmocom specific extensions */
+ case MF_TASK_GPRS_PDTCH:
+ case MF_TASK_GPRS_PTCCH:
+ cbits = 0x18;
+ break;
case MF_TASK_SDCCH4_CBCH:
cbits = 0x19;
break;
diff --git a/src/target/firmware/layer1/prim_rx_nb.c b/src/target/firmware/layer1/prim_rx_nb.c
index 38c7b53b..c90c98cb 100644
--- a/src/target/firmware/layer1/prim_rx_nb.c
+++ b/src/target/firmware/layer1/prim_rx_nb.c
@@ -126,6 +126,8 @@ static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
/* Set SACCH indication in Link IDentifier */
if (mf_task_flags & MF_F_SACCH)
rxnb.dl->link_id = 0x40;
+ if (mf_task_flags & MF_F_PTCCH)
+ rxnb.dl->link_id = 0x80;
else
rxnb.dl->link_id = 0x00;