summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/l1a_l23_interface.h11
-rw-r--r--src/host/layer23/include/osmocom/l1ctl.h4
-rw-r--r--src/host/layer23/src/l1ctl.c56
-rw-r--r--src/target/firmware/include/layer1/l23_api.h1
-rw-r--r--src/target/firmware/include/layer1/sync.h13
-rw-r--r--src/target/firmware/layer1/l23_api.c38
-rw-r--r--src/target/firmware/layer1/sync.c41
7 files changed, 141 insertions, 23 deletions
diff --git a/include/l1a_l23_interface.h b/include/l1a_l23_interface.h
index 64ede925..e9def59c 100644
--- a/include/l1a_l23_interface.h
+++ b/include/l1a_l23_interface.h
@@ -32,8 +32,9 @@
#define L1CTL_DATA_REQ 7
#define L1CTL_RESET 8
#define L1CTL_PM_REQ 9 /* power measurement */
-#define L1CTL_ECHO_REQ 10
-#define L1CTL_ECHO_RESP 11
+#define L1CTL_PM_RESP 10 /* power measurement */
+#define L1CTL_ECHO_REQ 11
+#define L1CTL_ECHO_RESP 12
/*
* NOTE: struct size. We do add manual padding out of the believe
@@ -138,4 +139,10 @@ struct l1ctl_pm_req {
};
} __attribute__((packed));
+/* a single L1CTL_PM response */
+struct l1ctl_pm_resp {
+ uint16_t band_arfcn;
+ uint8_t pm[2];
+} __attribute__((packed));
+
#endif
diff --git a/src/host/layer23/include/osmocom/l1ctl.h b/src/host/layer23/include/osmocom/l1ctl.h
index e4e76c05..d0ff8867 100644
--- a/src/host/layer23/include/osmocom/l1ctl.h
+++ b/src/host/layer23/include/osmocom/l1ctl.h
@@ -21,6 +21,10 @@ int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr
int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len);
+/* Transmit L1CTL_PM_REQ */
+int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
+ uint16_t arfcm_to);
+
extern int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg);
diff --git a/src/host/layer23/src/l1ctl.c b/src/host/layer23/src/l1ctl.c
index 97009cb2..ada7ec8d 100644
--- a/src/host/layer23/src/l1ctl.c
+++ b/src/host/layer23/src/l1ctl.c
@@ -212,6 +212,22 @@ int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg,
return osmo_send_l1(ms, msg);
}
+/* Transmit NEW_CCCH_REQ */
+int l1ctl_tx_ccch_req(struct osmocom_ms *ms)
+{
+ struct msgb *msg;
+ struct l1ctl_sync_new_ccch_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_NEW_CCCH_REQ);
+ if (!msg)
+ return -1;
+
+ req = (struct l1ctl_sync_new_ccch_req *) msgb_put(msg, sizeof(*req));
+ req->band_arfcn = osmo_make_band_arfcn(ms);
+
+ return osmo_send_l1(ms, msg);
+}
+
/* Transmit L1CTL_RACH_REQ */
int tx_ph_rach_req(struct osmocom_ms *ms)
{
@@ -272,23 +288,46 @@ int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len)
return osmo_send_l1(ms, msg);
}
-/* Receive L1CTL_RESET */
-static int rx_l1_reset(struct osmocom_ms *ms)
+/* Transmit L1CTL_PM_REQ */
+int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
+ uint16_t arfcn_to)
{
struct msgb *msg;
- struct l1ctl_sync_new_ccch_req *req;
+ struct l1ctl_pm_req *pm;
- msg = osmo_l1_alloc(L1CTL_NEW_CCCH_REQ);
+ msg = osmo_l1_alloc(L1CTL_PM_REQ);
if (!msg)
return -1;
- LOGP(DL1C, LOGL_INFO, "Layer1 Reset.\n");
- req = (struct l1ctl_sync_new_ccch_req *) msgb_put(msg, sizeof(*req));
- req->band_arfcn = osmo_make_band_arfcn(ms);
+ printf("Tx PM Req (%u-%u)\n", arfcn_from, arfcn_to);
+ pm = (struct l1ctl_pm_req *) msgb_put(msg, sizeof(*pm));
+ pm->type = 1;
+ pm->range.band_arfcn_from = htons(arfcn_from);
+ pm->range.band_arfcn_to = htons(arfcn_to);
return osmo_send_l1(ms, msg);
}
+/* Receive L1CTL_RESET */
+static int rx_l1_reset(struct osmocom_ms *ms)
+{
+ printf("Layer1 Reset.\n");
+ //return l1ctl_tx_pm_req_range(ms, 0, 124);
+ return l1ctl_tx_ccch_req(ms);
+}
+
+/* Receive L1CTL_PM_RESP */
+static int rx_l1_pm_resp(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct l1ctl_pm_resp *pmr;
+
+ for (pmr = (struct l1ctl_pm_resp *) msg->l1h;
+ (uint8_t *) pmr < msg->tail; pmr++) {
+ DEBUGP(DL1C, "PM MEAS: ARFCN: %4u RxLev: %3d %3d\n",
+ ntohs(pmr->band_arfcn), pmr->pm[0], pmr->pm[1]);
+ }
+ return 0;
+}
/* Receive incoming data from L1 using L1CTL format */
int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
@@ -319,6 +358,9 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
case L1CTL_RESET:
rc = rx_l1_reset(ms);
break;
+ case L1CTL_PM_RESP:
+ rc = rx_l1_pm_resp(ms, msg);
+ break;
default:
fprintf(stderr, "Unknown MSG: %u\n", l1h->msg_type);
break;
diff --git a/src/target/firmware/include/layer1/l23_api.h b/src/target/firmware/include/layer1/l23_api.h
index 69d4203a..66efce5d 100644
--- a/src/target/firmware/include/layer1/l23_api.h
+++ b/src/target/firmware/include/layer1/l23_api.h
@@ -7,6 +7,7 @@
void l1a_l23api_init(void);
void l1_queue_for_l2(struct msgb *msg);
+struct msgb *l1ctl_msgb_alloc(uint8_t msg_type);
struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr, uint16_t arfcn);
#endif /* _L1_L23_API_H */
diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h
index 6bdb57ac..f13d5a97 100644
--- a/src/target/firmware/include/layer1/sync.h
+++ b/src/target/firmware/include/layer1/sync.h
@@ -37,6 +37,19 @@ struct l1s_state {
uint32_t mf_tasks;
struct {
+ /* power measurement l1 task */
+ unsigned int mode;
+ union {
+ struct {
+ uint16_t arfcn_start;
+ uint16_t arfcn_next;
+ uint16_t arfcn_end;
+ } range;
+ };
+ struct msgb *msg;
+ } pm;
+
+ struct {
uint8_t ra;
} rach;
};
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index e1c3591c..d17c8c46 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -79,14 +79,12 @@ static enum mframe_task chan_nr2mf_task(uint8_t chan_nr)
return 0;
}
-struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr,
- uint16_t arfcn)
+struct msgb *l1ctl_msgb_alloc(uint8_t msg_type)
{
- struct l1ctl_hdr *l1h;
- struct l1ctl_info_dl *dl;
struct msgb *msg;
+ struct l1ctl_hdr *l1h;
- msg = msgb_alloc_headroom(L3_MSG_SIZE, L3_MSG_HEAD, "l1_burst");
+ msg = msgb_alloc_headroom(L3_MSG_SIZE, L3_MSG_HEAD, "l1ctl");
if (!msg) {
while (1) {
puts("OOPS. Out of buffers...\n");
@@ -94,10 +92,18 @@ struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr,
return NULL;
}
-
l1h = (struct l1ctl_hdr *) msgb_put(msg, sizeof(*l1h));
l1h->msg_type = msg_type;
+ 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;
@@ -106,12 +112,27 @@ struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr,
return msg;
}
+/* receive a L1CTL_PM_REQ from L23 */
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;
- /* FIXME */
+ 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);
}
/* callback from SERCOMM when L2 sends a message to L1 */
@@ -127,7 +148,7 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
{
int i;
- puts("l1a_l23_rx_cb: ");
+ printf("l1a_l23_rx_cb (%u): ", msg->len);
for (i = 0; i < msg->len; i++)
printf("%02x ", msg->data[i]);
puts("\n");
@@ -202,7 +223,6 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
/* we have to keep the msgb, not free it! */
goto exit_nofree;
case L1CTL_PM_REQ:
- printd("L1CTL_PM_REQ\n");
l1ctl_rx_pm_req(msg);
break;
}
diff --git a/src/target/firmware/layer1/sync.c b/src/target/firmware/layer1/sync.c
index e80756a5..a6049642 100644
--- a/src/target/firmware/layer1/sync.c
+++ b/src/target/firmware/layer1/sync.c
@@ -30,6 +30,7 @@
#include <defines.h>
#include <debug.h>
#include <memory.h>
+#include <byteorder.h>
#include <osmocore/gsm_utils.h>
#include <osmocore/msgb.h>
#include <calypso/dsp_api.h>
@@ -773,8 +774,9 @@ static int l1s_pm_cmd(__unused uint8_t p1,
/* scheduler callback to read power measurement resposnse from the DSP */
static int l1s_pm_resp(__unused uint8_t p1, __unused uint8_t p2,
- __unused uint16_t p3)
+ uint16_t arfcn)
{
+ struct l1ctl_pm_resp *pmr;
uint16_t pm_level[2];
struct l1_signal sig;
@@ -782,26 +784,55 @@ static int l1s_pm_resp(__unused uint8_t p1, __unused uint8_t p2,
l1ddsp_meas_read(2, pm_level);
- printd("PM MEAS: %-4d dBm, %-4d dBm ARFCN=%u\n",
+ printf("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, rf_arfcn);
+ agc_inp_dbm8_by_pm(pm_level[1])/8, arfcn);
/* build and deliver signal */
sig.signum = L1_SIG_PM;
- sig.arfcn = rf_arfcn;
+ sig.arfcn = arfcn;
sig.pm.dbm8[0] = agc_inp_dbm8_by_pm(pm_level[0]);
sig.pm.dbm8[1] = agc_inp_dbm8_by_pm(pm_level[1]);
if (l1s_cb)
l1s_cb(&sig);
+ if (!l1s.pm.msg)
+ l1s.pm.msg = l1ctl_msgb_alloc(L1CTL_PM_RESP);
+
+ 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_RESP);
+ }
+
+ 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);
+ pmr->pm[1] = dbm2rxlev(agc_inp_dbm8_by_pm(pm_level[1])/8);
+
+ 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 */
+ l1_queue_for_l2(l1s.pm.msg);
+ l1s.pm.msg = NULL;
+ }
+ }
+
return 0;
}
void l1s_pm_test(uint8_t base_fn, uint16_t arfcn)
{
+ printf("l1s_pm_test(%u, %u)\n", base_fn, arfcn);
tdma_schedule(base_fn, &l1s_pm_cmd, 0, 0, arfcn);
- tdma_schedule(base_fn + 2, &l1s_pm_resp, 0, 0, 0);
+ tdma_schedule(base_fn + 2, &l1s_pm_resp, 0, 0, arfcn);
}
/* Normal Burst ***************************************************************/