#include <calypso/dsp.h>
#include <calypso/timer.h>
#include <comm/sercomm.h>
+#include <comm/msgb.h>
+
+#include <abb/twl3025.h>
#include <layer1/sync.h>
#include <layer1/afc.h>
};
-/* dummy sched set for uplink */
+/* Transmit Burst *************************************************************/
+
+const uint8_t ubUui[23] = { 0x01, 0x03, 0x01, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b };
+
+/* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
+static int l1s_tx_resp(uint16_t p1, uint16_t burst_id)
+{
+ putchart('t');
+
+ dsp_api.r_page_used = 1;
+
+ return 0;
+}
+
+/* Channel type definitions for DEDICATED mode */
+#define INVALID_CHANNEL 0
+#define TCH_F 1
+#define TCH_H 2
+#define SDCCH_4 3
+#define SDCCH_8 4
+
+/* Channel mode definitions for DEDICATED mode */
+#define SIG_ONLY_MODE 0 // signalling only
+#define TCH_FS_MODE 1 // speech full rate
+#define TCH_HS_MODE 2 // speech half rate
+#define TCH_96_MODE 3 // data 9,6 kb/s
+#define TCH_48F_MODE 4 // data 4,8 kb/s full rate
+#define TCH_48H_MODE 5 // data 4,8 kb/s half rate
+#define TCH_24F_MODE 6 // data 2,4 kb/s full rate
+#define TCH_24H_MODE 7 // data 2,4 kb/s half rate
+#define TCH_EFR_MODE 8 // enhanced full rate
+#define TCH_144_MODE 9 // data 14,4 kb/s half rate
+
+static uint8_t loc_cnt = 0;
+
+/* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
+static int l1s_tx_cmd(uint16_t p1, uint16_t burst_id)
+{
+ int i;
+ uint8_t tsc;
+
+ putchart('T');
+
+ /* 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, 0xC0); /* 2 dBm pulse with offset 4 (GSM-1800) */
+
+ /* 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);
+
+ if (p1 == 0) /* DUL_DSP_TASK, one normal burst */
+ dsp_load_tch_param(0, SIG_ONLY_MODE, INVALID_CHANNEL, 0, 0, 0);
+ else if (p1 == 2) /* DUL_DSP_TASK, four normal bursts */
+ dsp_load_tch_param(0, SIG_ONLY_MODE, SDCCH_4, 0, 0, 0);
+
+ /* before sending first of the four bursts, copy data to API ram */
+ if (burst_id == 0) {
+ if (p1 == 0 || p1 == 2) { // DUL_DSP_TASK
+ uint16_t *info_ptr = dsp_api.ndb->a_cu;
+ struct msgb *msg;
+ uint8_t *data;
+ uint8_t j;
+
+ /* FIXME: distinguish between DCCH and ACCH */
+ msg = msgb_dequeue(&l1s.tx_queue[0]);
+
+ /* If the TX queue is empty, send idle pattern */
+ if (!msg)
+ data = ubUui;
+ else
+ data = msg->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; // 3rd word: cleared.
+
+ /* Copy first 22 bytes in the first 11 words after header. */
+ for (i=0, j=(3+0); j<(3+11); j++) {
+ info_ptr[j] = ((uint16_t)(data[i])) | ((uint16_t)(data[i+1]) << 8);
+ i += 2;
+ }
+ /* Copy last UWORD8 (23rd) in the 12th word after header. */
+ info_ptr[14] = data[22];
+
+ if (msg)
+ msgb_free(msg);
+ } else if (p1 == 1) { // RACH_DSP_TASK
+ uint16_t *info_ptr;
+ uint8_t data[2];
+
+ data[0] = l1s.serving_cell.bsic << 2;
+ data[1] = 0x00 + loc_cnt; // channel request, location update, loc_cnt as random reference
+ loc_cnt++;
+ if (loc_cnt > 16)
+ loc_cnt = 0;
+
+ info_ptr = &dsp_api.ndb->d_rach;
+ info_ptr[0] = ((uint16_t)(data[0])) | ((uint16_t)(data[1])<<8);
+ }
+ }
+
+ if (p1 == 0 || p1 == 2) {
+ tsc = 7; // !!!!! nanoBTS configuration for SDCCH 0 !!!!!!!!
+
+ dsp_load_tx_task(DUL_DSP_TASK, burst_id, tsc);
+ dsp_end_scenario();
+
+ l1s_tx_win_ctrl(rf_arfcn, L1_TXWIN_NB, 0);
+ tpu_end_scenario();
+ } else if (p1 == 1) {
+ dsp_api.db_w->d_task_ra = RACH_DSP_TASK;
+ dsp_end_scenario();
+
+ l1s_tx_win_ctrl(rf_arfcn, L1_TXWIN_AB, 0);
+ tpu_end_scenario();
+ }
+
+ return 0;
+}
+
+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);
+ tdma_schedule(base_fn + 2, &l1s_tx_resp, 0, 0);
+ } else if (type == 1) { // one RACH burst
+ tdma_schedule(base_fn, &l1s_tx_cmd, 1, 0);
+ tdma_schedule(base_fn + 2, &l1s_tx_resp, 1, 0);
+ } else if (type == 2) { // four normal burst
+ tdma_schedule(base_fn, &l1s_tx_cmd, 2, 0);
+ tdma_schedule(base_fn + 1, &l1s_tx_cmd, 2, 1);
+ tdma_schedule(base_fn + 2, &l1s_tx_resp, 2, 0);
+ tdma_schedule(base_fn + 2, &l1s_tx_cmd, 2, 2);
+ tdma_schedule(base_fn + 3, &l1s_tx_resp, 2, 1);
+ tdma_schedule(base_fn + 3, &l1s_tx_cmd, 2, 3);
+ tdma_schedule(base_fn + 4, &l1s_tx_resp, 2, 2);
+ tdma_schedule(base_fn + 5, &l1s_tx_resp, 2, 3);
+ }
+}
+
+/* sched sets for uplink */
+const struct tdma_sched_item rach_sched_set_ul[] = {
+ SCHED_ITEM(l1s_tx_cmd, 1, 0), SCHED_END_FRAME(),
+ SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_tx_resp, 1, 0), SCHED_END_FRAME(),
+ SCHED_END_SET()
+};
const struct tdma_sched_item nb_sched_set_ul[] = {
+ SCHED_ITEM(l1s_tx_cmd, 2, 0), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_tx_cmd, 2, 1), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_tx_resp, 2, 0), SCHED_ITEM(l1s_tx_cmd, 2, 2), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_tx_resp, 2, 1), SCHED_ITEM(l1s_tx_cmd, 2, 3), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_tx_resp, 2, 2), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_tx_resp, 2, 3), SCHED_END_FRAME(),
SCHED_END_SET()
};