summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-06-12 16:57:20 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2013-06-12 16:57:20 +0200
commit5fc544f90135ed0dc34e35c9f1bc4420ccc654ed (patch)
treebddfc0c57b2a99275fa5ba814c6073dd70a38b6a
parentc736754345f636770ba76f66a86cb959a42a7466 (diff)
Add handover support to calypso BTS
-rw-r--r--include/l1ctl_proto.h2
-rw-r--r--src/host/layer23/src/transceiver/l1ctl.c7
-rw-r--r--src/host/layer23/src/transceiver/l1ctl.h2
-rw-r--r--src/host/layer23/src/transceiver/trx.c48
-rw-r--r--src/host/layer23/src/transceiver/trx.h1
-rw-r--r--src/target/firmware/Makefile2
-rw-r--r--src/target/firmware/include/layer1/sync.h1
-rw-r--r--src/target/firmware/layer1/l23_api.c4
-rw-r--r--src/target/firmware/layer1/prim_bts.c90
9 files changed, 129 insertions, 28 deletions
diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h
index 4aa3ad76..8d506154 100644
--- a/include/l1ctl_proto.h
+++ b/include/l1ctl_proto.h
@@ -313,6 +313,7 @@ struct l1ctl_bts_mode {
uint8_t tx_mask;
uint8_t rx_mask;
uint8_t type[8];
+ uint8_t handover[8];
uint8_t bsic;
uint16_t band_arfcn;
uint8_t gain;
@@ -338,6 +339,7 @@ struct l1ctl_bts_burst_nb_ind {
/* BTS mode: AB Burst Indication */
struct l1ctl_bts_burst_ab_ind {
uint32_t fn;
+ uint8_t tn;
uint8_t toa;
uint8_t iq[2*88];
} __attribute__((packed));
diff --git a/src/host/layer23/src/transceiver/l1ctl.c b/src/host/layer23/src/transceiver/l1ctl.c
index 494d6ad5..5bcabe3f 100644
--- a/src/host/layer23/src/transceiver/l1ctl.c
+++ b/src/host/layer23/src/transceiver/l1ctl.c
@@ -117,7 +117,7 @@ l1ctl_tx_fbsb_req(struct l1ctl_link *l1l,
int
l1ctl_tx_bts_mode(struct l1ctl_link *l1l, uint8_t enabled, uint8_t *type,
uint8_t bsic, uint16_t band_arfcn, int gain, uint8_t tx_mask,
- uint8_t rx_mask)
+ uint8_t rx_mask, uint8_t *handover)
{
struct msgb *msg;
struct l1ctl_bts_mode *be;
@@ -142,6 +142,7 @@ l1ctl_tx_bts_mode(struct l1ctl_link *l1l, uint8_t enabled, uint8_t *type,
be->gain = gain;
be->tx_mask = tx_mask;
be->rx_mask = rx_mask;
+ memcpy(be->handover, handover, sizeof(be->handover));
return l1l_send(l1l, msg);
}
@@ -252,7 +253,7 @@ _l1ctl_rx_bts_burst_ab_ind(struct l1ctl_link *l1l, struct msgb *msg)
LOGP(DL1C, LOGL_INFO, "Access Burst Indication (fn=%d iq toa=%f)\n", fn, toa);
- trx_data_ind(l1l->trx, fn, 0, data, toa, 0);
+ trx_data_ind(l1l->trx, fn, bi->tn, data, toa, 0);
exit:
msgb_free(msg);
@@ -336,7 +337,7 @@ _l1ctl_rx_fbsb_conf(struct l1ctl_link *l1l, struct msgb *msg)
} else {
LOGP(DAPP, LOGL_INFO, "Sync acquired, setting BTS mode ...\n");
l1l->sync = 1;
- l1ctl_tx_bts_mode(l1l, l1l->trx->power, l1l->trx->type, l1l->trx->bsic, l1l->trx->arfcn, l1l->trx->gain, l1l->tx_mask, l1l->rx_mask);
+ l1ctl_tx_bts_mode(l1l, l1l->trx->power, l1l->trx->type, l1l->trx->bsic, l1l->trx->arfcn, l1l->trx->gain, l1l->tx_mask, l1l->rx_mask, l1l->trx->handover);
}
rc = 0;
diff --git a/src/host/layer23/src/transceiver/l1ctl.h b/src/host/layer23/src/transceiver/l1ctl.h
index 31d69037..07f79990 100644
--- a/src/host/layer23/src/transceiver/l1ctl.h
+++ b/src/host/layer23/src/transceiver/l1ctl.h
@@ -40,7 +40,7 @@ int l1ctl_tx_fbsb_req(struct l1ctl_link *l1l,
uint8_t sync_info_idx, uint8_t ccch_mode);
int l1ctl_tx_bts_mode(struct l1ctl_link *l1l, uint8_t enabled, uint8_t *type,
uint8_t bsic, uint16_t band_arfcn, int gain, uint8_t tx_mask,
- uint8_t rx_mask);
+ uint8_t rx_mask, uint8_t *handover);
int l1ctl_tx_bts_burst_req(struct l1ctl_link *l1l,
uint32_t fn, uint8_t tn, struct burst_data *burst);
diff --git a/src/host/layer23/src/transceiver/trx.c b/src/host/layer23/src/transceiver/trx.c
index ec50b89e..8432dcae 100644
--- a/src/host/layer23/src/transceiver/trx.c
+++ b/src/host/layer23/src/transceiver/trx.c
@@ -236,7 +236,7 @@ _trx_ctrl_cmd_poweroff(struct trx *trx, const char *cmd, const char *args)
trx->power = 0;
for (i = 0; i < 8; i++)
if (trx->l1l[i])
- l1ctl_tx_bts_mode(trx->l1l[i], 0, trx->type, 0, 0, 0, 0, 0);
+ l1ctl_tx_bts_mode(trx->l1l[i], 0, trx->type, 0, 0, 0, 0, 0, trx->handover);
return _trx_ctrl_send_resp(trx, cmd, "%d", 0);
}
@@ -253,9 +253,10 @@ _trx_ctrl_cmd_poweron(struct trx *trx, const char *cmd, const char *args)
rv = -EINVAL;
} else {
trx->power = 1;
+ memset(trx->handover, 0, sizeof(trx->handover));
for (i = 0; i < 8; i++)
if (trx->l1l[i])
- l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask);
+ l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask, trx->handover);
}
return _trx_ctrl_send_resp(trx, cmd, "%d", rv);
@@ -302,7 +303,7 @@ _trx_ctrl_cmd_setrxgain(struct trx *trx, const char *cmd, const char *args)
if (trx->power) {
for (i = 0; i < 8; i++)
if (trx->l1l[i])
- l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask);
+ l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask, trx->handover);
}
return _trx_ctrl_send_resp(trx, cmd, "%d %d", 0, db);
@@ -337,7 +338,7 @@ _trx_ctrl_cmd_setslot(struct trx *trx, const char *cmd, const char *args)
trx->type[tn] = type;
if (trx->l1l[tn])
- l1ctl_tx_bts_mode(trx->l1l[tn], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[tn]->tx_mask, trx->l1l[tn]->rx_mask);
+ l1ctl_tx_bts_mode(trx->l1l[tn], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[tn]->tx_mask, trx->l1l[tn]->rx_mask, trx->handover);
return _trx_ctrl_send_resp(trx, cmd, "%d %d", 0, type);
}
@@ -395,6 +396,42 @@ done:
return _trx_ctrl_send_resp(trx, cmd, "%d %d", rv, freq_khz);
}
+static int
+_trx_ctrl_cmd_handover(struct trx *trx, const char *cmd, const char *args)
+{
+ int n, tn, ss = 0;
+
+ n = sscanf(args, "%d %d", &tn, &ss);
+
+ if ((n < 1) || (tn < 0) || (tn > 7) || (ss < 0) || ((ss > 8)))
+ return _trx_ctrl_send_resp(trx, cmd, "%d %d %d", -1, tn, ss);
+
+ trx->handover[tn] |= (1 << ss);
+
+ if (trx->l1l[tn])
+ l1ctl_tx_bts_mode(trx->l1l[tn], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[tn]->tx_mask, trx->l1l[tn]->rx_mask, trx->handover);
+
+ return _trx_ctrl_send_resp(trx, cmd, "%d %d %d", 0, tn, ss);
+}
+
+static int
+_trx_ctrl_cmd_nohandover(struct trx *trx, const char *cmd, const char *args)
+{
+ int n, tn, ss = 0;
+
+ n = sscanf(args, "%d %d", &tn, &ss);
+
+ if ((n < 1) || (tn < 0) || (tn > 7) || (ss < 0) || ((ss > 8)))
+ return _trx_ctrl_send_resp(trx, cmd, "%d %d %d", -1, tn, ss);
+
+ trx->handover[tn] &= ~(1 << ss);
+
+ if (trx->l1l[tn])
+ l1ctl_tx_bts_mode(trx->l1l[tn], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[tn]->tx_mask, trx->l1l[tn]->rx_mask, trx->handover);
+
+ return _trx_ctrl_send_resp(trx, cmd, "%d %d %d", 0, tn, ss);
+}
+
struct trx_cmd_handler {
const char *cmd;
int (*handler)(struct trx *trx, const char *cmd, const char *args);
@@ -409,8 +446,11 @@ static const struct trx_cmd_handler trx_handlers[] = {
{ "SETRXGAIN", _trx_ctrl_cmd_setrxgain },
{ "SETMAXDLY", _trx_ctrl_cmd_setmaxdly },
{ "SETSLOT", _trx_ctrl_cmd_setslot },
+ { "SETSLOT", _trx_ctrl_cmd_setslot },
{ "RXTUNE", _trx_ctrl_cmd_rxtune },
{ "TXTUNE", _trx_ctrl_cmd_txtune },
+ { "HANDOVER", _trx_ctrl_cmd_handover },
+ { "NOHANDOVER", _trx_ctrl_cmd_nohandover },
{ NULL, NULL }
};
diff --git a/src/host/layer23/src/transceiver/trx.h b/src/host/layer23/src/transceiver/trx.h
index 65816c6d..d5c40e7f 100644
--- a/src/host/layer23/src/transceiver/trx.h
+++ b/src/host/layer23/src/transceiver/trx.h
@@ -54,6 +54,7 @@ struct trx {
uint8_t bsic;
int gain;
uint8_t type[8];
+ uint8_t handover[8];
};
diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile
index 9b02033b..5303d3d2 100644
--- a/src/target/firmware/Makefile
+++ b/src/target/firmware/Makefile
@@ -89,6 +89,8 @@ APPLICATIONS?=hello_world compal_dsp_dump layer1 loader rssi trx
# Applications specific env requirements
APP_loader_ENVIRONMENTS=compalram highram
APP_rssi_ENVIRONMENTS=* -compalram
+APP_layer1_ENVIRONMENTS=* -compalram
+APP_trx_ENVIRONMENTS=* -compalram
# Various objects that are currently linked into all applications
FLASH_OBJS=flash/cfi_flash.o
diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h
index 51fec14c..db6f1b46 100644
--- a/src/target/firmware/include/layer1/sync.h
+++ b/src/target/firmware/include/layer1/sync.h
@@ -160,6 +160,7 @@ struct l1s_state {
uint8_t tx_start, tx_num;
uint8_t rx_start, rx_num;
uint8_t type[8];
+ uint8_t handover[8];
uint16_t arfcn;
uint8_t bsic;
uint8_t gain;
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index 78ae2e44..6841f80e 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -609,8 +609,10 @@ static int l1ctl_bts_mode(struct msgb *msg)
mframe_enable(MF_TASK_BTS_SYNC);
mframe_enable(MF_TASK_BTS);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
l1s.bts.type[i] = bm->type[i];
+ l1s.bts.handover[i] = bm->handover[i];
+ }
l1s.bts.gain = bm->gain;
/* Calculate TX and RX windows by bit masks */
diff --git a/src/target/firmware/layer1/prim_bts.c b/src/target/firmware/layer1/prim_bts.c
index 5564f803..91b18dc6 100644
--- a/src/target/firmware/layer1/prim_bts.c
+++ b/src/target/firmware/layer1/prim_bts.c
@@ -117,6 +117,20 @@ sb_build(uint8_t bsic, uint16_t t1, uint8_t t2, uint8_t t3p)
((bsic & 0x3f) << 2);
}
+static uint8_t tchh_subslot[26] =
+ { 0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,1 };
+static uint8_t sdcch4_subslot[102] =
+ { 3,3,3,3,0,0,2,2,2,2,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,2,2,2,
+ 3,3,3,3,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,2,2,2 };
+static uint8_t sdcch8_subslot[102] =
+ { 5,5,5,5,6,6,6,6,7,7,7,7,0,0,0,0,0,0,0,1,1,1,1,2,2,2,
+ 2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,0,0,0,0,
+ 1,1,1,1,2,2,2,2,3,3,3,3,0,0,0,0,0,0,0,1,1,1,1,2,2,2,
+ 2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,4,4,4,4 };
+
+
static int
l1s_bts_resp(uint8_t p1, uint8_t p2, uint16_t p3)
@@ -135,17 +149,21 @@ l1s_bts_resp(uint8_t p1, uint8_t p2, uint16_t p3)
/* Access Burst ? */
if (db->rx[0].cmd == DSP_EXT_RX_CMD_AB)
{
- static struct l1ctl_bts_burst_ab_ind _bi[51];
- static int energy[51];
- struct l1ctl_bts_burst_ab_ind *bi = &_bi[rx_time.t3];
+ static int burst_count = 0;
+ static struct l1ctl_bts_burst_ab_ind _bi[10];
+ static int energy[10];
+ struct l1ctl_bts_burst_ab_ind *bi = &_bi[burst_count];
int i, j;
uint16_t *iq = &db->data[32];
- energy[rx_time.t3] = 0;
+ energy[burst_count] = 0;
/* Frame number */
bi->fn = htonl(rx_time.fn);
+ /* Timeslot */
+ bi->tn = l1s.bts.rx_start;
+
/* Data (cut to 8 bits */
bi->toa = db->rx[1].cmd;
if (bi->toa > 68)
@@ -154,15 +172,17 @@ l1s_bts_resp(uint8_t p1, uint8_t p2, uint16_t p3)
bi->iq[i] = iq[j] >> 8;
/* energy */
- energy[rx_time.t3] = db->rx[0].data;
+ energy[burst_count] = db->rx[0].data;
- if (rx_time.t3 == 46) {
+ if (++burst_count == 10) {
struct msgb *msg;
int energy_max = 0, energy_avg = 0;
- /* find strongest burst */
+ burst_count = 0;
+
+ /* find strongest burst out of 10 */
j = 0;
- for (i = 0; i < 51; i++) {
+ for (i = 0; i < 10; i++) {
energy_avg += energy[i];
if (energy[i] > energy_max) {
energy_max = energy[i];
@@ -255,7 +275,7 @@ l1s_bts_cmd(uint8_t p1, uint8_t p2, uint16_t p3)
uint32_t sb;
uint8_t data[15];
- int type, i, t3;
+ int type, i, t3, fn_mod_26, fn_mod_102;
/* Enable extensions */
dsp_ext_api.ndb->active = 1;
@@ -276,20 +296,52 @@ l1s_bts_cmd(uint8_t p1, uint8_t p2, uint16_t p3)
{
/* We're really a frame in advance since we RX in the next frame ! */
t3 = t3 - 1;
+ fn_mod_26 = (l1s.next_time.fn + 2715648 - 1) % 26;
+ fn_mod_102 = (l1s.next_time.fn + 2715648 - 1) % 102;
/* Select which type of burst */
- if ((l1s.bts.type[l1s.bts.rx_start] >> 1) != 2) /* not type 4,5 */
- db->rx[0].cmd = DSP_EXT_RX_CMD_NB;
- else if (l1s.bts.type[0] == 4) /* type 4 */
+ switch (l1s.bts.type[l1s.bts.rx_start]) {
+ case 1: /* TCH/F */
+ if (l1s.bts.handover[l1s.bts.rx_start] & (1 << 0))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else
+ db->rx[0].cmd = DSP_EXT_RX_CMD_NB;
+ break;
+ case 2: /* TCH/H */
+ case 3:
+ if ((l1s.bts.handover[l1s.bts.rx_start]
+ & (1 << tchh_subslot[fn_mod_26])))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else
+ db->rx[0].cmd = DSP_EXT_RX_CMD_NB;
+ break;
+ case 4:
+ case 6:
db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
- else if ((t3 >= 14) && (t3 <= 36))
- db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
- else if ((t3 == 4) || (t3 == 5))
- db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
- else if ((t3 == 45) || (t3 == 46))
- db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
- else
+ break;
+ case 5: /* BCCH+SDCCH/4 */
+ if ((t3 >= 14) && (t3 <= 36))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else if ((t3 == 4) || (t3 == 5))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else if ((t3 == 45) || (t3 == 46))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else if ((l1s.bts.handover[l1s.bts.rx_start]
+ & (1 << sdcch4_subslot[fn_mod_102])))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else
+ db->rx[0].cmd = DSP_EXT_RX_CMD_NB;
+ break;
+ case 7: /* SDCCH/8 */
+ if ((l1s.bts.handover[l1s.bts.rx_start]
+ & (1 << sdcch8_subslot[fn_mod_102])))
+ db->rx[0].cmd = DSP_EXT_RX_CMD_AB;
+ else
+ db->rx[0].cmd = DSP_EXT_RX_CMD_NB;
+ break;
+ default:
db->rx[0].cmd = DSP_EXT_RX_CMD_NB;
+ }
/* Enable dummy bursts detection */
dsp_api.db_w->d_ctrl_system |= (1 << B_BCCH_FREQ_IND);