diff options
-rw-r--r-- | include/l1a_l23_interface.h | 11 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/l1ctl.h | 4 | ||||
-rw-r--r-- | src/host/layer23/src/l1ctl.c | 56 | ||||
-rw-r--r-- | src/target/firmware/include/layer1/l23_api.h | 1 | ||||
-rw-r--r-- | src/target/firmware/include/layer1/sync.h | 13 | ||||
-rw-r--r-- | src/target/firmware/layer1/l23_api.c | 38 | ||||
-rw-r--r-- | src/target/firmware/layer1/sync.c | 41 |
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 ***************************************************************/ |