From e5ee0e5ef19c8c4c48f7999238d39ca70cce4114 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 9 Mar 2020 15:42:33 +0700 Subject: firmware/layer1: introduce experimental PDCH support Change-Id: I44531bbe8743c188cc5d4a6ca2a63000e41d6189 --- src/host/layer23/src/common/l1ctl.c | 6 +++ src/target/firmware/include/layer1/mframe_sched.h | 4 ++ src/target/firmware/include/layer1/sync.h | 1 + src/target/firmware/layer1/l23_api.c | 12 ++++- src/target/firmware/layer1/mframe_sched.c | 59 +++++++++++++++++++++++ src/target/firmware/layer1/prim_rx_nb.c | 2 + 6 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c index b6ee455a..6444fffb 100644 --- a/src/host/layer23/src/common/l1ctl.c +++ b/src/host/layer23/src/common/l1ctl.c @@ -319,6 +319,12 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg) dl->snr, ccch->data, sizeof(ccch->data)); } + /* HACK: Do not pass PDTCH / PTCCH frames to LAPDm */ + if (chan_type == RSL_CHAN_OSMO_PDCH) { + msgb_free(msg); + return 0; + } + /* determine LAPDm entity based on SACCH or not */ if (dl->link_id & 0x40) le = &ms->lapdm_channel.lapdm_acch; 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..7e691110 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 add_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; + add_task = MF_TASK_GPRS_PTCCH; + /* FIXME: is it really different from e.g. BCCH? */ + 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 << add_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..bc119f2b 100644 --- a/src/target/firmware/layer1/mframe_sched.c +++ b/src/target/firmware/layer1/mframe_sched.c @@ -311,6 +311,58 @@ 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 }, +#if 0 + /* FIXME: we need to use different handler here to avoid + * sending dummy blocks and DCCH / SACCH data here. */ + { .sched_set = NB_QUAD_UL, .modulo = 13, .frame_nr = 0 }, + { .sched_set = NB_QUAD_UL, .modulo = 13, .frame_nr = 4 }, + { .sched_set = NB_QUAD_UL, .modulo = 13, .frame_nr = 8 }, +#endif + { .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 +397,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 +470,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; -- cgit v1.2.3