From 146619933bdcdf4ce42f591c3aee7dc66fa16574 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 28 Feb 2010 14:31:06 +0100 Subject: add an actual Layer1 asynchronous (L1A) API that can be called from higher layers --- include/l1a_l23_interface.h | 1 + src/target/firmware/apps/layer1/main.c | 40 ------------- src/target/firmware/include/layer1/l23_api.h | 1 + src/target/firmware/include/layer1/sync.h | 4 ++ src/target/firmware/layer1/Makefile | 2 +- src/target/firmware/layer1/async.c | 89 ++++++++++++++++++++++++++++ src/target/firmware/layer1/init.c | 3 + src/target/firmware/layer1/l23_api.c | 56 +++++++++++++++++ 8 files changed, 155 insertions(+), 41 deletions(-) create mode 100644 src/target/firmware/layer1/async.c diff --git a/include/l1a_l23_interface.h b/include/l1a_l23_interface.h index fc03d720..6e94ebc1 100644 --- a/include/l1a_l23_interface.h +++ b/include/l1a_l23_interface.h @@ -80,6 +80,7 @@ struct l1_info_ul { uint8_t tx_power; uint8_t channel_number; uint32_t tdma_frame; + uint8_t payload[0]; } __attribute__((packed)); /* diff --git a/src/target/firmware/apps/layer1/main.c b/src/target/firmware/apps/layer1/main.c index 6e4d9817..62475433 100644 --- a/src/target/firmware/apps/layer1/main.c +++ b/src/target/firmware/apps/layer1/main.c @@ -78,7 +78,6 @@ static void l1s_signal_cb(struct l1_signal *sig) } static void key_handler(enum key_codes code, enum key_states state); -static void la1_l23_rx_cb(uint8_t dlci, struct msgb *msg); int main(void) { @@ -99,8 +98,6 @@ int main(void) st7558_set_attr(DISP_ATTR_INVERT); st7558_puts("layer1.bin"); - sercomm_register_rx_cb(SC_DLCI_L1A_L23, la1_l23_rx_cb); - layer1_init(); l1s_set_handler(&l1s_signal_cb); @@ -185,41 +182,4 @@ static void key_handler(enum key_codes code, enum key_states state) } } -static void la1_l23_rx_cb(uint8_t dlci, struct msgb *msg) -{ - struct l1_info_ul *ul = msg->data; - struct l1_sync_new_ccch_req *sync_req; - - if (sizeof(*ul) > msg->len) { - printf("la1_l23_cb: Short message. %u\n", msg->len); - goto exit; - } - - switch (ul->msg_type) { - case SYNC_NEW_CCCH_REQ: - if (sizeof(*ul) + sizeof(*sync_req) > msg->len) { - printf("Short sync msg. %u\n", msg->len); - break; - } - - sync_req = (struct l1_sync_new_ccch_req *) (&msg->data[0] + sizeof(*ul)); - printf("Asked to tune to frequency: %u\n", sync_req->band_arfcn); - - /* reset scheduler and hardware */ - tdma_sched_reset(); - l1s_dsp_abort(); - /* tune to specified frequency */ - trf6151_rx_window(0, sync_req->band_arfcn, 40, 0); - tpu_end_scenario(); - - puts("Starting FCCH Recognition\n"); - l1s_fb_test(1, 0); - break; - case DEDIC_MODE_EST_REQ: - break; - } - -exit: - msgb_free(msg); -} diff --git a/src/target/firmware/include/layer1/l23_api.h b/src/target/firmware/include/layer1/l23_api.h index a03c59c8..826f82ea 100644 --- a/src/target/firmware/include/layer1/l23_api.h +++ b/src/target/firmware/include/layer1/l23_api.h @@ -5,6 +5,7 @@ #include #include +void l1a_l23api_init(void); void l1_queue_for_l2(struct msgb *msg); struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr); diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h index a50969b8..901ff9db 100644 --- a/src/target/firmware/include/layer1/sync.h +++ b/src/target/firmware/include/layer1/sync.h @@ -36,6 +36,10 @@ struct l1s_state { /* bit-mask of multi-frame tasks that are currently active */ uint32_t mf_tasks; + + struct { + uint8_t ra; + } rach; }; extern struct l1s_state l1s; diff --git a/src/target/firmware/layer1/Makefile b/src/target/firmware/layer1/Makefile index d04573ed..39639581 100644 --- a/src/target/firmware/layer1/Makefile +++ b/src/target/firmware/layer1/Makefile @@ -3,7 +3,7 @@ INCLUDES=-I../include/ -I../../../../include LIBNAME=layer1 OBJS=avg.o agc.o afc.o sync.o gsm.o tdma_sched.o tpu_window.o init.o l23_api.o \ - mframe_sched.o sched_gsmtime.o + mframe_sched.o sched_gsmtime.o async.o LST=$(OBJS:.o=.lst) diff --git a/src/target/firmware/layer1/async.c b/src/target/firmware/layer1/async.c new file mode 100644 index 00000000..c1a457e4 --- /dev/null +++ b/src/target/firmware/layer1/async.c @@ -0,0 +1,89 @@ +/* Asynchronous part of GSM Layer 1 */ + +/* (C) 2010 by Harald Welte + * + * 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 + +#include +#include + +#include + +#include +#include +#include +#include + +extern const struct tdma_sched_item rach_sched_set_ul[]; + +/* When altering data structures used by L1 Sync part, we need to + * make sure to temporarily disable IRQ/FIQ to keep data consistent */ +static inline void l1a_lock_sync(void) +{ + arm_disable_interrupts(); +} + +static inline void l1a_unlock_sync(void) +{ + arm_enable_interrupts(); +} + +/* safely enable a message into the L1S TX queue */ +void l1a_txq_msgb_enq(struct llist_head *queue, struct msgb *msg) +{ + l1a_lock_sync(); + msgb_enqueue(queue, msg); + l1a_unlock_sync(); +} + +/* request a RACH request at the next multiframe T3 = fn51 */ +void l1a_rach_req(uint8_t fn51, uint8_t ra) +{ + uint32_t fn_sched; + + l1a_lock_sync(); + l1s.rach.ra = ra; + /* TODO: can we wrap here? I don't think so */ + fn_sched = l1s.current_time.fn - l1s.current_time.t3; + fn_sched += fn51; + sched_gsmtime(rach_sched_set_ul, fn_sched); + l1a_unlock_sync(); +} + +/* Enable a repeating multiframe task */ +void l1a_mftask_enable(enum mframe_task task) +{ + /* we don't need locking here as L1S only reads mf_tasks */ + l1s.mf_tasks |= (1 << task); +} + +/* Disable a repeating multiframe task */ +void l1a_mftask_disable(enum mframe_task task) +{ + /* we don't need locking here as L1S only reads mf_tasks */ + l1s.mf_tasks &= ~(1 << task); +} + +/* Initialize asynchronous part of Layer1 */ +void l1a_init(void) +{ + l1a_l23api_init(); +} diff --git a/src/target/firmware/layer1/init.c b/src/target/firmware/layer1/init.c index 1c387772..317a1266 100644 --- a/src/target/firmware/layer1/init.c +++ b/src/target/firmware/layer1/init.c @@ -33,12 +33,15 @@ #include #include +#include #include void layer1_init(void) { struct msgb *msg; + /* initialize asynchronous part of L1 */ + l1a_init(); /* initialize TDMA Frame IRQ driven synchronous L1 */ l1s_init(); /* power up the DSP */ diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c index 85f73cde..4784c857 100644 --- a/src/target/firmware/layer1/l23_api.c +++ b/src/target/firmware/layer1/l23_api.c @@ -27,6 +27,8 @@ #include #include +#include + #include /* the size we will allocate struct msgb* for HDLC */ @@ -61,3 +63,57 @@ struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr) return msg; } + +/* callbakc from SERCOMM when L2 sends a message to L1 */ +static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg) +{ + struct l1_info_ul *ul = msg->data; + struct l1_sync_new_ccch_req *sync_req; + struct l1_rach_req *rach_req; + struct l1_dedic_mode_est_req *est_req; + + if (sizeof(*ul) > msg->len) { + printf("la1_l23_cb: Short message. %u\n", msg->len); + goto exit; + } + + switch (ul->msg_type) { + case SYNC_NEW_CCCH_REQ: + if (sizeof(*ul) + sizeof(*sync_req) > msg->len) { + printf("Short sync msg. %u\n", msg->len); + break; + } + + sync_req = (struct l1_sync_new_ccch_req *) (&msg->data[0] + sizeof(*ul)); + printf("Asked to tune to frequency: %u\n", sync_req->band_arfcn); + + /* reset scheduler and hardware */ + tdma_sched_reset(); + l1s_dsp_abort(); + + /* tune to specified frequency */ + trf6151_rx_window(0, sync_req->band_arfcn, 40, 0); + tpu_end_scenario(); + + puts("Starting FCCH Recognition\n"); + l1s_fb_test(1, 0); + break; + case DEDIC_MODE_EST_REQ: + est_req = (struct l1_dedic_mode_est_req *) ul->payload; + /* FIXME: ARFCN! */ + /* figure out which MF tasks to enable, depending on channel number */ + break; + case CCCH_RACH_REQ: + rach_req = (struct l1_rach_req *) ul->payload; + l1a_rach_req(27, rach_req->ra); + break; + } + +exit: + msgb_free(msg); +} + +void l1a_l23api_init(void) +{ + sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb); +} -- cgit v1.2.3