summaryrefslogtreecommitdiffstats
path: root/Src/osmocom-bb/src/target/firmware/layer1
diff options
context:
space:
mode:
Diffstat (limited to 'Src/osmocom-bb/src/target/firmware/layer1')
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/Makefile9
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/afc.c130
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/agc.c62
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/apc.c57
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/async.c137
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/avg.c57
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/init.c73
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/l23_api.c536
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/mframe_sched.c462
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_fbsb.c573
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_freq.c112
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_pm.c153
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_rach.c159
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_rx_nb.c215
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_tch.c654
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_tx_nb.c173
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/prim_utils.c74
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/rfch.c152
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/sched_gsmtime.c119
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/sync.c402
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/tdma_sched.c244
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/toa.c80
-rw-r--r--Src/osmocom-bb/src/target/firmware/layer1/tpu_window.c166
23 files changed, 0 insertions, 4799 deletions
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/Makefile b/Src/osmocom-bb/src/target/firmware/layer1/Makefile
deleted file mode 100644
index 455a444..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-
-LIBRARIES+=layer1
-layer1_DIR=layer1
-layer1_SRCS=avg.c agc.c afc.c toa.c sync.c tdma_sched.c tpu_window.c init.c \
- l23_api.c mframe_sched.c sched_gsmtime.c async.c rfch.c apc.c
-
-layer1_SRCS += prim_pm.c prim_rach.c prim_tx_nb.c prim_rx_nb.c prim_fbsb.c \
- prim_freq.c prim_utils.c prim_tch.c
-
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/afc.c b/Src/osmocom-bb/src/target/firmware/layer1/afc.c
deleted file mode 100644
index a51a107..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/afc.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* AFC (Automatic Frequency Correction) Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include <debug.h>
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <layer1/afc.h>
-#include <layer1/avg.h>
-#include <calypso/dsp.h>
-
-#define AFC_INITIAL_DAC_VALUE -700
-
-/* Over how many TDMA frames do we want to average? (this may change in dedicated mode) */
-#define AFC_PERIOD 40
-/* How many of our measurements have to be valid? */
-#define AFC_MIN_MUN_VALID 8
-
-/* The actual AFC code */
-
-struct afc_state {
- struct running_avg ravg; /* running average */
- int16_t dac_value; /* current DAC output value */
- uint16_t arfcn;
-};
-
-static void afc_ravg_output(struct running_avg *ravg, int32_t avg);
-
-static struct afc_state afc_state = {
- .ravg = {
- .outfn = &afc_ravg_output,
- .period = AFC_PERIOD,
- .min_valid = AFC_MIN_MUN_VALID,
- },
- .dac_value = AFC_INITIAL_DAC_VALUE,
-};
-
-/* The AFC DAC in the ABB has to be configured as follows:
- * DAC = 1MHz / 947MHz * FreqErr(Hz) / AFCslop(ppm/LSB)
- * where:
- * 947 MHz is the center of EGSM
- * AFCslope is coded F1.15, thus a normalization factor of 2^15 applies
- */
-
-#define AFC_NORM_FACTOR_GSM ((1<<15) / 947)
-#define AFC_NORM_FACTOR_DCS ((1<<15) / 1894)
-
-/* we assume 8.769ppb per LSB, equals 0.008769 * 32768 == 287 */
-//#define AFC_SLOPE 320
-#define AFC_SLOPE 287
-
-/* The DSP can measure the frequency error in the following ranges:
- * FB_MODE0: +/- 20 kHz
- * FB_MODE1: +/- 4 kHz
- * Sync Burst: +/- 1 kHz
- * Normal Burst: +/- 400 Hz
- */
-
-/* Update the AFC with a frequency error, bypassing averaging */
-void afc_correct(int16_t freq_error, uint16_t arfcn)
-{
- int32_t afc_norm_factor;
- int16_t delta;
-
- switch (gsm_arfcn2band(arfcn)) {
- case GSM_BAND_900:
- case GSM_BAND_850:
- afc_norm_factor = AFC_NORM_FACTOR_GSM;
- break;
- default:
- afc_norm_factor = AFC_NORM_FACTOR_DCS;
- }
-
- delta = (int16_t) ((afc_norm_factor * (int32_t)freq_error) / AFC_SLOPE);
- printd("afc_correct(error=%dHz, arfcn=%u): delta=%d, afc_dac(old=%d,new=%d)\n",
- freq_error, arfcn, delta, afc_state.dac_value, afc_state.dac_value+delta);
- afc_state.dac_value += delta;
-
- /* The AFC DAC has only 13 bits */
- if (afc_state.dac_value > 4095)
- afc_state.dac_value = 4095;
- else if (afc_state.dac_value < -4096)
- afc_state.dac_value = -4096;
-}
-
-void afc_reset(void)
-{
- afc_state.dac_value = AFC_INITIAL_DAC_VALUE;
-}
-
-void afc_input(int32_t freq_error, uint16_t arfcn, int valid)
-{
- afc_state.arfcn = arfcn;
- runavg_input(&afc_state.ravg, freq_error, valid);
- runavg_check_output(&afc_state.ravg);
-}
-
-/* callback function for runavg */
-static void afc_ravg_output(struct running_avg *ravg, int32_t avg)
-{
- afc_correct(avg, afc_state.arfcn);
-}
-
-/* Update DSP with new AFC DAC value to be used for next TDMA frame */
-void afc_load_dsp(void)
-{
- dsp_api.db_w->d_afc = afc_state.dac_value;
- dsp_api.db_w->d_ctrl_abb |= (1 << B_AFC);
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/agc.c b/Src/osmocom-bb/src/target/firmware/layer1/agc.c
deleted file mode 100644
index b72a6e7..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/agc.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* AFC (Automatic Gain Control) Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-#include <debug.h>
-#include <rffe.h>
-
-#include <layer1/agc.h>
-#include <calypso/dsp.h>
-
-/* compute the input level present at the antenna based on a baseband
- * power measurement of the DSP at baseband */
-int16_t agc_inp_dbm8_by_pm(int16_t pm)
-{
- /* pm is in 1/8 dBm at baseband */
- int16_t total_gain_dbm8;
-
- /* compute total current gain */
- total_gain_dbm8 = (system_inherent_gain + rffe_get_gain()) * 8;
-
- /* subtract gain from power measurement at baseband level */
- return pm - total_gain_dbm8;
-}
-
-uint8_t agc_il_by_dbm8(int16_t dbm8)
-{
- uint16_t il;
-
- /* convert from 1/8 dBm to l1c format: [220..0] in -1/2dBm unit */
- if (dbm8 >= 0)
- il = 0;
- else
- il = -dbm8;
-
- /* saturate */
- if (il > 4 * 255)
- il = 4 * 255;
-
- return (uint8_t)(il >> 2);
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/apc.c b/Src/osmocom-bb/src/target/firmware/layer1/apc.c
deleted file mode 100644
index 480c760..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/apc.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* APC (Automatic Power Control) Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <errno.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <layer1/apc.h>
-
-/* calibration table defined in board file */
-extern const int16_t dbm2apc_gsm900[];
-extern const int dbm2apc_gsm900_max;
-
-
-/* determine the AUXAPC value by the Tx Power Level */
-int16_t apc_tx_dbm2auxapc(enum gsm_band band, int8_t dbm)
-{
- if (dbm < 0)
- return -ERANGE;
-
- /* FIXME: offsets for different bands! */
- if (dbm > dbm2apc_gsm900_max)
- dbm = dbm2apc_gsm900_max;
-
- return dbm2apc_gsm900[dbm];
-}
-
-/* determine the AUXAPC value by the Tx Power Level */
-int16_t apc_tx_pwrlvl2auxapc(enum gsm_band band, uint8_t lvl)
-{
- /* convert tx power level to dBm */
- int dbm = ms_pwr_dbm(band, lvl);
- if (dbm < 0)
- return dbm;
-
- return apc_tx_dbm2auxapc(band, dbm);
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/async.c b/Src/osmocom-bb/src/target/firmware/layer1/async.c
deleted file mode 100644
index e5c80c7..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/async.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Asynchronous part of GSM Layer 1 */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-
-#include <debug.h>
-#include <arm.h>
-#include <asm/system.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-
-#include <layer1/sync.h>
-#include <layer1/async.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/sched_gsmtime.h>
-#include <layer1/l23_api.h>
-#include <calypso/l1_environment.h>
-
-extern const struct tdma_sched_item rach_sched_set_ul[];
-
-/* safely enable a message into the L1S TX queue */
-void l1a_txq_msgb_enq(struct llist_head *queue, struct msgb *msg)
-{
- unsigned long flags;
-
- local_firq_save(flags);
- msgb_enqueue(queue, msg);
- local_irq_restore(flags);
-}
-
-void l1a_meas_msgb_set(struct msgb *msg)
-{
- unsigned long flags;
-
- local_firq_save(flags);
- if (l1s.tx_meas)
- msgb_free(l1s.tx_meas);
- l1s.tx_meas = msg;
- local_irq_restore(flags);
-}
-
-/* safely flush all pending msgb */
-void l1a_txq_msgb_flush(struct llist_head *queue)
-{
- struct msgb *msg;
- unsigned long flags;
-
- local_firq_save(flags);
- while ((msg = msgb_dequeue(queue)))
- msgb_free(msg);
- local_irq_restore(flags);
-}
-
-/* Enable a repeating multiframe task */
-void l1a_mftask_enable(enum mframe_task task)
-{
- /* we don't need locking here as L1S only reads mframe.tasks */
- mframe_enable(task);
-}
-
-/* Disable a repeating multiframe task */
-void l1a_mftask_disable(enum mframe_task task)
-{
- /* we don't need locking here as L1S only reads mframe.tasks */
- mframe_disable(task);
-}
-
-/* Set the mask for repeating multiframe tasks */
-void l1a_mftask_set(uint32_t tasks)
-{
- /* we don't need locking here as L1S only reads mframe.tasks */
- mframe_set(tasks);
-}
-
-/* Set TCH mode */
-uint8_t l1a_tch_mode_set(uint8_t mode)
-{
- switch (mode) {
- case GSM48_CMODE_SPEECH_V1:
- case GSM48_CMODE_SPEECH_EFR:
- l1s.tch_mode = mode;
- break;
- default:
- l1s.tch_mode = GSM48_CMODE_SIGN;
- }
-
- return l1s.tch_mode;
-}
-
-/* Initialize asynchronous part of Layer1 */
-void l1a_init(void)
-{
- l1a_l23api_init();
-}
-
-/* Execute pending L1A completions */
-void l1a_compl_execute(void)
-{
- unsigned long flags;
- unsigned int scheduled;
- unsigned int i;
-
- /* get and reset the currently scheduled tasks */
- local_firq_save(flags);
- scheduled = l1s.scheduled_compl;
- l1s.scheduled_compl = 0;
- local_irq_restore(flags);
-
- /* Iterate over list of scheduled completions, call their
- * respective completion handler */
- for (i = 0; i < 32; i++) {
- if (!(scheduled & (1 << i)))
- continue;
- /* call completion function */
- l1s.completion[i](i);
- }
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/avg.c b/Src/osmocom-bb/src/target/firmware/layer1/avg.c
deleted file mode 100644
index a4bf565..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/avg.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Averaging Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-
-#include <layer1/avg.h>
-
-/* input a new sample into the averaging process */
-void runavg_input(struct running_avg *ravg, int32_t val, int valid)
-{
- ravg->num_samples++;
- if (valid) {
- ravg->acc_val += val;
- ravg->num_samples_valid++;
- }
-}
-
-/* check if sufficient samples have been obtained, and call outfn() */
-int runavg_check_output(struct running_avg *ravg)
-{
- if (ravg->num_samples < ravg->period)
- return 0;
-
- if (ravg->num_samples_valid >= ravg->min_valid) {
- int32_t avg = ravg->acc_val / ravg->num_samples_valid;
-
- ravg->outfn(ravg, avg);
-
- ravg->num_samples = ravg->num_samples_valid = 0;
- ravg->acc_val = 0;
-
- return 1;
- }
-
- return 0;
-}
-
-
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/init.c b/Src/osmocom-bb/src/target/firmware/layer1/init.c
deleted file mode 100644
index e7fde23..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/init.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* OsmocomBB Layer1 initialization */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include <rffe.h>
-#include <rf/trf6151.h>
-#include <abb/twl3025.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/irq.h>
-
-#include <layer1/sync.h>
-#include <layer1/async.h>
-#include <layer1/l23_api.h>
-
-void layer1_init(void)
-{
-#ifndef CONFIG_TX_ENABLE
- printf("\n\nTHIS FIRMWARE WAS COMPILED WITHOUT TX SUPPORT!!!\n\n");
-#endif
-
- /* initialize asynchronous part of L1 */
- l1a_init();
- /* initialize TDMA Frame IRQ driven synchronous L1 */
- l1s_init();
- /* power up the DSP */
- dsp_power_on();
-
- /* Initialize TPU, TSP and TRF drivers */
- tpu_init();
- tsp_init();
-
- rffe_init();
-
-#if 0 /* only if RX TPU window is disabled! */
- /* Put TWL3025 in downlink mode (includes calibration) */
- twl3025_downlink(1, 1000);
-#endif
-
- /* issue the TRF and TWL initialization sequence */
- tpu_enq_sleep();
- tpu_enable(1);
- tpu_wait_idle();
-
- /* Disable RTC interrupt as it causes lost TDMA frames */
- irq_disable(IRQ_RTC_TIMER);
-
- /* inform l2 and upwards that we are ready for orders */
- l1ctl_tx_reset(L1CTL_RESET_IND, L1CTL_RES_T_BOOT);
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/l23_api.c b/Src/osmocom-bb/src/target/firmware/layer1/l23_api.c
deleted file mode 100644
index 2e95160..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/l23_api.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/* Synchronous part of GSM Layer 1: API to Layer2+ */
-
-/* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#define DEBUG
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <debug.h>
-#include <byteorder.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <comm/sercomm.h>
-
-#include <layer1/sync.h>
-#include <layer1/async.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/prim.h>
-#include <layer1/tpu_window.h>
-
-#include <abb/twl3025.h>
-#include <rf/trf6151.h>
-
-#include <l1ctl_proto.h>
-
-/* the size we will allocate struct msgb* for HDLC */
-#define L3_MSG_HEAD 4
-#define L3_MSG_SIZE (sizeof(struct l1ctl_hdr)+sizeof(struct l1ctl_info_dl)+sizeof(struct l1ctl_data_ind) + L3_MSG_HEAD)
-
-void l1_queue_for_l2(struct msgb *msg)
-{
- /* forward via serial for now */
- sercomm_sendmsg(SC_DLCI_L1A_L23, msg);
-}
-
-static enum mframe_task chan_nr2mf_task(uint8_t chan_nr)
-{
- uint8_t cbits = chan_nr >> 3;
- uint8_t tn = chan_nr & 0x7;
- uint8_t lch_idx;
-
- if (cbits == 0x01) {
- lch_idx = 0;
- return (tn & 1) ? MF_TASK_TCH_F_ODD : MF_TASK_TCH_F_EVEN;
- } else if ((cbits & 0x1e) == 0x02) {
- lch_idx = cbits & 0x1;
- return MF_TASK_TCH_H_0 + lch_idx;
- } else if ((cbits & 0x1c) == 0x04) {
- lch_idx = cbits & 0x3;
- return MF_TASK_SDCCH4_0 + lch_idx;
- } else if ((cbits & 0x18) == 0x08) {
- lch_idx = cbits & 0x7;
- return MF_TASK_SDCCH8_0 + lch_idx;
-#if 0
- } else if (cbits == 0x10) {
- /* FIXME: when to do extended BCCH? */
- return MF_TASK_BCCH_NORM;
- } else if (cbits == 0x11 || cbits == 0x12) {
- /* FIXME: how to decide CCCH norm/extd? */
- return MF_TASK_BCCH_CCCH;
-#endif
- }
- return 0;
-}
-
-static int chan_nr2dchan_type(uint8_t chan_nr)
-{
- uint8_t cbits = chan_nr >> 3;
-
- if (cbits == 0x01) {
- return GSM_DCHAN_TCH_F;
- } else if ((cbits & 0x1e) == 0x02) {
- return GSM_DCHAN_TCH_H;
- } else if ((cbits & 0x1c) == 0x04) {
- return GSM_DCHAN_SDCCH_4;
- } else if ((cbits & 0x18) == 0x08) {
- return GSM_DCHAN_SDCCH_8;
- }
- return GSM_DCHAN_UNKNOWN;
-}
-
-static int chan_nr_is_tch(uint8_t chan_nr)
-{
- return ((chan_nr >> 3) == 0x01 || /* TCH/F */
- ((chan_nr >> 3) & 0x1e) == 0x02); /* TCH/H */
-}
-
-static void audio_set_enabled(int enabled)
-{
- twl3025_unit_enable(TWL3025_UNIT_VUL, enabled);
- twl3025_unit_enable(TWL3025_UNIT_VDL, enabled);
-}
-
-struct msgb *l1ctl_msgb_alloc(uint8_t msg_type)
-{
- struct msgb *msg;
- struct l1ctl_hdr *l1h;
-
- msg = msgb_alloc_headroom(L3_MSG_SIZE, L3_MSG_HEAD, "l1ctl");
- if (!msg) {
- while (1) {
- puts("OOPS. Out of buffers...\n");
- }
-
- return NULL;
- }
- l1h = (struct l1ctl_hdr *) msgb_put(msg, sizeof(*l1h));
- l1h->msg_type = msg_type;
- l1h->flags = 0;
-
- msg->l1h = (uint8_t *)l1h;
-
- return msg;
-}
-
-struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr,
- uint16_t arfcn)
-{
- struct l1ctl_info_dl *dl;
- struct msgb *msg = l1ctl_msgb_alloc(msg_type);
-
- dl = (struct l1ctl_info_dl *) msgb_put(msg, sizeof(*dl));
- dl->frame_nr = htonl(fn);
- dl->snr = snr;
- dl->band_arfcn = htons(arfcn);
-
- return msg;
-}
-
-/* receive a L1CTL_FBSB_REQ from L23 */
-static void l1ctl_rx_fbsb_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_fbsb_req *sync_req = (struct l1ctl_fbsb_req *) l1h->data;
-
- if (sizeof(*sync_req) > msg->len) {
- printf("Short sync msg. %u\n", msg->len);
- return;
- }
-
- printd("L1CTL_FBSB_REQ (arfcn=%u, flags=0x%x)\n",
- ntohs(sync_req->band_arfcn), sync_req->flags);
-
- /* reset scheduler and hardware */
- l1s_reset();
-
- /* pre-set the CCCH mode */
- l1s.serving_cell.ccch_mode = sync_req->ccch_mode;
-
- printd("Starting FCCH Recognition\n");
- l1s_fbsb_req(1, sync_req);
-}
-
-/* receive a L1CTL_DM_EST_REQ from L23 */
-static void l1ctl_rx_dm_est_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
- struct l1ctl_dm_est_req *est_req = (struct l1ctl_dm_est_req *) ul->payload;
-
- printd("L1CTL_DM_EST_REQ (arfcn=%u, chan_nr=0x%02x, tsc=%u)\n",
- ntohs(est_req->h0.band_arfcn), ul->chan_nr, est_req->tsc);
-
- /* configure dedicated channel state */
- l1s.dedicated.type = chan_nr2dchan_type(ul->chan_nr);
- l1s.dedicated.tsc = est_req->tsc;
- l1s.dedicated.tn = ul->chan_nr & 0x7;
- l1s.dedicated.h = est_req->h;
-
- if (est_req->h) {
- int i;
- l1s.dedicated.h1.hsn = est_req->h1.hsn;
- l1s.dedicated.h1.maio = est_req->h1.maio;
- l1s.dedicated.h1.n = est_req->h1.n;
- for (i=0; i<est_req->h1.n; i++)
- l1s.dedicated.h1.ma[i] = ntohs(est_req->h1.ma[i]);
- } else {
- l1s.dedicated.h0.arfcn = ntohs(est_req->h0.band_arfcn);
- }
-
- /* TCH config */
- if (chan_nr_is_tch(ul->chan_nr)) {
- /* Mode */
- l1a_tch_mode_set(est_req->tch_mode);
-
- /* Sync */
- l1s.tch_sync = 1; /* can be set without locking */
-
- /* Audio path */
- audio_set_enabled(est_req->tch_mode != GSM48_CMODE_SIGN);
- }
-
- /* figure out which MF tasks to enable */
- l1a_mftask_set(1 << chan_nr2mf_task(ul->chan_nr));
-}
-
-/* receive a L1CTL_DM_FREQ_REQ from L23 */
-static void l1ctl_rx_dm_freq_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
- struct l1ctl_dm_freq_req *freq_req =
- (struct l1ctl_dm_freq_req *) ul->payload;
-
- printd("L1CTL_DM_FREQ_REQ (arfcn=%u, tsc=%u)\n",
- ntohs(freq_req->h0.band_arfcn), freq_req->tsc);
-
- /* configure dedicated channel state */
- l1s.dedicated.st_tsc = freq_req->tsc;
- l1s.dedicated.st_h = freq_req->h;
-
- if (freq_req->h) {
- int i;
- l1s.dedicated.st_h1.hsn = freq_req->h1.hsn;
- l1s.dedicated.st_h1.maio = freq_req->h1.maio;
- l1s.dedicated.st_h1.n = freq_req->h1.n;
- for (i=0; i<freq_req->h1.n; i++)
- l1s.dedicated.st_h1.ma[i] = ntohs(freq_req->h1.ma[i]);
- } else {
- l1s.dedicated.st_h0.arfcn = ntohs(freq_req->h0.band_arfcn);
- }
-
- l1a_freq_req(ntohs(freq_req->fn));
-}
-
-/* receive a L1CTL_CRYPTO_REQ from L23 */
-static void l1ctl_rx_crypto_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
- struct l1ctl_crypto_req *cr = (struct l1ctl_crypto_req *) ul->payload;
- uint8_t key_len = msg->len - sizeof(*l1h) - sizeof(*ul) - sizeof(*cr);
-
- printd("L1CTL_CRYPTO_REQ (algo=A5/%u, len=%u)\n", cr->algo, key_len);
-
- if (cr->algo && key_len != 8) {
- printd("L1CTL_CRYPTO_REQ -> Invalid key\n");
- return;
- }
-
- dsp_load_ciph_param(cr->algo, cr->key);
-}
-
-/* receive a L1CTL_DM_REL_REQ from L23 */
-static void l1ctl_rx_dm_rel_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
-
- printd("L1CTL_DM_REL_REQ\n");
- l1a_mftask_set(0);
- l1s.dedicated.type = GSM_DCHAN_NONE;
- l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_MAIN]);
- l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_SACCH]);
- l1a_meas_msgb_set(NULL);
- dsp_load_ciph_param(0, NULL);
- l1a_tch_mode_set(GSM48_CMODE_SIGN);
- audio_set_enabled(0);
-}
-
-/* receive a L1CTL_PARAM_REQ from L23 */
-static void l1ctl_rx_param_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
- struct l1ctl_par_req *par_req = (struct l1ctl_par_req *) ul->payload;
-
- printd("L1CTL_PARAM_REQ (ta=%d, tx_power=%d)\n", par_req->ta,
- par_req->tx_power);
-
- l1s.ta = par_req->ta;
- l1s.tx_power = par_req->tx_power;
-}
-
-/* receive a L1CTL_RACH_REQ from L23 */
-static void l1ctl_rx_rach_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
- struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *) ul->payload;
-
- printd("L1CTL_RACH_REQ (ra=0x%02x, offset=%d combined=%d)\n",
- rach_req->ra, ntohs(rach_req->offset), rach_req->combined);
-
- l1a_rach_req(ntohs(rach_req->offset), rach_req->combined,
- rach_req->ra);
-}
-
-/* receive a L1CTL_DATA_REQ from L23 */
-static void l1ctl_rx_data_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
- struct l1ctl_data_ind *data_ind = (struct l1ctl_data_ind *) ul->payload;
- struct llist_head *tx_queue;
-
- printd("L1CTL_DATA_REQ (link_id=0x%02x)\n", ul->link_id);
-
- msg->l3h = data_ind->data;
- if (ul->link_id & 0x40) {
- struct gsm48_hdr *gh = (struct gsm48_hdr *)(data_ind->data + 5);
- if (gh->proto_discr == GSM48_PDISC_RR
- && gh->msg_type == GSM48_MT_RR_MEAS_REP) {
- printd("updating measurement report\n");
- l1a_meas_msgb_set(msg);
- return;
- }
- tx_queue = &l1s.tx_queue[L1S_CHAN_SACCH];
- } else
- tx_queue = &l1s.tx_queue[L1S_CHAN_MAIN];
-
- printd("ul=%p, ul->payload=%p, data_ind=%p, data_ind->data=%p l3h=%p\n",
- ul, ul->payload, data_ind, data_ind->data, msg->l3h);
-
- l1a_txq_msgb_enq(tx_queue, msg);
-}
-
-/* receive a L1CTL_PM_REQ from L23 */
-static void l1ctl_rx_pm_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_pm_req *pm_req = (struct l1ctl_pm_req *) l1h->data;
-
- switch (pm_req->type) {
- case 1:
- l1s.pm.mode = 1;
- l1s.pm.range.arfcn_start =
- ntohs(pm_req->range.band_arfcn_from);
- l1s.pm.range.arfcn_next =
- ntohs(pm_req->range.band_arfcn_from);
- l1s.pm.range.arfcn_end =
- ntohs(pm_req->range.band_arfcn_to);
- printf("L1CTL_PM_REQ start=%u end=%u\n",
- l1s.pm.range.arfcn_start, l1s.pm.range.arfcn_end);
- break;
- }
-
- l1s_pm_test(1, l1s.pm.range.arfcn_next);
-}
-
-/* Transmit a L1CTL_RESET_IND or L1CTL_RESET_CONF */
-void l1ctl_tx_reset(uint8_t msg_type, uint8_t reset_type)
-{
- struct msgb *msg = l1ctl_msgb_alloc(msg_type);
- struct l1ctl_reset *reset_resp;
- reset_resp = (struct l1ctl_reset *)
- msgb_put(msg, sizeof(*reset_resp));
- reset_resp->type = reset_type;
-
- l1_queue_for_l2(msg);
-}
-
-/* receive a L1CTL_RESET_REQ from L23 */
-static void l1ctl_rx_reset_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_reset *reset_req =
- (struct l1ctl_reset *) l1h->data;
-
- switch (reset_req->type) {
- case L1CTL_RES_T_FULL:
- printf("L1CTL_RESET_REQ: FULL!\n");
- l1s_reset();
- l1s_reset_hw();
- audio_set_enabled(0);
- l1ctl_tx_reset(L1CTL_RESET_CONF, reset_req->type);
- break;
- case L1CTL_RES_T_SCHED:
- printf("L1CTL_RESET_REQ: SCHED!\n");
- l1ctl_tx_reset(L1CTL_RESET_CONF, reset_req->type);
- sched_gsmtime_reset();
- break;
- default:
- printf("unknown L1CTL_RESET_REQ type\n");
- break;
- }
-}
-
-/* Transmit a L1CTL_CCCH_MODE_CONF */
-static void l1ctl_tx_ccch_mode_conf(uint8_t ccch_mode)
-{
- struct msgb *msg = l1ctl_msgb_alloc(L1CTL_CCCH_MODE_CONF);
- struct l1ctl_ccch_mode_conf *mode_conf;
- mode_conf = (struct l1ctl_ccch_mode_conf *)
- msgb_put(msg, sizeof(*mode_conf));
- mode_conf->ccch_mode = ccch_mode;
-
- l1_queue_for_l2(msg);
-}
-
-/* receive a L1CTL_CCCH_MODE_REQ from L23 */
-static void l1ctl_rx_ccch_mode_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_ccch_mode_req *ccch_mode_req =
- (struct l1ctl_ccch_mode_req *) l1h->data;
- uint8_t ccch_mode = ccch_mode_req->ccch_mode;
-
- /* pre-set the CCCH mode */
- l1s.serving_cell.ccch_mode = ccch_mode;
-
- /* Update task */
- mframe_disable(MF_TASK_CCCH_COMB);
- mframe_disable(MF_TASK_CCCH);
-
- if (ccch_mode == CCCH_MODE_COMBINED)
- mframe_enable(MF_TASK_CCCH_COMB);
- else if (ccch_mode == CCCH_MODE_NON_COMBINED)
- mframe_enable(MF_TASK_CCCH);
-
- l1ctl_tx_ccch_mode_conf(ccch_mode);
-}
-
-/* Transmit a L1CTL_TCH_MODE_CONF */
-static void l1ctl_tx_tch_mode_conf(uint8_t tch_mode)
-{
- struct msgb *msg = l1ctl_msgb_alloc(L1CTL_TCH_MODE_CONF);
- struct l1ctl_tch_mode_conf *mode_conf;
- mode_conf = (struct l1ctl_tch_mode_conf *)
- msgb_put(msg, sizeof(*mode_conf));
- mode_conf->tch_mode = tch_mode;
-
- l1_queue_for_l2(msg);
-}
-
-/* receive a L1CTL_TCH_MODE_REQ from L23 */
-static void l1ctl_rx_tch_mode_req(struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_tch_mode_req *tch_mode_req =
- (struct l1ctl_tch_mode_req *) l1h->data;
- uint8_t tch_mode = tch_mode_req->tch_mode;
-
- printd("L1CTL_TCH_MODE_REQ (mode=0x%02x)\n", tch_mode);
- tch_mode = l1a_tch_mode_set(tch_mode);
-
- audio_set_enabled(tch_mode != GSM48_CMODE_SIGN);
-
- l1s.tch_sync = 1; /* Needed for audio to work */
-
- l1ctl_tx_tch_mode_conf(tch_mode);
-}
-
-/* callback from SERCOMM when L2 sends a message to L1 */
-static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
-
-#if 0
- {
- int i;
- printf("l1a_l23_rx_cb (%u): ", msg->len);
- for (i = 0; i < msg->len; i++)
- printf("%02x ", msg->data[i]);
- puts("\n");
- }
-#endif
-
- msg->l1h = msg->data;
-
- if (sizeof(*l1h) > msg->len) {
- printf("l1a_l23_cb: Short message. %u\n", msg->len);
- goto exit_msgbfree;
- }
-
- switch (l1h->msg_type) {
- case L1CTL_FBSB_REQ:
- l1ctl_rx_fbsb_req(msg);
- break;
- case L1CTL_DM_EST_REQ:
- l1ctl_rx_dm_est_req(msg);
- break;
- case L1CTL_DM_REL_REQ:
- l1ctl_rx_dm_rel_req(msg);
- break;
- case L1CTL_PARAM_REQ:
- l1ctl_rx_param_req(msg);
- break;
- case L1CTL_DM_FREQ_REQ:
- l1ctl_rx_dm_freq_req(msg);
- break;
- case L1CTL_CRYPTO_REQ:
- l1ctl_rx_crypto_req(msg);
- break;
- case L1CTL_RACH_REQ:
- l1ctl_rx_rach_req(msg);
- break;
- case L1CTL_DATA_REQ:
- l1ctl_rx_data_req(msg);
- /* we have to keep the msgb, not free it! */
- goto exit_nofree;
- case L1CTL_PM_REQ:
- l1ctl_rx_pm_req(msg);
- break;
- case L1CTL_RESET_REQ:
- l1ctl_rx_reset_req(msg);
- break;
- case L1CTL_CCCH_MODE_REQ:
- l1ctl_rx_ccch_mode_req(msg);
- break;
- case L1CTL_TCH_MODE_REQ:
- l1ctl_rx_tch_mode_req(msg);
- break;
- }
-
-exit_msgbfree:
- msgb_free(msg);
-exit_nofree:
- return;
-}
-
-void l1a_l23api_init(void)
-{
- sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/mframe_sched.c b/Src/osmocom-bb/src/target/firmware/layer1/mframe_sched.c
deleted file mode 100644
index 428102a..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/mframe_sched.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/* GSM Multiframe Scheduler Implementation (on top of TDMA sched) */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <debug.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <layer1/prim.h>
-#include <layer1/sync.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/mframe_sched.h>
-
-/* A multiframe operation which can be scheduled for a multiframe */
-struct mframe_sched_item {
- /* The TDMA scheduler item that shall be scheduled */
- const struct tdma_sched_item *sched_set;
- /* Which modulo shall be used on the frame number */
- uint16_t modulo;
- /* At which number inside the modulo shall we be scheduled */
- uint16_t frame_nr;
- /* bit-mask of flags */
- uint16_t flags;
-};
-
-/* FIXME: properly clean this up */
-#define NB_QUAD_DL nb_sched_set
-#define NB_QUAD_FH_DL NB_QUAD_DL
-#define NB_QUAD_UL nb_sched_set_ul
-#define NB_QUAD_FH_UL NB_QUAD_UL
-
-/* BCCH Normal */
-static const struct mframe_sched_item mf_bcch_norm[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 2 },
- { .sched_set = NULL }
-};
-
-/* BCCH Extended */
-static const struct mframe_sched_item mf_bcch_ext[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 6 },
- { .sched_set = NULL }
-};
-
-/* Full CCCH in a pure BCCH + CCCH C0T0 */
-static const struct mframe_sched_item mf_ccch[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 6 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 12 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 16 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 22 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 26 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 32 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 36 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 42 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 46 },
- { .sched_set = NULL }
-};
-
-/* Full CCCH in a combined CCCH on C0T0 */
-static const struct mframe_sched_item mf_ccch_comb[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 6 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 12 },
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 16 },
- { .sched_set = NULL }
-};
-
-/* SDCCH/4 in a combined CCCH on C0T0, cannot be FH */
-static const struct mframe_sched_item mf_sdcch4_0[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 22 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 22+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 42,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 42+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch4_1[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 26 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 26+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 46,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 46+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch4_2[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 32 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 32+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 51+42,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 51+42+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch4_3[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 36 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 36+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 51+46,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 51+46+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-
-/* SDCCH/8, can be frequency hopping (FH) */
-static const struct mframe_sched_item mf_sdcch8_0[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 0 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 0+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 32,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 32+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_1[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 4 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 4+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 36,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 36+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_2[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 8 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 8+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 40,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 40+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_3[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 12 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 12+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 44,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 44+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_4[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 16 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 16+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+32,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+32+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_5[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 20 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 20+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+36,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+36+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_6[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 24 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 24+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+40,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+40+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-static const struct mframe_sched_item mf_sdcch8_7[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 28 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 28+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+44,
- .flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+44+15,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-
-/* TCH */
-#define TCH tch_sched_set
-#define TCH_A tch_a_sched_set
-#define TCH_D tch_d_sched_set
-
-static const struct mframe_sched_item mf_tch_f_even[] = {
- { .sched_set = TCH, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 12,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-
-static const struct mframe_sched_item mf_tch_f_odd[] = {
- { .sched_set = TCH, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 25,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-
-static const struct mframe_sched_item mf_tch_h_0[] = {
- { .sched_set = TCH, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 12,
- .flags = MF_F_SACCH },
- { .sched_set = NULL }
-};
-
-static const struct mframe_sched_item mf_tch_h_1[] = {
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 25,
- .flags = MF_F_SACCH },
- { .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 },
- { .sched_set = NULL }
-};
-
-static const struct mframe_sched_item *sched_set_for_task[32] = {
- [MF_TASK_BCCH_NORM] = mf_bcch_norm,
- [MF_TASK_BCCH_EXT] = mf_bcch_ext,
- [MF_TASK_CCCH] = mf_ccch,
- [MF_TASK_CCCH_COMB] = mf_ccch_comb,
-
- [MF_TASK_SDCCH4_0] = mf_sdcch4_0,
- [MF_TASK_SDCCH4_1] = mf_sdcch4_1,
- [MF_TASK_SDCCH4_2] = mf_sdcch4_2,
- [MF_TASK_SDCCH4_3] = mf_sdcch4_3,
-
- [MF_TASK_SDCCH8_0] = mf_sdcch8_0,
- [MF_TASK_SDCCH8_1] = mf_sdcch8_1,
- [MF_TASK_SDCCH8_2] = mf_sdcch8_2,
- [MF_TASK_SDCCH8_3] = mf_sdcch8_3,
- [MF_TASK_SDCCH8_4] = mf_sdcch8_4,
- [MF_TASK_SDCCH8_5] = mf_sdcch8_5,
- [MF_TASK_SDCCH8_6] = mf_sdcch8_6,
- [MF_TASK_SDCCH8_7] = mf_sdcch8_7,
-
- [MF_TASK_TCH_F_EVEN] = mf_tch_f_even,
- [MF_TASK_TCH_F_ODD] = mf_tch_f_odd,
- [MF_TASK_TCH_H_0] = mf_tch_h_0,
- [MF_TASK_TCH_H_1] = mf_tch_h_1,
-
- [MF_TASK_UL_ALL_NB] = mf_tx_all_nb,
-};
-
-/* encodes a channel number according to 08.58 Chapter 9.3.1 */
-uint8_t mframe_task2chan_nr(enum mframe_task mft, uint8_t ts)
-{
- uint8_t cbits;
-
- switch (mft) {
- case MF_TASK_BCCH_NORM:
- case MF_TASK_BCCH_EXT:
- cbits = 0x10;
- break;
- case MF_TASK_CCCH:
- case MF_TASK_CCCH_COMB:
- cbits = 0x12;
- break;
- case MF_TASK_SDCCH4_0:
- cbits = 0x04 + 0;
- break;
- case MF_TASK_SDCCH4_1:
- cbits = 0x04 + 1;
- break;
- case MF_TASK_SDCCH4_2:
- cbits = 0x04 + 2;
- break;
- case MF_TASK_SDCCH4_3:
- cbits = 0x04 + 3;
- break;
- case MF_TASK_SDCCH8_0:
- cbits = 0x08 + 0;
- break;
- case MF_TASK_SDCCH8_1:
- cbits = 0x08 + 1;
- break;
- case MF_TASK_SDCCH8_2:
- cbits = 0x08 + 2;
- break;
- case MF_TASK_SDCCH8_3:
- cbits = 0x08 + 3;
- break;
- case MF_TASK_SDCCH8_4:
- cbits = 0x08 + 4;
- break;
- case MF_TASK_SDCCH8_5:
- cbits = 0x08 + 5;
- break;
- case MF_TASK_SDCCH8_6:
- cbits = 0x08 + 6;
- break;
- case MF_TASK_SDCCH8_7:
- cbits = 0x08 + 7;
- break;
- case MF_TASK_TCH_F_EVEN:
- case MF_TASK_TCH_F_ODD:
- cbits = 0x01;
- break;
- case MF_TASK_TCH_H_0:
- cbits = 0x02 + 0;
- break;
- case MF_TASK_TCH_H_1:
- cbits = 0x02 + 1;
- break;
- case MF_TASK_UL_ALL_NB:
- /* ERROR: cannot express as channel number */
- cbits = 0;
- break;
- }
-
- return (cbits << 3) | (ts & 0x7);
-}
-
-/* how many TDMA frame ticks should we schedule events ahead? */
-#define SCHEDULE_AHEAD 2
-
-/* how long do we need to tell the DSP in advance what we want to do? */
-#define SCHEDULE_LATENCY 1
-
-/* (test and) schedule one particular sched_item_set by means of the TDMA scheduler */
-static void mframe_schedule_set(enum mframe_task task_id)
-{
- const struct mframe_sched_item *set = sched_set_for_task[task_id];
- const struct mframe_sched_item *si;
-
- for (si = set; si->sched_set != NULL; si++) {
- unsigned int trigger = si->frame_nr % si->modulo;
- unsigned int current = (l1s.current_time.fn + SCHEDULE_AHEAD) % si->modulo;
- if (current == trigger) {
- uint32_t fn;
- int rv;
-
- /* Schedule the set */
- /* FIXME: what to do with SACCH Flag etc? */
- rv = tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
- si->sched_set, task_id | (si->flags<<8));
-
- /* Compute the next safe time to queue a DSP command */
- fn = l1s.current_time.fn;
- ADD_MODULO(fn, rv - 2, GSM_MAX_FN); /* -2 = worst case last dsp command */
- if ((fn > l1s.mframe_sched.safe_fn) ||
- (l1s.mframe_sched.safe_fn >= GSM_MAX_FN))
- l1s.mframe_sched.safe_fn = fn;
- }
- }
-}
-
-/* Enable a specific task */
-void mframe_enable(enum mframe_task task_id)
-{
- l1s.mframe_sched.tasks_tgt |= (1 << task_id);
-}
-
-/* Disable a specific task */
-void mframe_disable(enum mframe_task task_id)
-{
- l1s.mframe_sched.tasks_tgt &= ~(1 << task_id);
-}
-
-/* Replace the current active set by the new one */
-void mframe_set(uint32_t tasks)
-{
- l1s.mframe_sched.tasks_tgt = tasks;
-}
-
-/* Schedule mframe_sched_items according to current MF TASK list */
-void mframe_schedule(void)
-{
- unsigned int i;
- int fn_diff;
-
- /* Try to enable/disable task to meet target bitmap */
- fn_diff = l1s.mframe_sched.safe_fn - l1s.current_time.fn;
- if ((fn_diff <= 0) || (fn_diff >= (GSM_MAX_FN>>1)) ||
- (l1s.mframe_sched.safe_fn >= GSM_MAX_FN))
- /* If nothing is in the way, enable new tasks */
- l1s.mframe_sched.tasks = l1s.mframe_sched.tasks_tgt;
- else
- /* Else, Disable only */
- l1s.mframe_sched.tasks &= l1s.mframe_sched.tasks_tgt;
-
- /* Schedule any active pending set */
- for (i = 0; i < 32; i++) {
- if (l1s.mframe_sched.tasks & (1 << i))
- mframe_schedule_set(i);
- }
-}
-
-/* reset the scheduler, disabling all tasks */
-void mframe_reset(void)
-{
- l1s.mframe_sched.tasks = 0;
- l1s.mframe_sched.tasks_tgt = 0;
- l1s.mframe_sched.safe_fn = -1UL; /* Force safe */
-}
-
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_fbsb.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_fbsb.c
deleted file mode 100644
index 124a316..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_fbsb.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/* Layer 1 - FCCH and SCH burst handling */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-
-#include <layer1/sync.h>
-#include <layer1/afc.h>
-#include <layer1/toa.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-
-#include <l1ctl_proto.h>
-
-#define FB0_RETRY_COUNT 3
-#define AFC_RETRY_COUNT 30
-
-extern uint16_t rf_arfcn; // TODO
-
-struct mon_state {
- uint32_t fnr_report; /* frame number when DSP reported it */
- int attempt; /* which attempt was this ? */
-
- int16_t toa;
- uint16_t pm;
- uint16_t angle;
- uint16_t snr;
-
- /* computed values */
- int16_t freq_diff;
-
- /* Sync Burst (SB) */
- uint8_t bsic;
- struct gsm_time time;
-};
-
-struct l1a_fb_state {
- struct mon_state mon;
- struct l1ctl_fbsb_req req;
- int16_t initial_freq_err;
- uint8_t fb_retries;
- uint8_t afc_retries;
-};
-
-static struct l1a_fb_state fbs;
-static struct mon_state *last_fb = &fbs.mon;
-
-static void dump_mon_state(struct mon_state *fb)
-{
-#if 0
- printf("(%u:%u): TOA=%5u, Power=%4ddBm, Angle=%5dHz, "
- "SNR=%04x(%d.%u) OFFSET=%u SYNCHRO=%u\n",
- fb->fnr_report, fb->attempt, fb->toa,
- agc_inp_dbm8_by_pm(fb->pm)/8, ANGLE_TO_FREQ(fb->angle),
- fb->snr, l1s_snr_int(fb->snr), l1s_snr_fract(fb->snr),
- tpu_get_offset(), tpu_get_synchro());
-#else
- printf("(%u:%u): TOA=%5u, Power=%4ddBm, Angle=%5dHz\n",
- fb->fnr_report, fb->attempt, fb->toa,
- agc_inp_dbm8_by_pm(fb->pm)/8, ANGLE_TO_FREQ(fb->angle));
-#endif
-}
-
-static int l1ctl_fbsb_resp(uint8_t res)
-{
- struct msgb *msg;
- struct l1ctl_fbsb_conf *resp;
-
- msg = l1_create_l2_msg(L1CTL_FBSB_CONF, fbs.mon.time.fn,
- l1s_snr_int(fbs.mon.snr),
- fbs.req.band_arfcn);
- if (!msg)
- return -ENOMEM;
-
- resp = (struct l1ctl_fbsb_conf *) msgb_put(msg, sizeof(*resp));
- resp->initial_freq_err = htons(fbs.initial_freq_err);
- resp->result = res;
- resp->bsic = fbs.mon.bsic;
-
- /* no need to set BSIC, as it is never used here */
- l1_queue_for_l2(msg);
-
- return 0;
-}
-
-/* SCH Burst Detection ********************************************************/
-
-/* determine the GSM time and BSIC from a Sync Burst */
-static uint8_t l1s_decode_sb(struct gsm_time *time, uint32_t sb)
-{
- uint8_t bsic = (sb >> 2) & 0x3f;
- uint8_t t3p;
-
- memset(time, 0, sizeof(*time));
-
- /* TS 05.02 Chapter 3.3.2.2.1 SCH Frame Numbers */
- time->t1 = ((sb >> 23) & 1) | ((sb >> 7) & 0x1fe) | ((sb << 9) & 0x600);
- time->t2 = (sb >> 18) & 0x1f;
- t3p = ((sb >> 24) & 1) | ((sb >> 15) & 6);
- time->t3 = t3p*10 + 1;
-
- /* TS 05.02 Chapter 4.3.3 TDMA frame number */
- time->fn = gsm_gsmtime2fn(time);
-
- time->tc = (time->fn / 51) % 8;
-
- return bsic;
-}
-
-static void read_sb_result(struct mon_state *st, int attempt)
-{
- st->toa = dsp_api.db_r->a_serv_demod[D_TOA];
- st->pm = dsp_api.db_r->a_serv_demod[D_PM]>>3;
- st->angle = dsp_api.db_r->a_serv_demod[D_ANGLE];
- st->snr = dsp_api.db_r->a_serv_demod[D_SNR];
-
- st->freq_diff = ANGLE_TO_FREQ(st->angle);
- st->fnr_report = l1s.current_time.fn;
- st->attempt = attempt;
-
- dump_mon_state(st);
-
- if (st->snr > AFC_SNR_THRESHOLD)
- afc_input(st->freq_diff, rf_arfcn, 1);
- else
- afc_input(st->freq_diff, rf_arfcn, 0);
-
- dsp_api.r_page_used = 1;
-}
-
-/* Note: When we get the SB response, it is 2 TDMA frames after the SB
- * actually happened, as it is a "C W W R" task */
-#define SB2_LATENCY 2
-
-static int l1s_sbdet_resp(__unused uint8_t p1, uint8_t attempt,
- __unused uint16_t p3)
-{
- uint32_t sb;
- int qbits, fn_offset;
- struct l1_cell_info *cinfo = &l1s.serving_cell;
- int fnr_delta, bits_delta;
- struct l1ctl_sync_new_ccch_resp *l1;
- struct msgb *msg;
-
- putchart('s');
-
- if (dsp_api.db_r->a_sch[0] & (1<<B_SCH_CRC)) {
- /* mark READ page as being used */
- dsp_api.r_page_used = 1;
-
- /* after 2nd attempt, we failed */
- if (attempt == 2) {
- last_fb->attempt = 13;
- l1s_compl_sched(L1_COMPL_FB);
- }
-
- /* after 1st attempt, we simply wait for 2nd */
- return 0;
- }
-
- printf("SB%d ", attempt);
- read_sb_result(last_fb, attempt);
-
- sb = dsp_api.db_r->a_sch[3] | dsp_api.db_r->a_sch[4] << 16;
- fbs.mon.bsic = l1s_decode_sb(&fbs.mon.time, sb);
- printf("=> SB 0x%08x: BSIC=%u ", sb, fbs.mon.bsic);
- l1s_time_dump(&fbs.mon.time);
-
- l1s.serving_cell.bsic = fbs.mon.bsic;
-
- /* calculate synchronisation value (TODO: only complete for qbits) */
- last_fb->toa -= 23;
- qbits = last_fb->toa * 4;
- fn_offset = l1s.current_time.fn; // TODO
-
- if (qbits > QBITS_PER_TDMA) {
- qbits -= QBITS_PER_TDMA;
- fn_offset -= 1;
- } else if (qbits < 0) {
- qbits += QBITS_PER_TDMA;
- fn_offset += 1;
- }
-
- fnr_delta = last_fb->fnr_report - attempt;
- bits_delta = fnr_delta * BITS_PER_TDMA;
-
- cinfo->fn_offset = fnr_delta;
- cinfo->time_alignment = qbits;
- cinfo->arfcn = rf_arfcn;
-
- if (last_fb->toa > bits_delta)
- printf("=> DSP reports SB in bit that is %d bits in the "
- "future?!?\n", last_fb->toa - bits_delta);
- else
- printf(" qbits=%u\n", qbits);
-
- synchronize_tdma(&l1s.serving_cell);
-
- /* if we have recived a SYNC burst, update our local GSM time */
- gsm_fn2gsmtime(&l1s.current_time, fbs.mon.time.fn + SB2_LATENCY);
- /* compute next time from new current time */
- l1s.next_time = l1s.current_time;
- l1s_time_inc(&l1s.next_time, 1);
-
- /* If we call tdma_sched_reset(), which is only needed if there
- * are further l1s_sbdet_resp() scheduled, we will bring
- * dsp_api.db_r and dsp_api.db_w out of sync because we changed
- * dsp_api.db_w for l1s_sbdet_cmd() and canceled
- * l1s_sbdet_resp() which would change dsp_api.db_r. The DSP
- * however expects dsp_api.db_w and dsp_api.db_r to be in sync
- * (either "0 - 0" or "1 - 1"). So we have to bring dsp_api.db_w
- * and dsp_api.db_r into sync again, otherwise NB reading will
- * complain. We probably don't need the Abort command and could
- * just bring dsp_api.db_w and dsp_api.db_r into sync. */
- if (attempt != 2) {
- tdma_sched_reset();
- l1s_dsp_abort();
- }
-
- l1s_reset_hw();
- /* enable the MF Task for BCCH reading */
- mframe_enable(MF_TASK_BCCH_NORM);
- if (l1s.serving_cell.ccch_mode == CCCH_MODE_COMBINED)
- mframe_enable(MF_TASK_CCCH_COMB);
- else if (l1s.serving_cell.ccch_mode == CCCH_MODE_NON_COMBINED)
- mframe_enable(MF_TASK_CCCH);
-
- l1s_compl_sched(L1_COMPL_FB);
-
- return 0;
-}
-
-static int l1s_sbdet_cmd(__unused uint8_t p1, __unused uint8_t p2,
- __unused uint16_t p3)
-{
- putchart('S');
-
- fbs.mon.bsic = 0;
- fbs.mon.time.fn = 0;
-
- dsp_api.db_w->d_task_md = SB_DSP_TASK;
- dsp_api.ndb->d_fb_mode = 0; /* wideband search */
-
- /* Program TPU */
- l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_SB, 0);
-
- return 0;
-}
-
-/* This is how it is done by the TSM30 */
-static const struct tdma_sched_item sb_sched_set[] = {
- SCHED_ITEM_DT(l1s_sbdet_cmd, 0, 0, 1), SCHED_END_FRAME(),
- SCHED_ITEM_DT(l1s_sbdet_cmd, 0, 0, 2), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_sbdet_resp, -4, 0, 1), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_sbdet_resp, -4, 0, 2), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-void l1s_sb_test(uint8_t base_fn)
-{
- tdma_schedule_set(base_fn, sb_sched_set, 0);
-}
-/* FCCH Burst *****************************************************************/
-
-static int read_fb_result(struct mon_state *st, int attempt)
-{
- st->toa = dsp_api.ndb->a_sync_demod[D_TOA];
- st->pm = dsp_api.ndb->a_sync_demod[D_PM]>>3;
- st->angle = dsp_api.ndb->a_sync_demod[D_ANGLE];
- st->snr = dsp_api.ndb->a_sync_demod[D_SNR];
-
- //last_fb->angle = clip_int16(last_fb->angle, AFC_MAX_ANGLE);
- st->freq_diff = ANGLE_TO_FREQ(last_fb->angle);
- st->fnr_report = l1s.current_time.fn;
- st->attempt = attempt;
-
- dump_mon_state(st);
-
- dsp_api.ndb->d_fb_det = 0;
- dsp_api.ndb->a_sync_demod[D_TOA] = 0; /* TSM30 does it (really needed ?) */
-
- /* Update AFC with current frequency offset */
- afc_correct(st->freq_diff, rf_arfcn);
-
- //tpu_dsp_frameirq_enable();
- return 1;
-}
-
-static void fbinfo2cellinfo(struct l1_cell_info *cinfo,
- const struct mon_state *mon)
-{
- int ntdma, qbits, fn_offset, fnr_delta, bits_delta;
-
- /* FIXME: where did this magic 23 come from? */
- last_fb->toa -= 23;
-
- if (last_fb->toa < 0) {
- qbits = (last_fb->toa + BITS_PER_TDMA) * 4;
- ntdma = -1;
- } else {
- ntdma = (last_fb->toa) / BITS_PER_TDMA;
- qbits = (last_fb->toa - ntdma * BITS_PER_TDMA) * 4;
- }
-
- fn_offset = l1s.current_time.fn - last_fb->attempt + ntdma;
- fnr_delta = last_fb->fnr_report - last_fb->attempt;
- bits_delta = fnr_delta * BITS_PER_TDMA;
-
- cinfo->fn_offset = fnr_delta;
- cinfo->time_alignment = qbits;
- cinfo->arfcn = rf_arfcn;
-
- if (last_fb->toa > bits_delta)
- printf("=> DSP reports FB in bit that is %d bits in "
- "the future?!?\n", last_fb->toa - bits_delta);
- else {
- int fb_fnr = (last_fb->fnr_report - last_fb->attempt)
- + last_fb->toa/BITS_PER_TDMA;
- printf("=>FB @ FNR %u fn_offset=%d qbits=%u\n",
- fb_fnr, fn_offset, qbits);
- }
-}
-
-/* scheduler callback to issue a FB detection task to the DSP */
-static int l1s_fbdet_cmd(__unused uint8_t p1, __unused uint8_t p2,
- uint16_t fb_mode)
-{
- if (fb_mode == 0) {
- putchart('F');
- } else {
- putchart('V');
- }
-
- l1s.fb.mode = fb_mode;
-
- /* Tell the RF frontend to set the gain appropriately */
- rffe_set_gain(-85, CAL_DSP_TGT_BB_LVL);
-
- /* Program DSP */
- dsp_api.db_w->d_task_md = FB_DSP_TASK; /* maybe with I/Q swap? */
- dsp_api.ndb->d_fb_mode = fb_mode;
-
- /* Program TPU */
- l1s_rx_win_ctrl(fbs.req.band_arfcn, L1_RXWIN_FB, 0);
-
- return 0;
-}
-
-#if 0
-#define FB0_SNR_THRESH 2000
-#define FB1_SNR_THRESH 3000
-#else
-#define FB0_SNR_THRESH 0
-#define FB1_SNR_THRESH 0
-#endif
-
-static const struct tdma_sched_item fb_sched_set[];
-
-/* scheduler callback to check for a FB detection response */
-static int l1s_fbdet_resp(__unused uint8_t p1, uint8_t attempt,
- uint16_t fb_mode)
-{
- putchart('f');
-
- if (!dsp_api.ndb->d_fb_det) {
- /* we did not detect a FB */
-
- /* attempt < 12, do nothing */
- if (attempt < 12)
- return 0;
-
- /* attempt >= 12, we simply don't find one */
-
- /* If we don't reset here, we get DSP DMA errors */
- tdma_sched_reset();
-
- if (fbs.fb_retries < FB0_RETRY_COUNT) {
- /* retry once more */
- tdma_schedule_set(1, fb_sched_set, 0);
- fbs.fb_retries++;
- } else {
- last_fb->attempt = 13;
- l1s_compl_sched(L1_COMPL_FB);
- }
-
- return 0;
- }
-
- /* We found a frequency burst, reset everything */
- l1s_reset_hw();
-
- printf("FB%u ", dsp_api.ndb->d_fb_mode);
- read_fb_result(last_fb, attempt);
-
- /* if this is the first success, save freq err */
- if (!fbs.initial_freq_err)
- fbs.initial_freq_err = last_fb->freq_diff;
-
- /* If we don't reset here, we get DSP DMA errors */
- tdma_sched_reset();
-
- /* Immediately schedule further TDMA tasklets, if requested. Doing
- * this directly from L1S means we can do this quickly without any
- * additional delays */
- if (fb_mode == 0) {
- if (fbs.req.flags & L1CTL_FBSB_F_FB1) {
- /* If we don't reset here, we get DSP DMA errors */
- tdma_sched_reset();
- /* FIXME: don't only use the last but an average */
- if (abs(last_fb->freq_diff) < fbs.req.freq_err_thresh1 &&
- last_fb->snr > FB0_SNR_THRESH) {
- /* continue with FB1 task in DSP */
- tdma_schedule_set(1, fb_sched_set, 1);
- } else {
- if (fbs.afc_retries < AFC_RETRY_COUNT) {
- tdma_schedule_set(1, fb_sched_set, 0);
- fbs.afc_retries++;
- } else {
- /* Abort */
- last_fb->attempt = 13;
- l1s_compl_sched(L1_COMPL_FB);
- }
- }
- } else
- l1s_compl_sched(L1_COMPL_FB);
- } else if (fb_mode == 1) {
- if (fbs.req.flags & L1CTL_FBSB_F_SB) {
-
- int ntdma, qbits;
- /* FIXME: where did this magic 23 come from? */
- last_fb->toa -= 23;
-
- if (last_fb->toa < 0) {
- qbits = (last_fb->toa + BITS_PER_TDMA) * 4;
- ntdma = -1;
- } else {
- ntdma = (last_fb->toa) / BITS_PER_TDMA;
- qbits = (last_fb->toa - ntdma * BITS_PER_TDMA) * 4;
- }
-
-
- int fn_offset = l1s.current_time.fn - last_fb->attempt + ntdma;
- int delay = fn_offset + 11 - l1s.current_time.fn - 1;
- printf(" fn_offset=%d (fn=%u + attempt=%u + ntdma = %d)\m",
- fn_offset, l1s.current_time.fn, last_fb->attempt, ntdma);
- printf(" delay=%d (fn_offset=%d + 11 - fn=%u - 1\n", delay,
- fn_offset, l1s.current_time.fn);
- printf(" scheduling next FB/SB detection task with delay %u\n", delay);
- if (abs(last_fb->freq_diff) < fbs.req.freq_err_thresh2 &&
- last_fb->snr > FB1_SNR_THRESH) {
- /* synchronize before reading SB */
- fbinfo2cellinfo(&l1s.serving_cell, last_fb);
- synchronize_tdma(&l1s.serving_cell);
- tdma_schedule_set(delay, sb_sched_set, 0);
- } else
- tdma_schedule_set(delay, fb_sched_set, 1);
- } else
- l1s_compl_sched(L1_COMPL_FB);
- }
-
- return 0;
-}
-
-/* FB detection */
-static const struct tdma_sched_item fb_sched_set[] = {
- SCHED_ITEM_DT(l1s_fbdet_cmd, 0, 0, 0), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 1), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 2), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 3), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 4), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 5), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 6), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 7), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 8), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 9), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 10), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 11), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_fbdet_resp, -4, 0, 12), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-/* Asynchronous completion handler for FB detection */
-static void l1a_fb_compl(__unused enum l1_compl c)
-{
- struct l1_cell_info *cinfo = &l1s.serving_cell;
-
- if (last_fb->attempt >= 13) {
- /* FB detection failed, signal this via L1CTL */
- return l1ctl_fbsb_resp(255);
- }
-
- /* FIME: use l1s.neigh_cell[fbs.cinfo_idx] */
- fbinfo2cellinfo(&l1s.serving_cell, last_fb);
-
- /* send FBSB_CONF success message via L1CTL */
- l1ctl_fbsb_resp(0);
-}
-
-void l1s_fbsb_req(uint8_t base_fn, struct l1ctl_fbsb_req *req)
-{
- /* copy + endian convert request data */
- fbs.req.band_arfcn = ntohs(req->band_arfcn);
- fbs.req.timeout = ntohs(req->timeout);
- fbs.req.freq_err_thresh1 = ntohs(req->freq_err_thresh1);
- fbs.req.freq_err_thresh2 = ntohs(req->freq_err_thresh2);
- fbs.req.num_freqerr_avg = req->num_freqerr_avg;
- fbs.req.flags = req->flags;
- fbs.req.sync_info_idx = req->sync_info_idx;
-
- /* clear initial frequency error */
- fbs.initial_freq_err = 0;
- fbs.fb_retries = 0;
- fbs.afc_retries = 0;
-
- /* Make sure we start at a 'center' AFCDAC output value */
- afc_reset();
-
- /* Reset the TOA loop counters */
- toa_reset();
-
- if (fbs.req.flags & L1CTL_FBSB_F_FB0)
- tdma_schedule_set(base_fn, fb_sched_set, 0);
- else if (fbs.req.flags & L1CTL_FBSB_F_FB1)
- tdma_schedule_set(base_fn, fb_sched_set, 0);
- else if (fbs.req.flags & L1CTL_FBSB_F_SB)
- tdma_schedule_set(base_fn, sb_sched_set, 0);
-
-}
-
-static __attribute__ ((constructor)) void l1s_prim_fbsb_init(void)
-{
- l1s.completion[L1_COMPL_FB] = &l1a_fb_compl;
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_freq.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_freq.c
deleted file mode 100644
index 88bc453..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_freq.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Layer 1 Frequency redefinition at "starting time" */
-
-/* (C) 2010 by Andreas Eversverg <jolly@eversberg.eu>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-#include <asm/system.h>
-
-#include <layer1/sync.h>
-#include <layer1/async.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-
-#include <l1ctl_proto.h>
-
-struct {
- uint32_t fn;
- uint16_t band_arfcn;
-} last_rach;
-
-/* if the "starting time" is reached, use frequencies "after time" */
-static int l1s_freq_cmd(__unused uint8_t p1, __unused uint8_t p2, __unused uint16_t p3)
-{
- putchart('F');
-
- printf("Reached starting time, altering frequency set\n");
-
- l1s.dedicated.tsc = l1s.dedicated.st_tsc;
- l1s.dedicated.h = l1s.dedicated.st_h;
- if (l1s.dedicated.h)
- memcpy(&l1s.dedicated.h1, &l1s.dedicated.st_h1,
- sizeof(l1s.dedicated.h1));
- else
- memcpy(&l1s.dedicated.h0, &l1s.dedicated.st_h0,
- sizeof(l1s.dedicated.h0));
-
- return 0;
-}
-
-/* sched set for frequency change */
-const struct tdma_sched_item freq_sched_set[] = {
- SCHED_ITEM(l1s_freq_cmd, -3, 1, 0),
- SCHED_END_SET()
-};
-
-/* request a frequency change at the given frame number
- * Note: The fn_sched parameter must be in range 0..42431. */
-void l1a_freq_req(uint32_t fn_sched)
-{
- int32_t diff;
- unsigned long flags;
-
- /* We must check here, if the time already elapsed.
- * This is required, because we may have an undefined delay between
- * layer 1 and layer 3.
- */
- diff = fn_sched - (l1s.current_time.fn % 42432);
- if (diff < 0)
- diff += 42432;
- /* note: 5 is used to give scheduler some time */
- if (diff == 5 || diff >= 32024) {
- l1s_freq_cmd(0, 0, 0);
- return;
- }
-
- /* calculate (full range) frame number */
- fn_sched = l1s.current_time.fn + diff;
- if (fn_sched >= GSM_MAX_FN)
- fn_sched -= GSM_MAX_FN;
- printf("Scheduling frequency change at fn=%u, currently fn=%u\n",
- fn_sched, l1s.current_time.fn);
-
- local_firq_save(flags);
- sched_gsmtime(freq_sched_set, fn_sched, 0);
- local_irq_restore(flags);
-}
-
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_pm.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_pm.c
deleted file mode 100644
index 5d2f413..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_pm.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Layer 1 Power Measurement */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-#include <asm/system.h>
-
-#include <layer1/sync.h>
-#include <layer1/agc.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-#include <layer1/prim.h>
-
-#include <l1ctl_proto.h>
-
-static void l1ddsp_meas_read(uint8_t nbmeas, uint16_t *pm)
-{
- uint8_t i;
-
- for (i = 0; i < nbmeas; i++)
- pm[i] = (uint16_t) ((dsp_api.db_r->a_pm[i] & 0xffff) >> 3);
- dsp_api.r_page_used = 1;
-}
-
-/* scheduler callback to issue a power measurement task to the DSP */
-static int l1s_pm_cmd(uint8_t num_meas,
- __unused uint8_t p2, uint16_t arfcn)
-{
- putchart('P');
-
- dsp_api.db_w->d_task_md = num_meas; /* number of measurements */
- dsp_api.ndb->d_fb_mode = 0; /* wideband search */
-
- /* Tell the RF frontend to set the gain appropriately */
- rffe_set_gain(-85, CAL_DSP_TGT_BB_LVL);
-
- /* Program TPU */
- /* FIXME: RXWIN_PW needs to set up multiple times in case
- * num_meas > 1 */
- l1s_rx_win_ctrl(arfcn, L1_RXWIN_PW, 0);
- //l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB);
-
- return 0;
-}
-
-/* scheduler callback to read power measurement resposnse from the DSP */
-static int l1s_pm_resp(uint8_t num_meas, __unused uint8_t p2,
- uint16_t arfcn)
-{
- struct l1ctl_pm_conf *pmr;
- uint16_t pm_level[2];
-
- putchart('p');
-
- l1ddsp_meas_read(num_meas, pm_level);
-
- printf("PM MEAS: ARFCN=%u, %-4d dBm at baseband, %-4d dBm at RF\n",
- arfcn, pm_level[0]/8, agc_inp_dbm8_by_pm(pm_level[0])/8);
-
- printd("PM MEAS: %-4d dBm, %-4d dBm ARFCN=%u\n",
- agc_inp_dbm8_by_pm(pm_level[0])/8,
- agc_inp_dbm8_by_pm(pm_level[1])/8, arfcn);
-
- if (!l1s.pm.msg)
- l1s.pm.msg = l1ctl_msgb_alloc(L1CTL_PM_CONF);
-
- if (msgb_tailroom(l1s.pm.msg) < sizeof(*pmr)) {
- /* flush current msgb */
- l1_queue_for_l2(l1s.pm.msg);
- /* allocate a new msgb and initialize header */
- l1s.pm.msg = l1ctl_msgb_alloc(L1CTL_PM_CONF);
- }
-
- pmr = msgb_put(l1s.pm.msg, sizeof(*pmr));
- pmr->band_arfcn = htons(arfcn);
- /* FIXME: do this as RxLev rather than DBM8 ? */
- pmr->pm[0] = dbm2rxlev(agc_inp_dbm8_by_pm(pm_level[0])/8);
- if (num_meas > 1)
- pmr->pm[1] = dbm2rxlev(agc_inp_dbm8_by_pm(pm_level[1])/8);
- else
- pmr->pm[1] = 0;
-
- if (l1s.pm.mode == 1) {
- if (l1s.pm.range.arfcn_next <= l1s.pm.range.arfcn_end) {
- /* schedule PM for next ARFCN in range */
- l1s_pm_test(1, l1s.pm.range.arfcn_next);
- l1s.pm.range.arfcn_next++;
- } else {
- /* we have finished, flush the msgb to L2 */
- struct l1ctl_hdr *l1h = l1s.pm.msg->l1h;
- l1h->flags |= L1CTL_F_DONE;
- l1_queue_for_l2(l1s.pm.msg);
- l1s.pm.msg = NULL;
- }
- }
-
- return 0;
-}
-
-static const struct tdma_sched_item pm_sched_set[] = {
- SCHED_ITEM_DT(l1s_pm_cmd, 0, 1, 0), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_pm_resp, -4, 1, 0), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-/* Schedule a power measurement test */
-void l1s_pm_test(uint8_t base_fn, uint16_t arfcn)
-{
- unsigned long flags;
-
- printd("l1s_pm_test(%u, %u)\n", base_fn, arfcn);
-
- local_firq_save(flags);
- tdma_schedule_set(base_fn, pm_sched_set, arfcn);
- local_irq_restore(flags);
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_rach.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_rach.c
deleted file mode 100644
index 47f7424..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_rach.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Layer 1 Random Access Channel Burst */
-
-/* (C) 2010 by Dieter Spaar <spaar@mirider.augusta.de>
- * (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-#include <asm/system.h>
-
-#include <layer1/sync.h>
-#include <layer1/async.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-
-#include <l1ctl_proto.h>
-
-struct {
- uint32_t fn;
- uint16_t band_arfcn;
-} last_rach;
-
-/* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
-static int l1s_tx_rach_cmd(__unused uint8_t p1, __unused uint8_t p2, __unused uint16_t p3)
-{
- int i;
- uint16_t *info_ptr;
- uint8_t data[2];
-
- putchart('T');
-
- l1s_tx_apc_helper(l1s.serving_cell.arfcn);
-
- data[0] = l1s.serving_cell.bsic << 2;
- data[1] = l1s.rach.ra;
-
- info_ptr = &dsp_api.ndb->d_rach;
- info_ptr[0] = ((uint16_t)(data[0])) | ((uint16_t)(data[1])<<8);
-
- dsp_api.db_w->d_task_ra = RACH_DSP_TASK;
-
- l1s_tx_win_ctrl(l1s.serving_cell.arfcn, L1_TXWIN_AB, 0, 3);
-
- return 0;
-}
-
-/* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
-static int l1s_tx_rach_resp(__unused uint8_t p1, __unused uint8_t burst_id,
- __unused uint16_t p3)
-{
- putchart('t');
-
- dsp_api.r_page_used = 1;
-
- /* schedule a confirmation back indicating the GSM time at which
- * the RACH burst was transmitted to the BTS */
- last_rach.fn = l1s.current_time.fn - 1;
- last_rach.band_arfcn = l1s.serving_cell.arfcn;
- l1s_compl_sched(L1_COMPL_RACH);
-
- return 0;
-}
-
-/* sched sets for uplink */
-const struct tdma_sched_item rach_sched_set_ul[] = {
- SCHED_ITEM_DT(l1s_tx_rach_cmd, 3, 1, 0), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tx_rach_resp, -4, 1, 0), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-/* Asynchronous completion handler for FB detection */
-static void l1a_rach_compl(__unused enum l1_compl c)
-{
- struct msgb *msg;
-
- msg = l1_create_l2_msg(L1CTL_RACH_CONF, last_rach.fn, 0,
- last_rach.band_arfcn);
- l1_queue_for_l2(msg);
-}
-
-static uint8_t t3_to_rach_comb[51] = {
- 0, 0, 0, 0,
- 0, 1,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 26,
- 27, 27, 27, 27};
-static uint8_t rach_to_t3_comb[27] = {
- 4, 5,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
- 45, 46};
-
-/* request a RACH request at the next multiframe T3 = fn51 */
-void l1a_rach_req(uint16_t offset, uint8_t combined, uint8_t ra)
-{
- uint32_t fn_sched;
- unsigned long flags;
-
- offset += 3;
-
- local_firq_save(flags);
- if (combined) {
- /* add elapsed RACH slots to offset */
- offset += t3_to_rach_comb[l1s.current_time.t3];
- /* offset is the number of RACH slots in the future */
- fn_sched = l1s.current_time.fn - l1s.current_time.t3;
- fn_sched += offset / 27 * 51;
- fn_sched += rach_to_t3_comb[offset % 27];
- } else
- fn_sched = l1s.current_time.fn + offset;
- l1s.rach.ra = ra;
- sched_gsmtime(rach_sched_set_ul, fn_sched, 0);
- local_irq_restore(flags);
-
- memset(&last_rach, 0, sizeof(last_rach));
-}
-
-static __attribute__ ((constructor)) void prim_rach_init(void)
-{
- l1s.completion[L1_COMPL_RACH] = &l1a_rach_compl;
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_rx_nb.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_rx_nb.c
deleted file mode 100644
index ea90267..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_rx_nb.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Layer 1 - Receiving Normal Bursts */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-
-#include <layer1/sync.h>
-#include <layer1/afc.h>
-#include <layer1/toa.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-#include <layer1/rfch.h>
-#include <layer1/prim.h>
-
-#include <l1ctl_proto.h>
-
-struct l1s_rxnb_state {
- struct l1s_meas_hdr meas[4];
-
- struct msgb *msg;
- struct l1ctl_info_dl *dl;
- struct l1ctl_data_ind *di;
-};
-
-static struct l1s_rxnb_state rxnb;
-
-static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
-{
- struct gsm_time rx_time;
- uint8_t mf_task_id = p3 & 0xff;
- uint8_t mf_task_flags = p3 >> 8;
- uint16_t rf_arfcn;
- uint8_t tsc, tn;
-
- putchart('n');
-
- /* just for debugging, d_task_d should not be 0 */
- if (dsp_api.db_r->d_task_d == 0) {
- puts("EMPTY\n");
- return 0;
- }
-
- /* DSP burst ID needs to correspond with what we expect */
- if (dsp_api.db_r->d_burst_d != burst_id) {
- printf("BURST ID %u!=%u\n", dsp_api.db_r->d_burst_d, burst_id);
- return 0;
- }
-
- /* get radio parameters for _this_ burst */
- gsm_fn2gsmtime(&rx_time, l1s.current_time.fn - 1);
- rfch_get_params(&rx_time, &rf_arfcn, &tsc, &tn);
-
- /* collect measurements */
- rxnb.meas[burst_id].toa_qbit = dsp_api.db_r->a_serv_demod[D_TOA];
- rxnb.meas[burst_id].pm_dbm8 =
- agc_inp_dbm8_by_pm(dsp_api.db_r->a_serv_demod[D_PM] >> 3);
- rxnb.meas[burst_id].freq_err =
- ANGLE_TO_FREQ(dsp_api.db_r->a_serv_demod[D_ANGLE]);
- rxnb.meas[burst_id].snr = dsp_api.db_r->a_serv_demod[D_SNR];
-
- /* feed computed frequency error into AFC loop */
- if (rxnb.meas[burst_id].snr > AFC_SNR_THRESHOLD)
- afc_input(rxnb.meas[burst_id].freq_err, rf_arfcn, 1);
- else
- afc_input(rxnb.meas[burst_id].freq_err, rf_arfcn, 0);
-
- /* feed computed TOA into TA loop */
- toa_input(rxnb.meas[burst_id].toa_qbit << 2, rxnb.meas[burst_id].snr);
-
- /* Tell the RF frontend to set the gain appropriately */
- rffe_set_gain(rxnb.meas[burst_id].pm_dbm8/8, CAL_DSP_TGT_BB_LVL);
-
- /* 4th burst, get frame data */
- if (dsp_api.db_r->d_burst_d == 3) {
- uint8_t i;
- uint16_t num_biterr;
- uint32_t avg_snr = 0;
- int32_t avg_dbm8 = 0;
-
- /* Get radio parameters for the first burst */
- gsm_fn2gsmtime(&rx_time, l1s.current_time.fn - 4);
- rfch_get_params(&rx_time, &rf_arfcn, &tsc, &tn);
-
- /* Set Channel Number depending on MFrame Task ID */
- rxnb.dl->chan_nr = mframe_task2chan_nr(mf_task_id, tn);
-
- /* Set SACCH indication in Link IDentifier */
- if (mf_task_flags & MF_F_SACCH)
- rxnb.dl->link_id = 0x40;
- else
- rxnb.dl->link_id = 0x00;
-
- rxnb.dl->band_arfcn = htons(rf_arfcn);
-
- rxnb.dl->frame_nr = htonl(rx_time.fn);
-
- /* compute average snr and rx level */
- for (i = 0; i < 4; ++i) {
- avg_snr += rxnb.meas[i].snr;
- avg_dbm8 += rxnb.meas[i].pm_dbm8;
- }
- rxnb.dl->snr = avg_snr / 4;
- rxnb.dl->rx_level = dbm2rxlev(avg_dbm8 / (8*4));
-
- num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
- if (num_biterr > 0xff)
- rxnb.dl->num_biterr = 0xff;
- else
- rxnb.dl->num_biterr = num_biterr;
-
- rxnb.dl->fire_crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
-
- /* update rx level for pm report */
- pu_update_rx_level(rxnb.dl->rx_level);
-
- /* copy actual data, skipping the information block [0,1,2] */
- dsp_memcpy_from_api(rxnb.di->data, &dsp_api.ndb->a_cd[3], 23, 0);
-
- l1_queue_for_l2(rxnb.msg);
- rxnb.msg = NULL; rxnb.dl = NULL; rxnb.di = NULL;
-
- /* clear downlink task */
- dsp_api.db_w->d_task_d = 0;
- }
-
- /* mark READ page as being used */
- dsp_api.r_page_used = 1;
-
- return 0;
-}
-
-static int l1s_nb_cmd(__unused uint8_t p1, uint8_t burst_id,
- __unused uint16_t p3)
-{
- uint16_t arfcn;
- uint8_t tsc, tn;
-
- putchart('N');
-
- if (burst_id == 1) {
- /* allocate message only at 2nd burst in case of
- * consecutive/overlapping normal burst RX tasks */
- /* FIXME: we actually want all allocation out of L1S! */
- if (rxnb.msg) {
- /* Can happen when resetting ... */
- printf("nb_cmd(0) and rxnb.msg != NULL\n");
- msgb_free(rxnb.msg);
- }
- /* allocate msgb as needed. FIXME: from L1A ?? */
- rxnb.msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
- if (!rxnb.msg)
- printf("nb_cmd(0): unable to allocate msgb\n");
- rxnb.dl = (struct l1ctl_info_dl *) msgb_put(rxnb.msg, sizeof(*rxnb.dl));
- rxnb.di = (struct l1ctl_data_ind *) msgb_put(rxnb.msg, sizeof(*rxnb.di));
- }
-
- rfch_get_params(&l1s.next_time, &arfcn, &tsc, &tn);
-
- /* DDL_DSP_TASK, four normal bursts */
- dsp_load_tch_param(&l1s.next_time,
- SIG_ONLY_MODE, SDCCH_4, 0, 0, 0, tn);
-
- dsp_load_rx_task(ALLC_DSP_TASK, burst_id, tsc);
-
- l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB, 0);
-
- return 0;
-}
-
-const struct tdma_sched_item nb_sched_set[] = {
- SCHED_ITEM_DT(l1s_nb_cmd, 0, 0, 0), SCHED_END_FRAME(),
- SCHED_ITEM_DT(l1s_nb_cmd, 0, 0, 1), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_nb_resp, -4, 0, 0), SCHED_ITEM_DT(l1s_nb_cmd, 0, 0, 2), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_nb_resp, -4, 0, 1), SCHED_ITEM_DT(l1s_nb_cmd, 0, 0, 3), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_nb_resp, -4, 0, 2), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_nb_resp, -4, 0, 3), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_tch.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_tch.c
deleted file mode 100644
index 013318d..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_tch.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/* Layer 1 - TCH */
-
-/* (C) 2010 by Dieter Spaar <spaar@mirider.augusta.de>
- * (C) 2010 by Sylvain Munaut <tnt@246tnt.com>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-
-#include <rffe.h>
-#include <layer1/sync.h>
-#include <layer1/afc.h>
-#include <layer1/agc.h>
-#include <layer1/toa.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-#include <layer1/rfch.h>
-#include <layer1/prim.h>
-
-#include <l1ctl_proto.h>
-
-
-/* This computes various parameters both for the DSP and for
- * our logic. Not all are used all the time, but it's easier
- * to build all in one place */
-static void tch_get_params(struct gsm_time *time, uint8_t chan_nr,
- uint32_t *fn_report, uint8_t *tch_f_hn,
- uint8_t *tch_sub, uint8_t *tch_mode)
-{
- uint8_t tn = chan_nr & 0x07;
- uint8_t cbits = chan_nr >> 3;
-
- *tch_f_hn = (cbits & 2) ? 0 : 1;
-
- if (*tch_f_hn) {
- *fn_report = (time->fn - (tn * 13) + 104) % 104;
- *tch_sub = 0;
- } else {
- uint8_t chan_sub = cbits & 1;
- uint8_t tn_report = (tn & ~1) | chan_sub;
- *fn_report = (time->fn - (tn_report * 13) + 104) % 104;
- *tch_sub = chan_sub;
- }
-
- if (tch_mode) {
- switch (l1s.tch_mode) {
- case GSM48_CMODE_SPEECH_V1:
- *tch_mode = *tch_f_hn ? TCH_FS_MODE : TCH_HS_MODE;
- break;
- case GSM48_CMODE_SPEECH_EFR:
- *tch_mode = *tch_f_hn ? TCH_EFR_MODE : SIG_ONLY_MODE;
- break;
- default:
- *tch_mode = SIG_ONLY_MODE;
- }
- }
-}
-
-
-/* -------------------------------------------------------------------------
- * Shared completion handler
- * ------------------------------------------------------------------------- */
-
-/*
- * FIXME We really need a better way to handle completion, where we can
- * pass arguments and such ...
- *
- * Right now, we just 'hope' it gets processed before the next one ...
- */
-
-static uint16_t last_tx_tch_fn;
-
-static void l1a_tx_tch_compl(__unused enum l1_compl c)
-{
- struct msgb *msg;
-
- msg = l1_create_l2_msg(L1CTL_DATA_CONF, last_tx_tch_fn, 0, 0);
- l1_queue_for_l2(msg);
-}
-
-static __attribute__ ((constructor)) void prim_tch_init(void)
-{
- l1s.completion[L1_COMPL_TX_TCH] = &l1a_tx_tch_compl;
-}
-
-
-/* -------------------------------------------------------------------------
- * TCH: Voice & FACCH
- * ------------------------------------------------------------------------- */
-
-/*
- * Voice and FACCH data are spread in various ways depending on a lot of
- * factors. Trying to handle that with the mframe scheduler is just a mess,
- * so we schedule it burst by burst and handle the complex logic inside the
- * primitive task code itself.
- */
-
-
-#define FACCH_MEAS_HIST 8 /* Up to 8 bursts history */
-struct l1s_rx_tch_state {
- struct l1s_meas_hdr meas[FACCH_MEAS_HIST];
-};
-
-static struct l1s_rx_tch_state rx_tch;
-
-
-static int l1s_tch_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
-{
- static uint8_t meas_id = 0;
- uint8_t mf_task_id = p3 & 0xff;
- struct gsm_time rx_time;
- uint8_t chan_nr;
- uint16_t arfcn;
- uint8_t tsc, tn;
- uint8_t tch_f_hn, tch_sub;
- uint32_t fn_report;
- int facch_rx_now, traffic_rx_now;
-
- /* Get/compute various parameters */
- gsm_fn2gsmtime(&rx_time, (l1s.current_time.fn - 1 + GSM_MAX_FN) % GSM_MAX_FN);
- rfch_get_params(&rx_time, &arfcn, &tsc, &tn);
- chan_nr = mframe_task2chan_nr(mf_task_id, tn);
- tch_get_params(&rx_time, chan_nr, &fn_report, &tch_f_hn, &tch_sub, NULL);
-
- meas_id = (meas_id + 1) % FACCH_MEAS_HIST; /* absolute value doesn't matter */
-
- /* Collect measurements */
- rx_tch.meas[meas_id].toa_qbit = dsp_api.db_r->a_serv_demod[D_TOA];
- rx_tch.meas[meas_id].pm_dbm8 =
- agc_inp_dbm8_by_pm(dsp_api.db_r->a_serv_demod[D_PM] >> 3);
- rx_tch.meas[meas_id].freq_err =
- ANGLE_TO_FREQ(dsp_api.db_r->a_serv_demod[D_ANGLE]);
- rx_tch.meas[meas_id].snr = dsp_api.db_r->a_serv_demod[D_SNR];
-
- /* feed computed frequency error into AFC loop */
- if (rx_tch.meas[meas_id].snr > AFC_SNR_THRESHOLD)
- afc_input(rx_tch.meas[meas_id].freq_err, arfcn, 1);
- else
- afc_input(rx_tch.meas[meas_id].freq_err, arfcn, 0);
-
- /* feed computed TOA into TA loop */
- toa_input(rx_tch.meas[meas_id].toa_qbit << 2, rx_tch.meas[meas_id].snr);
-
- /* Tell the RF frontend to set the gain appropriately */
- rffe_set_gain(rx_tch.meas[meas_id].pm_dbm8 / 8, CAL_DSP_TGT_BB_LVL);
-
- /* FACCH Block end ? */
- if (tch_f_hn) {
- /* FACCH/F: B0(0...7),B1(4...11),B2(8...11,0...3) (mod 13) */
- facch_rx_now = ((rx_time.fn % 13) % 4) == 3;
- } else {
- /* FAACH/H: See GSM 05.02 Clause 7 Table 1of9 */
- uint8_t t2_norm = rx_time.t2 - tch_sub;
- facch_rx_now = (t2_norm == 15) ||
- (t2_norm == 23) ||
- (t2_norm == 6);
- }
-
- if (facch_rx_now && (dsp_api.ndb->a_fd[0] & (1<<B_BLUD))) {
- struct msgb *msg;
- struct l1ctl_info_dl *dl;
- struct l1ctl_data_ind *di;
- uint16_t num_biterr;
- uint32_t avg_snr = 0;
- int32_t avg_dbm8 = 0;
- int i, n;
-
- /* Allocate msgb */
- /* FIXME: we actually want all allocation out of L1S! */
- msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
- if(!msg) {
- printf("TCH FACCH: unable to allocate msgb\n");
- goto skip;
- }
-
- dl = (struct l1ctl_info_dl *) msgb_put(msg, sizeof(*dl));
- di = (struct l1ctl_data_ind *) msgb_put(msg, sizeof(*di));
-
- /* Fill DL header (should be about the first burst ... here is the last) */
- dl->chan_nr = chan_nr;
- dl->link_id = 0x00; /* FACCH */
- dl->band_arfcn = htons(arfcn);
- dl->frame_nr = htonl(rx_time.fn);
-
- /* Average SNR & RX level */
- n = tch_f_hn ? 8 : 6;
- for (i=0; i<n; i++) {
- int j = (meas_id + FACCH_MEAS_HIST - i) % FACCH_MEAS_HIST;
- avg_snr += rx_tch.meas[j].snr;
- avg_dbm8 += rx_tch.meas[j].pm_dbm8;
- }
-
- dl->snr = avg_snr / n;
- dl->rx_level = dbm2rxlev(avg_dbm8 / (8*n));
-
- /* Errors & CRC status */
- num_biterr = dsp_api.ndb->a_fd[2] & 0xffff;
- if (num_biterr > 0xff)
- dl->num_biterr = 0xff;
- else
- dl->num_biterr = num_biterr;
-
- dl->fire_crc = ((dsp_api.ndb->a_fd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
-
- /* Update rx level for pm report */
- pu_update_rx_level(dl->rx_level);
-
- /* Copy actual data, skipping the information block [0,1,2] */
- dsp_memcpy_from_api(di->data, &dsp_api.ndb->a_fd[3], 23, 0);
-
- /* Give message to up layer */
- l1_queue_for_l2(msg);
-
- skip:
- /* Reset A_FD header (needed by DSP) */
- /* B_FIRE1 =1, B_FIRE0 =0 , BLUD =0 */
- dsp_api.ndb->a_fd[0] = (1<<B_FIRE1);
- dsp_api.ndb->a_fd[2] = 0xffff;
-
- /* Reset A_DD_0 header in NDB (needed by DSP) */
- dsp_api.ndb->a_dd_0[0] = 0;
- dsp_api.ndb->a_dd_0[2] = 0xffff;
-
- /* Reset A_DD_1 header in NDB (needed by DSP) */
- dsp_api.ndb->a_dd_1[0] = 0;
- dsp_api.ndb->a_dd_1[2] = 0xffff;
- }
-
- /* Traffic now ? */
- if (tch_f_hn) {
- /* TCH/F: B0(0...7),B1(4...11),B2(8...11,0...3) (mod 13)*/
- traffic_rx_now = ((rx_time.fn % 13) % 4) == 3;
- } else {
- /* TCH/H0: B0(0,2,4,6),B1(4,6,8,10),B2(8,10,0,2) (mod 13) */
- /* H1: B0(1,3,5,7),B1(5,7,9,11),B2(9,11,1,3) (mod 13) */
- traffic_rx_now = (((rx_time.fn - tch_sub + 13) % 13) % 4) == 2;
- }
-
- if (traffic_rx_now) {
- volatile uint16_t *traffic_buf;
-
- traffic_buf = tch_sub ? dsp_api.ndb->a_dd_1 : dsp_api.ndb->a_dd_0;
-
- if (traffic_buf[0] & (1<<B_BLUD)) {
- /* Reset traffic buffer header in NDB (needed by DSP) */
- traffic_buf[0] = 0;
- traffic_buf[2] = 0xffff;
- }
- }
-
- /* mark READ page as being used */
- dsp_api.r_page_used = 1;
-
- return 0;
-}
-
-static int l1s_tch_cmd(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
-{
- uint8_t mf_task_id = p3 & 0xff;
- uint8_t chan_nr;
- uint16_t arfcn;
- uint8_t tsc, tn;
- uint8_t tch_f_hn, tch_sub, tch_mode;
- uint32_t fn_report;
- uint8_t sync = 0;
- static int icnt;
- int facch_tx_now;
-
- /* Get/compute various parameters */
- rfch_get_params(&l1s.next_time, &arfcn, &tsc, &tn);
- chan_nr = mframe_task2chan_nr(mf_task_id, tn);
- tch_get_params(&l1s.next_time, chan_nr, &fn_report, &tch_f_hn, &tch_sub, &tch_mode);
-
- /* Sync & FACCH delay */
- if (l1s.tch_sync) {
- l1s.tch_sync = 0;
- sync = 1;
- icnt = 0;
- } else if (icnt <= 26)
- icnt++;
-
- /* Load FACCH data if we start a new burst */
- /* (the DSP wants the data on the CMD of the burst _preceding_ the
- * first burst) */
- if (tch_f_hn) {
- /* FACCH/F: B0(0...7),B1(4...11),B2(8...11,0...3) */
- facch_tx_now = ((l1s.next_time.fn % 13) % 4) == 3;
- } else {
- /* FAACH/H: See GSM 05.02 Clause 7 Table 1of9 */
- uint8_t t2_norm = l1s.next_time.t2 - tch_sub;
- facch_tx_now = (t2_norm == 23) ||
- (t2_norm == 6) ||
- (t2_norm == 15);
- }
-
- if (facch_tx_now) {
- uint16_t *info_ptr = dsp_api.ndb->a_fu;
- struct msgb *msg;
- const uint8_t *data;
-
- /* Pull FACCH data (if ready) */
- if (icnt > 26)
- msg = msgb_dequeue(&l1s.tx_queue[L1S_CHAN_MAIN]);
- else
- msg = NULL;
-
- /* If TX is empty and we're signalling only, use dummy frame */
- if (msg)
- data = msg->l3h;
- else if (tch_mode == SIG_ONLY_MODE)
- data = pu_get_idle_frame();
- else
- data = NULL;
-
- /* Do we really send something ? */
- if (data) {
- /* Fill data block header */
- info_ptr[0] = (1 << B_BLUD); /* 1st word: Set B_BLU bit. */
- info_ptr[1] = 0; /* 2nd word: cleared. */
- info_ptr[2] = 0; /* 3nd word: cleared. */
-
- /* Copy the actual data after the header */
- dsp_memcpy_to_api(&info_ptr[3], data, 23, 0);
- }
-
- /* Indicate completion (FIXME: early but easier this way for now) */
- if (msg) {
- last_tx_tch_fn = l1s.next_time.fn;
- l1s_compl_sched(L1_COMPL_TX_TCH);
- }
-
- /* Free msg now that we're done with it */
- if (msg)
- msgb_free(msg);
- }
-
- /* Configure DSP for TX/RX */
- l1s_tx_apc_helper(arfcn);
-
- dsp_load_tch_param(
- &l1s.next_time,
- tch_mode, tch_f_hn ? TCH_F : TCH_H, tch_sub,
- 0, sync, tn
- );
-
- dsp_load_rx_task(TCHT_DSP_TASK, 0, tsc); /* burst_id unused for TCH */
- l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB, 0);
-
- dsp_load_tx_task(TCHT_DSP_TASK, 0, tsc); /* burst_id unused for TCH */
- l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB, 0, 3);
-
- return 0;
-}
-
-
-const struct tdma_sched_item tch_sched_set[] = {
- SCHED_ITEM_DT(l1s_tch_cmd, 0, 0, 0), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tch_resp, 0, 0, -4), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-
-/* -------------------------------------------------------------------------
- * TCH/H: Dummy
- * ------------------------------------------------------------------------- */
-
-/* This task is needed to perform some operation in the DSP when there is
- * no data to be exchanged */
-
-static int l1s_tch_d_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
-{
- /* mark READ page as being used */
- dsp_api.r_page_used = 1;
-
- return 0;
-}
-
-static int l1s_tch_d_cmd(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
-{
- uint8_t mf_task_id = p3 & 0xff;
- uint8_t chan_nr;
- uint8_t tsc, tn;
- uint8_t tch_f_hn, tch_sub, tch_mode;
- uint32_t fn_report;
-
- /* Get/compute various parameters */
- rfch_get_params(&l1s.next_time, NULL, &tsc, &tn);
- chan_nr = mframe_task2chan_nr(mf_task_id, tn);
- tch_get_params(&l1s.next_time, chan_nr, &fn_report, &tch_f_hn, &tch_sub, &tch_mode);
-
- /* Configure DSP */
- dsp_load_tch_param(
- &l1s.next_time,
- tch_mode, tch_f_hn ? TCH_F : TCH_H, tch_sub,
- 0, 0, tn
- );
-
- dsp_load_rx_task(TCHD_DSP_TASK, 0, tsc); /* burst_id unused for TCH */
- dsp_load_tx_task(TCHD_DSP_TASK, 0, tsc); /* burst_id unused for TCH */
-
- return 0;
-}
-
-const struct tdma_sched_item tch_d_sched_set[] = {
- SCHED_ITEM_DT(l1s_tch_d_cmd, 0, 0, 0), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tch_d_resp, 0, 0, -4), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-
-/* -------------------------------------------------------------------------
- * TCH: SACCH
- * ------------------------------------------------------------------------- */
-
-/*
- * SACCH data are spread over 4 bursts, however they are so far appart that
- * we can't use the normal scheduler to schedule all them at once in a single
- * set.
- * Therefore, the task code itself decides in which burst it is, if it's the
- * start/end, and act appropriately.
- */
-
-
-struct l1s_rx_tch_a_state {
- struct l1s_meas_hdr meas[4];
-
- struct msgb *msg;
- struct l1ctl_info_dl *dl;
- struct l1ctl_data_ind *di;
-};
-
-static struct l1s_rx_tch_a_state rx_tch_a;
-
-
-static int l1s_tch_a_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
-{
- uint8_t mf_task_id = p3 & 0xff;
- struct gsm_time rx_time;
- uint8_t chan_nr;
- uint16_t arfcn;
- uint8_t tsc, tn;
- uint8_t tch_f_hn, tch_sub;
- uint32_t fn_report;
- uint8_t burst_id;
-
- /* It may happen we've never gone through cmd(0) yet, skip until then */
- if (!rx_tch_a.msg)
- goto skip;
-
- /* Get/compute various parameters */
- gsm_fn2gsmtime(&rx_time, (l1s.current_time.fn - 1 + GSM_MAX_FN) % GSM_MAX_FN);
- rfch_get_params(&rx_time, &arfcn, &tsc, &tn);
- chan_nr = mframe_task2chan_nr(mf_task_id, tn);
- tch_get_params(&rx_time, chan_nr, &fn_report, &tch_f_hn, &tch_sub, NULL);
- burst_id = (fn_report - 12) / 26;
-
- /* Collect measurements */
- rx_tch_a.meas[burst_id].toa_qbit = dsp_api.db_r->a_serv_demod[D_TOA];
- rx_tch_a.meas[burst_id].pm_dbm8 =
- agc_inp_dbm8_by_pm(dsp_api.db_r->a_serv_demod[D_PM] >> 3);
- rx_tch_a.meas[burst_id].freq_err =
- ANGLE_TO_FREQ(dsp_api.db_r->a_serv_demod[D_ANGLE]);
- rx_tch_a.meas[burst_id].snr = dsp_api.db_r->a_serv_demod[D_SNR];
-
- /* feed computed frequency error into AFC loop */
- if (rx_tch_a.meas[burst_id].snr > AFC_SNR_THRESHOLD)
- afc_input(rx_tch_a.meas[burst_id].freq_err, arfcn, 1);
- else
- afc_input(rx_tch_a.meas[burst_id].freq_err, arfcn, 0);
-
- /* feed computed TOA into TA loop */
- toa_input(rx_tch_a.meas[burst_id].toa_qbit << 2, rx_tch_a.meas[burst_id].snr);
-
- /* Tell the RF frontend to set the gain appropriately */
- rffe_set_gain(rx_tch_a.meas[burst_id].pm_dbm8 / 8, CAL_DSP_TGT_BB_LVL);
-
- /* Last burst, read data & send to the up layer */
- if ((burst_id == 3) && (dsp_api.ndb->a_cd[0] & (1<<B_BLUD))) {
- unsigned int i;
- uint16_t num_biterr;
- uint32_t avg_snr = 0;
- int32_t avg_dbm8 = 0;
-
- /* Average SNR & RX level + error & crc status */
- for (i=0; i<4; i++) {
- avg_snr += rx_tch_a.meas[i].snr;
- avg_dbm8 += rx_tch_a.meas[i].pm_dbm8;
- }
- rx_tch_a.dl->snr = avg_snr / 4;
- rx_tch_a.dl->rx_level = dbm2rxlev(avg_dbm8 / (8*4));
-
- num_biterr = dsp_api.ndb->a_cd[2];
- if (num_biterr > 0xff)
- rx_tch_a.dl->num_biterr = 0xff;
- else
- rx_tch_a.dl->num_biterr = num_biterr;
-
- rx_tch_a.dl->fire_crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
-
- /* Update rx level for pm report */
- pu_update_rx_level(rx_tch_a.dl->rx_level);
-
- /* Copy actual data, skipping the information block [0,1,2] */
- dsp_memcpy_from_api(rx_tch_a.di->data, &dsp_api.ndb->a_cd[3], 23, 0);
-
- /* Give message to up layer */
- l1_queue_for_l2(rx_tch_a.msg);
- rx_tch_a.msg = NULL; rx_tch_a.dl = NULL; rx_tch_a.di = NULL;
-
- /* Reset header */
- dsp_api.ndb->a_cd[0] = (1<<B_FIRE1);
- dsp_api.ndb->a_cd[2] = 0xffff;
- }
-
-skip:
- /* mark READ page as being used */
- dsp_api.r_page_used = 1;
-
- return 0;
-}
-
-static int l1s_tch_a_cmd(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
-{
- uint8_t mf_task_id = p3 & 0xff;
- uint8_t chan_nr;
- uint16_t arfcn;
- uint8_t tsc, tn;
- uint8_t tch_f_hn, tch_sub, tch_mode;
- uint32_t fn_report;
- uint8_t burst_id;
-
- /* Get/compute various parameters */
- rfch_get_params(&l1s.next_time, &arfcn, &tsc, &tn);
- chan_nr = mframe_task2chan_nr(mf_task_id, tn);
- tch_get_params(&l1s.next_time, chan_nr, &fn_report, &tch_f_hn, &tch_sub, &tch_mode);
- burst_id = (fn_report - 12) / 26;
-
- /* Load SACCH data if we start a new burst */
- if (burst_id == 0) {
- uint16_t *info_ptr = dsp_api.ndb->a_cu;
- struct msgb *msg;
- const uint8_t *data;
-
- /* If the TX queue is empty, send dummy measurement */
- msg = msgb_dequeue(&l1s.tx_queue[L1S_CHAN_SACCH]);
- data = msg ? msg->l3h : pu_get_meas_frame();
-
- /* Fill data block header */
- info_ptr[0] = (1 << B_BLUD); /* 1st word: Set B_BLU bit. */
- info_ptr[1] = 0; /* 2nd word: cleared. */
- info_ptr[2] = 0; /* 3nd word: cleared. */
-
- /* Copy the actual data after the header */
- dsp_memcpy_to_api(&info_ptr[3], data, 23, 0);
-
- /* Indicate completion (FIXME: early but easier this way for now) */
- if (msg) {
- last_tx_tch_fn = l1s.next_time.fn;
- l1s_compl_sched(L1_COMPL_TX_TCH);
- }
-
- /* Free msg now that we're done with it */
- if (msg)
- msgb_free(msg);
- }
-
- /* Allocate RX burst */
- if (burst_id == 0) {
- /* Clear 'dangling' msgb */
- if (rx_tch_a.msg) {
- /* Can happen if the task was shutdown in the middle of
- * 4 bursts ... */
- msgb_free(rx_tch_a.msg);
- }
-
- /* Allocate burst */
- /* FIXME: we actually want all allocation out of L1S! */
- rx_tch_a.msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
- if (!rx_tch_a.msg)
- printf("tch_a_cmd(0): unable to allocate msgb\n");
-
- rx_tch_a.dl = (struct l1ctl_info_dl *) msgb_put(rx_tch_a.msg, sizeof(*rx_tch_a.dl));
- rx_tch_a.di = (struct l1ctl_data_ind *) msgb_put(rx_tch_a.msg, sizeof(*rx_tch_a.di));
-
- /* Pre-fill DL header with some info about burst(0) */
- rx_tch_a.dl->chan_nr = chan_nr;
- rx_tch_a.dl->link_id = 0x40; /* SACCH */
- rx_tch_a.dl->band_arfcn = htons(arfcn);
- rx_tch_a.dl->frame_nr = htonl(l1s.next_time.fn);
- }
-
- /* Configure DSP for TX/RX */
- l1s_tx_apc_helper(arfcn);
-
- dsp_load_tch_param(
- &l1s.next_time,
- tch_mode, tch_f_hn ? TCH_F : TCH_H, tch_sub,
- 0, 0, tn
- );
-
- dsp_load_rx_task(TCHA_DSP_TASK, 0, tsc); /* burst_id unused for TCHA */
- l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB, 0);
-
- dsp_load_tx_task(TCHA_DSP_TASK, 0, tsc); /* burst_id unused for TCHA */
- l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB, 0, 3);
-
- return 0;
-}
-
-
-const struct tdma_sched_item tch_a_sched_set[] = {
- SCHED_ITEM_DT(l1s_tch_a_cmd, 0, 0, 0), SCHED_END_FRAME(),
- SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tch_a_resp, 0, 0, -4), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_tx_nb.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_tx_nb.c
deleted file mode 100644
index 3038178..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_tx_nb.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Layer 1 - Transmit Normal Burst */
-
-/* (C) 2010 by Dieter Spaar <spaar@mirider.augusta.de>
- * (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-
-#include <layer1/sync.h>
-#include <layer1/agc.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-#include <layer1/rfch.h>
-#include <layer1/prim.h>
-
-#include <l1ctl_proto.h>
-
-
-static uint32_t last_txnb_fn;
-
-/* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB) */
-static int l1s_tx_resp(__unused uint8_t p1, __unused uint8_t burst_id,
- __unused uint16_t p3)
-{
- putchart('t');
-
- dsp_api.r_page_used = 1;
-
- if (burst_id == 3) {
- last_txnb_fn = l1s.current_time.fn - 4;
- l1s_compl_sched(L1_COMPL_TX_NB);
- }
-
- return 0;
-}
-
-/* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB) */
-static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
-{
- uint16_t arfcn;
- uint8_t tsc, tn;
- uint8_t mf_task_id = p3 & 0xff;
- uint8_t mf_task_flags = p3 >> 8;
-
- putchart('T');
-
- /* before sending first of the four bursts, copy data to API ram */
- if (burst_id == 0) {
- uint16_t *info_ptr = dsp_api.ndb->a_cu;
- struct msgb *msg;
- const uint8_t *data;
-
- /* distinguish between DCCH and ACCH */
- if (mf_task_flags & MF_F_SACCH) {
- msg = msgb_dequeue(&l1s.tx_queue[L1S_CHAN_SACCH]);
- data = msg ? msg->l3h : pu_get_meas_frame();
- } else {
- msg = msgb_dequeue(&l1s.tx_queue[L1S_CHAN_MAIN]);
- data = msg ? msg->l3h : pu_get_idle_frame();
- }
-
- /* Fill data block Header */
- info_ptr[0] = (1 << B_BLUD); // 1st word: Set B_BLU bit.
- info_ptr[1] = 0; // 2nd word: cleared.
- info_ptr[2] = 0; // 3rd word: cleared.
-
- /* Copy the actual data after the header */
- dsp_memcpy_to_api(&info_ptr[3], data, 23, 0);
-
- if (msg)
- msgb_free(msg);
- }
-
- rfch_get_params(&l1s.next_time, &arfcn, &tsc, &tn);
-
- l1s_tx_apc_helper(arfcn);
-
- if (p1 == 0)
- /* DUL_DSP_TASK, one normal burst */
- dsp_load_tch_param(&l1s.next_time,
- SIG_ONLY_MODE, INVALID_CHANNEL, 0, 0, 0, tn);
-
- else if (p1 == 2)
- /* DUL_DSP_TASK, four normal bursts */
- dsp_load_tch_param(&l1s.next_time,
- SIG_ONLY_MODE, SDCCH_4, 0, 0, 0, tn);
-
- dsp_load_tx_task(DUL_DSP_TASK, burst_id, tsc);
-
- l1s_tx_win_ctrl(arfcn, L1_TXWIN_NB, 0, 3);
-
- return 0;
-}
-
-/* Asynchronous completion handler for NB transmit */
-static void l1a_tx_nb_compl(__unused enum l1_compl c)
-{
- struct msgb *msg;
-
- msg = l1_create_l2_msg(L1CTL_DATA_CONF, last_txnb_fn, 0, 0);
- l1_queue_for_l2(msg);
-}
-
-void l1s_tx_test(uint8_t base_fn, uint8_t type)
-{
- printf("Starting TX %d\n", type);
-
- if (type == 0) {// one normal burst
- tdma_schedule(base_fn, &l1s_tx_cmd, 0, 0, 0, 3);
- tdma_schedule(base_fn + 2, &l1s_tx_resp, 0, 0, 0, 3);
- } else if (type == 2) { // four normal bursts
- tdma_schedule(base_fn, &l1s_tx_cmd, 2, 0, 0, 3);
- tdma_schedule(base_fn + 1, &l1s_tx_cmd, 2, 1, 0, 3);
- tdma_schedule(base_fn + 2, &l1s_tx_resp, 2, 0, 0, 3);
- tdma_schedule(base_fn + 2, &l1s_tx_cmd, 2, 2, 0, 3);
- tdma_schedule(base_fn + 3, &l1s_tx_resp, 2, 1, 0, 3);
- tdma_schedule(base_fn + 3, &l1s_tx_cmd, 2, 3, 0, 3);
- tdma_schedule(base_fn + 4, &l1s_tx_resp, 2, 2, 0, 3);
- tdma_schedule(base_fn + 5, &l1s_tx_resp, 2, 3, 0, 3);
- }
-}
-
-/* sched sets for uplink */
-const struct tdma_sched_item nb_sched_set_ul[] = {
- SCHED_ITEM_DT(l1s_tx_cmd, 3, 2, 0), SCHED_END_FRAME(),
- SCHED_ITEM_DT(l1s_tx_cmd, 3, 2, 1), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tx_resp, -4, 2, 0), SCHED_ITEM_DT(l1s_tx_cmd, 3, 2, 2), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tx_resp, -4, 2, 1), SCHED_ITEM_DT(l1s_tx_cmd, 3, 2, 3), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tx_resp, -4, 2, 2), SCHED_END_FRAME(),
- SCHED_ITEM(l1s_tx_resp, -4, 2, 3), SCHED_END_FRAME(),
- SCHED_END_SET()
-};
-
-static __attribute__ ((constructor)) void prim_tx_nb_init(void)
-{
- l1s.completion[L1_COMPL_TX_NB] = &l1a_tx_nb_compl;
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/prim_utils.c b/Src/osmocom-bb/src/target/firmware/layer1/prim_utils.c
deleted file mode 100644
index c85da71..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/prim_utils.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Layer 1 Various primitive utilities */
-
-/* (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-
-#include <osmocom/core/msgb.h>
-#include <layer1/sync.h>
-
-
-static const uint8_t ubUui[23] = {
- /* dummy lapdm header */
- 0x01, 0x03, 0x01,
-
- /* fill bytes */
- 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
- 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
- 0x2b, 0x2b, 0x2b, 0x2b
-};
-
-static uint8_t ubMeas[23] = {
- /* L1 SAACH pseudo-header */
- 0x0f, 0x00,
-
- /* lapdm header */
- 0x01, 0x03, 0x49,
-
- /* Measurement report */
- 0x06, 0x15, 0x36, 0x36, 0x01, 0xC0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
-};
-
-
-const uint8_t *pu_get_idle_frame(void)
-{
- return ubUui;
-}
-
-void pu_update_rx_level(uint8_t rx_level)
-{
- ubMeas[7] = ubMeas[8] = rx_level;
-}
-
-const uint8_t *pu_get_meas_frame(void)
-{
- if (l1s.tx_meas) {
- return l1s.tx_meas->l3h;
- } else {
- /* Update L1 SAACH pseudo-header */
- ubMeas[0] = l1s.tx_power;
- ubMeas[1] = l1s.ta;
-
- return ubMeas;
- }
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/rfch.c b/Src/osmocom-bb/src/target/firmware/layer1/rfch.c
deleted file mode 100644
index d0818d0..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/rfch.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* RF Channel utilities */
-
-/* (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <layer1/sync.h>
-
-
-/*
- * Hopping sequence generation
- *
- * The algorithm is explained in GSM 05.02 Section 6.2.3
- *
- * if HSN = 0 (cyclic hopping) then:
- * MAI, integer (0 .. N-1) :
- * MAI = (FN + MAIO) modulo N
- *
- * else:
- * M, integer (0 .. 152) :
- * M = T2 + RNTABLE((HSN xor T1R) + T3)
- *
- * S, integer (0 .. N-1) :
- * M' = M modulo (2 ^ NBIN)
- * T' = T3 modulo (2 ^ NBIN)
- *
- * if M' < N then:
- * S = M'
- * else:
- * S = (M'+T') modulo N
- *
- * MAI, integer (0 .. N-1) :
- * MAI = (S + MAIO) modulo N
- */
-
-static uint8_t rn_table[114] = {
- 48, 98, 63, 1, 36, 95, 78, 102, 94, 73,
- 0, 64, 25, 81, 76, 59, 124, 23, 104, 100,
- 101, 47, 118, 85, 18, 56, 96, 86, 54, 2,
- 80, 34, 127, 13, 6, 89, 57, 103, 12, 74,
- 55, 111, 75, 38, 109, 71, 112, 29, 11, 88,
- 87, 19, 3, 68, 110, 26, 33, 31, 8, 45,
- 82, 58, 40, 107, 32, 5, 106, 92, 62, 67,
- 77, 108, 122, 37, 60, 66, 121, 42, 51, 126,
- 117, 114, 4, 90, 43, 52, 53, 113, 120, 72,
- 16, 49, 7, 79, 119, 61, 22, 84, 9, 97,
- 91, 15, 21, 24, 46, 39, 93, 105, 65, 70,
- 125, 99, 17, 123,
-};
-
-
-static int pow_nbin_mask(int n)
-{
- int x;
- x = (n ) |
- (n >> 1) |
- (n >> 2) |
- (n >> 3) |
- (n >> 4) |
- (n >> 5) |
- (n >> 6);
- return x;
-}
-
-static int16_t rfch_hop_seq_gen(struct gsm_time *t,
- uint8_t hsn, uint8_t maio,
- uint8_t n, uint16_t *arfcn_tbl)
-{
- int mai;
-
- if (!hsn) {
- /* cyclic hopping */
- mai = (t->fn + maio) % n;
- } else {
- /* pseudo random hopping */
- int m, mp, tp, s, pnm;
-
- pnm = pow_nbin_mask(n);
-
- m = t->t2 + rn_table[(hsn ^ (t->t1 & 63)) + t->t3];
- mp = m & pnm;
-
- if (mp < n)
- s = mp;
- else {
- tp = t->t3 & pnm;
- s = (mp + tp) % n;
- }
-
- mai = (s + maio) % n;
- }
-
- return arfcn_tbl ? arfcn_tbl[mai] : mai;
-}
-
-
-/* RF Channel parameters */
-void rfch_get_params(struct gsm_time *t,
- uint16_t *arfcn_p, uint8_t *tsc_p, uint8_t *tn_p)
-{
- if (l1s.dedicated.type == GSM_DCHAN_NONE) {
- /* Serving cell only */
- if (arfcn_p)
- *arfcn_p = l1s.serving_cell.arfcn;
-
- if (tsc_p)
- *tsc_p = l1s.serving_cell.bsic & 0x7;
-
- if (tn_p)
- *tn_p = 0;
- } else {
- /* Dedicated channel */
- if (arfcn_p) {
- if (l1s.dedicated.h) {
- *arfcn_p = rfch_hop_seq_gen(t,
- l1s.dedicated.h1.hsn,
- l1s.dedicated.h1.maio,
- l1s.dedicated.h1.n,
- l1s.dedicated.h1.ma);
- } else {
- *arfcn_p = l1s.dedicated.h0.arfcn;
- }
- }
-
- if (tsc_p)
- *tsc_p = l1s.dedicated.tsc;
-
- if (tn_p)
- *tn_p = l1s.dedicated.tn;
- }
-}
-
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/sched_gsmtime.c b/Src/osmocom-bb/src/target/firmware/layer1/sched_gsmtime.c
deleted file mode 100644
index 01e22ca..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/sched_gsmtime.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* GSM-Time One-shot Event Scheduler Implementation (on top of TDMA sched) */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <errno.h>
-
-#include <debug.h>
-#include <osmocom/core/linuxlist.h>
-
-#include <layer1/tdma_sched.h>
-#include <layer1/sched_gsmtime.h>
-
-static struct sched_gsmtime_event sched_gsmtime_events[16];
-static LLIST_HEAD(active_evts);
-static LLIST_HEAD(inactive_evts);
-
-/* Scheduling of a tdma_sched_item list one-shot at a given GSM time */
-int sched_gsmtime(const struct tdma_sched_item *si, uint32_t fn, uint16_t p3)
-{
- struct llist_head *lh;
- struct sched_gsmtime_event *evt, *cur;
-
- printd("sched_gsmtime(si=%p, fn=%u)\n", si, fn);
-
- /* obtain a free/inactive event structure */
- if (llist_empty(&inactive_evts))
- return -EBUSY;
- lh = inactive_evts.next;
- llist_del(lh);
- evt = llist_entry(lh, struct sched_gsmtime_event, list);
-
- evt->fn = fn;
- evt->si = si;
- evt->p3 = p3;
-
- /* do a sorted insert into the list, i.e. insert the new
- * event _before_ the first entry that has a higher fn */
- llist_for_each_entry(cur, &active_evts, list) {
- if (cur->fn > evt->fn) {
- llist_add_tail(lh, &cur->list);
- return 0;
- }
- }
-
- /* if we reach here, active_evts is empty _OR_ new event
- * is after all the other events: append at end of list */
- llist_add_tail(lh, &active_evts);
-
- return 0;
-}
-
-/* how many TDMA frame ticks should we schedule events ahead? */
-#define SCHEDULE_AHEAD 2
-
-/* how long do we need to tell the DSP in advance what we want to do? */
-#define SCHEDULE_LATENCY 1
-
-/* execute all GSMTIME one-shot events pending for 'fn' */
-int sched_gsmtime_execute(uint32_t fn)
-{
- struct sched_gsmtime_event *evt, *evt2;
- int num = 0;
-
- llist_for_each_entry_safe(evt, evt2, &active_evts, list) {
- if (evt->fn == fn + SCHEDULE_AHEAD) {
- printd("sched_gsmtime_execute(time=%u): fn=%u si=%p\n", fn, evt->fn, evt->si);
- tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
- evt->si, evt->p3);
- llist_del(&evt->list);
- /* put event back in list of inactive (free) events */
- llist_add(&evt->list, &inactive_evts);
- num++;
- } if (evt->fn > fn + SCHEDULE_AHEAD) {
- /* break the loop as our list is ordered */
- break;
- }
- }
- return num;
-}
-
-void sched_gsmtime_init(void)
-{
- unsigned int i;
-
- printd("sched_gsmtime_init()\n");
-
- for (i = 0; i < ARRAY_SIZE(sched_gsmtime_events); i++)
- llist_add(&sched_gsmtime_events[i].list, &inactive_evts);
-}
-
-void sched_gsmtime_reset(void)
-{
- struct sched_gsmtime_event *evt, *evt2;
-
- llist_for_each_entry_safe(evt, evt2, &active_evts, list) {
- llist_del(&evt->list);
- /* put event back in list of inactive (free) events */
- llist_add(&evt->list, &inactive_evts);
- }
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/sync.c b/Src/osmocom-bb/src/target/firmware/layer1/sync.c
deleted file mode 100644
index 36f4297..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/sync.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/* Synchronous part of GSM Layer 1 */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010 by Dieter Spaar <spaar@mirider.augusta.de>
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <memory.h>
-#include <byteorder.h>
-#include <asm/system.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <calypso/dsp_api.h>
-#include <calypso/irq.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <calypso/dsp.h>
-#include <calypso/timer.h>
-#include <comm/sercomm.h>
-
-#include <abb/twl3025.h>
-
-//#define DEBUG_EVERY_TDMA
-
-#include <layer1/sync.h>
-#include <layer1/afc.h>
-#include <layer1/agc.h>
-#include <layer1/apc.h>
-#include <layer1/tdma_sched.h>
-#include <layer1/mframe_sched.h>
-#include <layer1/sched_gsmtime.h>
-#include <layer1/tpu_window.h>
-#include <layer1/l23_api.h>
-
-#include <l1ctl_proto.h>
-
-struct l1s_state l1s;
-
-void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn)
-{
- ADD_MODULO(time->fn, delta_fn, GSM_MAX_FN);
-
- if (delta_fn == 1) {
- ADD_MODULO(time->t2, 1, 26);
- ADD_MODULO(time->t3, 1, 51);
-
- /* if the new frame number is a multiple of 51 */
- if (time->t3 == 0) {
- ADD_MODULO(time->tc, 1, 8);
-
- /* if new FN is multiple of 51 and 26 */
- if (time->t2 == 0)
- ADD_MODULO(time->t1, 1, 2048);
- }
- } else
- gsm_fn2gsmtime(time, time->fn);
-}
-
-void l1s_time_dump(const struct gsm_time *time)
-{
- printf("fn=%lu(%u/%2u/%2u)", time->fn, time->t1, time->t2, time->t3);
-}
-
-/* clip a signed 16bit value at a certain limit */
-int16_t clip_int16(int16_t angle, int16_t clip_at)
-{
- if (angle > clip_at)
- angle = clip_at;
- else if (angle < -clip_at)
- angle = -clip_at;
-
- return angle;
-}
-
-int16_t l1s_snr_int(uint16_t snr)
-{
- return snr >> 10;
-}
-
-uint16_t l1s_snr_fract(uint16_t snr)
-{
- uint32_t fract = snr & 0x3ff;
- fract = fract * 1000 / (2 << 10);
-
- return fract & 0xffff;
-}
-
-#define AFC_MAX_ANGLE 328 /* 0.01 radian in fx1.15 */
-
-/* synchronize the L1S to a new timebase (typically a new cell */
-void synchronize_tdma(struct l1_cell_info *cinfo)
-{
- int32_t fn_offset;
- uint32_t tpu_shift = cinfo->time_alignment;
-
- /* NB detection only works if the TOA of the SB
- * is within 0...8. We have to add 75 to get an SB TOA of 4. */
- tpu_shift += 75;
-
- tpu_shift = (l1s.tpu_offset + tpu_shift) % QBITS_PER_TDMA;
-
- fn_offset = cinfo->fn_offset - 1;
-
- /* if we're already very close to the end of the TPU frame, the
- * next interrupt will basically occur now and we need to
- * compensate */
- if (tpu_shift < SWITCH_TIME)
- fn_offset++;
-
-#if 0 /* probably wrong as we already added "offset" and "shift" above */
- /* increment the TPU quarter-bit offset */
- l1s.tpu_offset = (l1s.tpu_offset + tpu_shift) % TPU_RANGE;
-#else
- l1s.tpu_offset = tpu_shift;
-#endif
-
- puts("Synchronize_TDMA\n");
- /* request the TPU to adjust the SYNCHRO and OFFSET registers */
- tpu_enq_at(SWITCH_TIME);
- tpu_enq_sync(l1s.tpu_offset);
-#if 0
- /* FIXME: properly end the TPU window at the emd of l1_sync() */
- tpu_end_scenario();
-#endif
-
- /* Change the current time to reflect the new value */
- l1s_time_inc(&l1s.current_time, fn_offset);
- l1s.next_time = l1s.current_time;
- l1s_time_inc(&l1s.next_time, 1);
-
- /* The serving cell now no longer has a frame or bit offset */
- cinfo->fn_offset = 0;
- cinfo->time_alignment = 0;
-}
-
-void l1s_reset_hw(void)
-{
- dsp_api.w_page = 0;
- dsp_api.r_page = 0;
- dsp_api.r_page_used = 0;
- dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_0;
- dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
- dsp_api.ndb->d_dsp_page = 0;
-
- /* we have to really reset the TPU, otherwise FB detection
- * somtimes returns wrong TOA values. */
- tpu_reset(1);
- tpu_reset(0);
- tpu_rewind();
- tpu_enq_wait(5); /* really needed ? */
- tpu_enq_sync(l1s.tpu_offset);
- tpu_end_scenario();
-}
-
-/* Lost TDMA interrupt detection. This works by starting a hardware timer
- * that is clocked by the same master clock source (VCTCXO). We expect
- * 1875 timer ticks in the duration of a TDMA frame (5000 qbits / 1250 bits) */
-
-/* Timer for detecting lost IRQ */
-#define TIMER_TICKS_PER_TDMA 1875
-#define TIMER_TICK_JITTER 1
-
-static int last_timestamp;
-
-static inline void check_lost_frame(void)
-{
- int diff, timestamp = hwtimer_read(1);
-
- if (last_timestamp < timestamp)
- last_timestamp += (4*TIMER_TICKS_PER_TDMA);
-
- diff = last_timestamp - timestamp;
-
- /* allow for a bit of jitter */
- if (diff < TIMER_TICKS_PER_TDMA - TIMER_TICK_JITTER ||
- diff > TIMER_TICKS_PER_TDMA + TIMER_TICK_JITTER)
- printf("LOST %d!\n", diff);
-
- last_timestamp = timestamp;
-}
-
-/* schedule a completion */
-void l1s_compl_sched(enum l1_compl c)
-{
- unsigned long flags;
-
- local_firq_save(flags);
- l1s.scheduled_compl |= (1 << c);
- local_irq_restore(flags);
-}
-
-/* main routine for synchronous part of layer 1, called by frame interrupt
- * generated by TPU once every TDMA frame */
-static void l1_sync(void)
-{
- uint16_t sched_flags;
-
- putchart('+');
-
- check_lost_frame();
-
- /* Increment Time */
- l1s.current_time = l1s.next_time;
- l1s_time_inc(&l1s.next_time, 1);
- //l1s_time_dump(&l1s.current_time); putchar(' ');
-
- dsp_api.frame_ctr++;
- dsp_api.r_page_used = 0;
-
- /* Update pointers */
- if (dsp_api.w_page == 0)
- dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_0;
- else
- dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_1;
-
- if (dsp_api.r_page == 0)
- dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
- else
- dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_1;
-
- /* Reset MCU->DSP page */
- dsp_api_memset((uint16_t *) dsp_api.db_w, sizeof(*dsp_api.db_w));
-
- /* Update AFC */
- afc_load_dsp();
-
- if (dsp_api.ndb->d_error_status) {
- printf("DSP Error Status: %u\n", dsp_api.ndb->d_error_status);
- dsp_api.ndb->d_error_status = 0;
- }
-
- /* execute the sched_items that have been scheduled for this
- * TDMA frame (including setup/cleanup steps) */
- sched_flags = tdma_sched_flag_scan();
-
- if (sched_flags & TDMA_IFLG_TPU)
- l1s_win_init();
-
- tdma_sched_execute();
-
- if (dsp_api.r_page_used) {
- /* clear and switch the read page */
- dsp_api_memset((uint16_t *) dsp_api.db_r,
- sizeof(*dsp_api.db_r));
-
- /* TSM30 does it (really needed ?):
- * Set crc result as "SB not found". */
- dsp_api.db_r->a_sch[0] = (1<<B_SCH_CRC); /* B_SCH_CRC =1, BLUD =0 */
-
- dsp_api.r_page ^= 1;
- }
-
- if (sched_flags & TDMA_IFLG_DSP)
- dsp_end_scenario();
-
- if (sched_flags & TDMA_IFLG_TPU)
- tpu_end_scenario();
-
- /* schedule new / upcoming TDMA items */
- mframe_schedule();
- /* schedule new / upcoming one-shot events */
- sched_gsmtime_execute(l1s.current_time.fn);
-
- tdma_sched_advance();
-}
-
-/* ABORT command ********************************************************/
-
-static int l1s_abort_cmd(__unused uint8_t p1, __unused uint8_t p2,
- __unused uint16_t p3)
-{
- putchart('A');
-
- /* similar to l1s_reset_hw() without touching the TPU */
-
- dsp_api.w_page = 0;
- dsp_api.r_page = 0;
- dsp_api.r_page_used = 0;
- dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_0;
- dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
-
- /* Reset task commands. */
- dsp_api.db_w->d_task_d = NO_DSP_TASK; /* Init. RX task to NO TASK */
- dsp_api.db_w->d_task_u = NO_DSP_TASK; /* Init. TX task to NO TASK */
- dsp_api.db_w->d_task_ra = NO_DSP_TASK; /* Init. RA task to NO TASK */
- dsp_api.db_w->d_task_md = NO_DSP_TASK; /* Init. MONITORING task to NO TASK */
- dsp_api.ndb->d_dsp_page = 0;
-
- /* Set "b_abort" to TRUE, dsp will reset current and pending tasks */
- dsp_api.db_w->d_ctrl_system |= (1 << B_TASK_ABORT);
- return 0;
-}
-
-void l1s_dsp_abort(void)
-{
- /* abort right now */
- tdma_schedule(0, &l1s_abort_cmd, 0, 0, 0, 10);
-}
-
-void l1s_tx_apc_helper(uint16_t arfcn)
-{
- int16_t auxapc;
- enum gsm_band band;
- int i;
-
- /* Get DAC setting */
- band = gsm_arfcn2band(arfcn);
- auxapc = apc_tx_pwrlvl2auxapc(band, l1s.tx_power);
-
- /* Load the ApcOffset into the DSP */
- #define MY_OFFSET 4
- dsp_api.ndb->d_apcoff = ABB_VAL(APCOFF, (1 << 6) | MY_OFFSET) | 1; /* 2x slope for the GTA-02 ramp */
-
- /* Load the TX Power into the DSP */
- /*
- If the power is too low (below 0 dBm) the ramp is not OK,
- especially for GSM-1800. However an MS does not send below
- 0dBm anyway.
- */
- dsp_api.db_w->d_power_ctl = ABB_VAL(AUXAPC, auxapc);
-
- /* Update the ramp according to the PCL */
- for (i = 0; i < 16; i++)
- dsp_api.ndb->a_ramp[i] = ABB_VAL(APCRAM, twl3025_default_ramp[i]);
-
- /* The Ramp Table is sent to ABB only once after RF init routine called */
- dsp_api.db_w->d_ctrl_abb |= (1 << B_RAMP) | (1 << B_BULRAMPDEL);
-}
-
-/* Interrupt handler */
-static void frame_irq(__unused enum irq_nr nr)
-{
- l1_sync();
-}
-
-/* reset the layer1 as part of synchronizing to a new cell */
-void l1s_reset(void)
-{
- /* Reset state */
- l1s.fb.mode = 0;
- l1s.tx_power = 7; /* initial power reset */
-
- /* Leave dedicated mode */
- l1s.dedicated.type = GSM_DCHAN_NONE;
-
- /* reset scheduler and hardware */
- sched_gsmtime_reset();
- mframe_reset();
- tdma_sched_reset();
- l1s_dsp_abort();
-
- /* Cipher off */
- dsp_load_ciph_param(0, NULL);
-}
-
-void l1s_init(void)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(l1s.tx_queue); i++)
- INIT_LLIST_HEAD(&l1s.tx_queue[i]);
- l1s.tx_meas = NULL;
-
- sched_gsmtime_init();
-
- /* register FRAME interrupt as FIQ so it can interrupt normal IRQs */
- irq_register_handler(IRQ_TPU_FRAME, &frame_irq);
- irq_config(IRQ_TPU_FRAME, 1, 1, 0);
- irq_enable(IRQ_TPU_FRAME);
-
- /* configure timer 1 to be auto-reload and have a prescale of 12 (13MHz/12 == qbit clock) */
- hwtimer_enable(1, 1);
- hwtimer_load(1, (1875*4)-1);
- hwtimer_config(1, 0, 1);
- hwtimer_enable(1, 1);
-}
-
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/tdma_sched.c b/Src/osmocom-bb/src/target/firmware/layer1/tdma_sched.c
deleted file mode 100644
index 8812992..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/tdma_sched.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* TDMA Scheduler Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <defines.h>
-#include <debug.h>
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <layer1/tdma_sched.h>
-#include <layer1/sync.h>
-
-#include <calypso/dsp.h>
-
-/* dummy function to mark end of set */
-int tdma_end_set(__unused uint8_t p1, __unused uint8_t p2,
- __unused uint16_t p3)
-{
- return 0;
-}
-
-static uint8_t wrap_bucket(uint8_t offset)
-{
- uint16_t bucket;
-
- bucket = (l1s.tdma_sched.cur_bucket + offset)
- % ARRAY_SIZE(l1s.tdma_sched.bucket);
-
- return bucket;
-}
-
-/* Schedule an item at 'frame_offset' TDMA frames in the future */
-int tdma_schedule(uint8_t frame_offset, tdma_sched_cb *cb,
- uint8_t p1, uint8_t p2, uint16_t p3, int16_t prio)
-{
- struct tdma_scheduler *sched = &l1s.tdma_sched;
- uint8_t bucket_nr = wrap_bucket(frame_offset);
- struct tdma_sched_bucket *bucket = &sched->bucket[bucket_nr];
- struct tdma_sched_item *sched_item;
-
- if (bucket->num_items >= ARRAY_SIZE(bucket->item)) {
- puts("tdma_schedule bucket overflow\n");
- return -1;
- }
-
- sched_item = &bucket->item[bucket->num_items++];
-
- sched_item->cb = cb;
- sched_item->p1 = p1;
- sched_item->p2 = p2;
- sched_item->p3 = p3;
- sched_item->prio = prio;
-
- return 0;
-}
-
-/* Schedule a set of items starting from 'frame_offset' TDMA frames in the future */
-int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_set, uint16_t p3)
-{
- struct tdma_scheduler *sched = &l1s.tdma_sched;
- uint8_t bucket_nr = wrap_bucket(frame_offset);
- int i, j;
-
- for (i = 0, j = 0; 1; i++) {
- const struct tdma_sched_item *sched_item = &item_set[i];
- struct tdma_sched_bucket *bucket = &sched->bucket[bucket_nr];
-
- if (sched_item->cb == &tdma_end_set) {
- /* end of scheduler set, return */
- break;
- }
-
- if (sched_item->cb == NULL) {
- /* advance to next bucket (== TDMA frame) */
- bucket_nr = wrap_bucket(++frame_offset);
- j++;
- continue;
- }
- /* check for bucket overflow */
- if (bucket->num_items >= ARRAY_SIZE(bucket->item)) {
- puts("tdma_schedule bucket overflow\n");
- return -1;
- }
- /* copy the item from the set into the current bucket item position */
- memcpy(&bucket->item[bucket->num_items], sched_item, sizeof(*sched_item));
- bucket->item[bucket->num_items].p3 = p3;
- bucket->num_items++;
- }
-
- return j;
-}
-
-/* Advance TDMA scheduler to the next bucket */
-void tdma_sched_advance(void)
-{
- struct tdma_scheduler *sched = &l1s.tdma_sched;
- uint8_t next_bucket;
-
- /* advance to the next bucket */
- next_bucket = wrap_bucket(1);
- sched->cur_bucket = next_bucket;
-}
-
-/* Scan current frame scheduled items for flags */
-uint16_t tdma_sched_flag_scan(void)
-{
- struct tdma_scheduler *sched = &l1s.tdma_sched;
- struct tdma_sched_bucket *bucket;
- int i;
- uint16_t flags = 0;
-
- /* determine current bucket */
- bucket = &sched->bucket[sched->cur_bucket];
-
- /* iterate over items in this bucket and call callback function */
- for (i=0; i<bucket->num_items; i++) {
- struct tdma_sched_item *item = &bucket->item[i];
- flags |= item->flags;
- }
-
- return flags;
-}
-
-/* Sort a bucket entries by priority */
-static void _tdma_sched_bucket_sort(struct tdma_sched_bucket *bucket, int *seq)
-{
- int i, j, k;
- struct tdma_sched_item *item_i, *item_j;
-
- /* initial sequence */
- /* we need all the items because some call back may schedule
- * new call backs 'on the fly' */
- for (i=0; i<TDMASCHED_NUM_CB; i++)
- seq[i] = i;
-
- /* iterate over items in this bucket and sort them */
- for (i=0; i<bucket->num_items; i++)
- {
- item_i = &bucket->item[seq[i]];
-
- for (j=i+1; j<bucket->num_items; j++)
- {
- item_j = &bucket->item[seq[j]];
-
- if (item_i->prio > item_j->prio)
- {
- item_i = item_j;
- k = seq[i];
- seq[i] = seq[j];
- seq[j] = k;
- }
- }
- }
-}
-
-/* Execute pre-scheduled events for current frame */
-int tdma_sched_execute(void)
-{
- struct tdma_scheduler *sched = &l1s.tdma_sched;
- struct tdma_sched_bucket *bucket;
- int i, num_events = 0;
- int seq[TDMASCHED_NUM_CB];
-
- /* determine current bucket */
- bucket = &sched->bucket[sched->cur_bucket];
-
- /* get sequence in priority order */
- _tdma_sched_bucket_sort(bucket, seq);
-
- /* iterate over items in this bucket and call callback function */
- for (i = 0; i < bucket->num_items; i++) {
- struct tdma_sched_item *item = &bucket->item[seq[i]];
- int rc;
-
- num_events++;
-
- rc = item->cb(item->p1, item->p2, item->p3);
- if (rc < 0) {
- printf("Error %d during processing of item %u of bucket %u\n",
- rc, i, sched->cur_bucket);
- return rc;
- }
- /* if the cb() we just called has scheduled more items for the
- * current TDMA, bucket->num_items will have increased and we
- * will simply continue to execute them as intended. Priorities
- * won't work though ! */
- }
-
- /* clear/reset the bucket */
- bucket->num_items = 0;
-
- /* return number of items that we called */
- return num_events;
-}
-
-void tdma_sched_reset(void)
-{
- struct tdma_scheduler *sched = &l1s.tdma_sched;
- unsigned int bucket_nr;
-
- for (bucket_nr = 0; bucket_nr < ARRAY_SIZE(sched->bucket); bucket_nr++) {
- struct tdma_sched_bucket *bucket = &sched->bucket[bucket_nr];
- /* current bucket will be reset by iteration code above! */
- if (bucket_nr != sched->cur_bucket)
- bucket->num_items = 0;
- }
-
- /* Don't reset cur_bucket, as it would upset the bucket iteration code
- * in tdma_sched_execute() */
-}
-
-void tdma_sched_dump(void)
-{
- unsigned int i;
-
- printf("\n(%2u)", l1s.tdma_sched.cur_bucket);
- for (i = 0; i < ARRAY_SIZE(l1s.tdma_sched.bucket); i++) {
- int bucket_nr = wrap_bucket(i);
- struct tdma_sched_bucket *bucket = &l1s.tdma_sched.bucket[bucket_nr];
- printf("%u:", bucket->num_items);
- }
- putchar('\n');
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/toa.c b/Src/osmocom-bb/src/target/firmware/layer1/toa.c
deleted file mode 100644
index 7d80d95..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/toa.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* AFC (Automatic Frequency Correction) Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include <debug.h>
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <layer1/toa.h>
-#include <layer1/avg.h>
-#include <layer1/sync.h>
-
-/* Over how many TDMA frames do we want to average? */
-#define TOA_PERIOD 250
-/* How many of our measurements have to be valid? */
-#define TOA_MIN_MUN_VALID 125
-
-// FIXME:
-#define TOA_SNR_THRESHOLD 2560 /* 2.5 dB in fx6.10 */
-
-struct toa_state {
- struct running_avg ravg; /* running average */
-};
-
-
-static void toa_ravg_output(struct running_avg *ravg, int32_t avg);
-
-static struct toa_state toa_state = {
- .ravg = {
- .outfn = &toa_ravg_output,
- .period = TOA_PERIOD,
- .min_valid = TOA_MIN_MUN_VALID,
- },
-};
-
-void toa_input(int32_t offset, uint32_t snr)
-{
- int valid = 1;
-
- if (snr < TOA_SNR_THRESHOLD || offset < 0 || offset >31)
- valid = 0;
- runavg_input(&toa_state.ravg, offset, valid);
- runavg_check_output(&toa_state.ravg);
-}
-
-void toa_reset(void)
-{
- toa_state.ravg.num_samples = toa_state.ravg.num_samples_valid = 0;
- toa_state.ravg.acc_val = 0;
-}
-
-/* callback function for runavg */
-static void toa_ravg_output(struct running_avg *ravg, int32_t avg)
-{
- if (avg != 16) {
- printf("TOA AVG is not 16 qbits, correcting (got %ld)\n", avg);
- l1s.tpu_offset_correction = avg - 16;
- }
-}
diff --git a/Src/osmocom-bb/src/target/firmware/layer1/tpu_window.c b/Src/osmocom-bb/src/target/firmware/layer1/tpu_window.c
deleted file mode 100644
index 8d9c899..0000000
--- a/Src/osmocom-bb/src/target/firmware/layer1/tpu_window.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* TPU window control routines for Layer 1 */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <debug.h>
-#include <defines.h>
-#include <stdio.h>
-
-#include <rffe.h>
-#include <calypso/tpu.h>
-#include <calypso/tsp.h>
-#include <abb/twl3025.h>
-#include <rf/trf6151.h>
-
-#include <layer1/sync.h>
-#include <layer1/tpu_window.h>
-
-/* all units in GSM quarter-bits (923.1ns) */
-#define L1_TDMA_LENGTH_Q 5000
-#define L1_BURST_LENGTH_Q 625 /* L1_TDMA_LENGTH_Q/8 */
-
-#define L1_NB_MARGIN_Q (3 * 4)
-#define L1_SB_MARGIN_Q (23 * 4)
-#define L1_TAIL_DURATION_Q (3 * 4)
-
-/* Sample length as required by the Calypso DSP */
-#define L1_NB_DURATION_Q (L1_BURST_LENGTH_Q + 2 * L1_NB_MARGIN_Q - L1_TAIL_DURATION_Q)
-#define L1_SB_DURATION_Q (L1_BURST_LENGTH_Q + 2 * L1_SB_MARGIN_Q - L1_TAIL_DURATION_Q)
-#define L1_FB_DURATION_Q (11 * L1_TDMA_LENGTH_Q + 2057) /* more than 11 full slots */
-#define L1_FB26_DURATION_Q (L1_TDMA_LENGTH_Q + 798)
-#define L1_PW_DURATION_Q 289
-
-#define DSP_SETUP_TIME 66
-
-static const uint16_t rx_burst_duration[_NUM_L1_RXWIN] = {
- [L1_RXWIN_PW] = L1_PW_DURATION_Q,
- [L1_RXWIN_FB] = L1_FB_DURATION_Q,
- [L1_RXWIN_SB] = L1_SB_DURATION_Q,
- [L1_RXWIN_NB] = L1_NB_DURATION_Q,
-};
-
-#define L1_TX_NB_DURATION_Q 626
-#define L1_TX_AB_DURATION_Q 386
-
-static const uint16_t tx_burst_duration[_NUM_L1_TXWIN] = {
- [L1_TXWIN_NB] = L1_TX_NB_DURATION_Q,
- [L1_TXWIN_AB] = L1_TX_AB_DURATION_Q,
-};
-
-
-static int _win_setup(__unused uint8_t p1, __unused uint8_t p2, __unused uint16_t p3)
-{
- uint8_t tn;
-
- rfch_get_params(&l1s.next_time, NULL, NULL, &tn);
-
- l1s.tpu_offset = (5000 + l1s.tpu_offset + l1s.tpu_offset_correction) % 5000;
- l1s.tpu_offset_correction = 0;
-
- tpu_enq_at(4740);
- tpu_enq_sync((5000 + l1s.tpu_offset + (L1_BURST_LENGTH_Q * tn)) % 5000);
-
- return 0;
-}
-
-static int _win_cleanup(__unused uint8_t p1, __unused uint8_t p2, __unused uint16_t p3)
-{
- uint8_t tn;
-
- rfch_get_params(&l1s.next_time, NULL, NULL, &tn);
-
- /* restore offset */
- tpu_enq_offset((5000 + l1s.tpu_offset + (L1_BURST_LENGTH_Q * tn)) % 5000);
-
- return 0;
-}
-
-void l1s_win_init(void)
-{
- tdma_schedule(0, _win_setup, 0, 0, 0, -2);
- tdma_schedule(0, _win_cleanup, 0, 0, 0, 9);
-}
-
-void l1s_rx_win_ctrl(uint16_t arfcn, enum l1_rxwin_type wtype, uint8_t tn_ofs)
-{
- int16_t start, stop;
-
- /* TN offset & TA adjust */
- start = DSP_SETUP_TIME;
- start += L1_BURST_LENGTH_Q * tn_ofs;
-
- stop = start + rx_burst_duration[wtype] - 1;
-
- /* window open for TRF6151 */
- /* FIXME: why do we need the magic value 100 ? */
- rffe_mode(gsm_arfcn2band(arfcn), 0);
- trf6151_rx_window(start - 100, arfcn);
-
- /* Window open for ABB */
- twl3025_downlink(1, start);
-
- /* Delay 11 full TDMA frames */
- if (wtype == L1_RXWIN_FB) {
- uint8_t i;
- for (i = 0; i < 11; i++)
- tpu_enq_at(0);
-
- stop -= 11 * L1_TDMA_LENGTH_Q;
- }
-
- /* Window close for ABB */
- twl3025_downlink(0, stop);
-
- /* window close for TRF6151 */
- trf6151_set_mode(TRF6151_IDLE);
-}
-
-void l1s_tx_win_ctrl(uint16_t arfcn, enum l1_txwin_type wtype, uint8_t pwr, uint8_t tn_ofs)
-{
- uint16_t offset;
-
- /* TN offset & TA adjust */
- offset = 28; /* ("+ 32" gives a TA of 1) */
- offset += L1_BURST_LENGTH_Q * tn_ofs;
- offset -= l1s.ta << 2;
-
-#ifdef CONFIG_TX_ENABLE
- /* window open for TRF6151 and RFFE */
- rffe_mode(gsm_arfcn2band(arfcn), 1);
- trf6151_tx_window(offset, arfcn);
-#endif
-
- /* Window open for ABB */
- twl3025_uplink(1, offset);
-
- /* Window close for ABB */
- twl3025_uplink(0, tx_burst_duration[wtype] + offset + 2); // TODO: "+ 2"
-
- /* window close for TRF6151 and RFFE */
- trf6151_set_mode(TRF6151_IDLE);
-}
-
-void tpu_end_scenario(void)
-{
- tpu_enq_sleep();
- tpu_enable(1);
-}