Make new L1CTL_FBSB_REQ work reliably
[osmocom-bb.git] / src / target / firmware / include / layer1 / sync.h
index 6bdb57a..4c055d2 100644 (file)
@@ -4,13 +4,22 @@
 #include <osmocore/linuxlist.h>
 #include <osmocore/gsm_utils.h>
 #include <layer1/tdma_sched.h>
+#include <layer1/mframe_sched.h>
 #include <l1a_l23_interface.h>
 
+/* structure representing L1 sync information about a cell */
 struct l1_cell_info {
+       /* on which ARFCN (+band) is the cell? */
        uint16_t        arfcn;
-       uint32_t        bsic;
-       uint32_t        fn_offset;
+       /* what's the BSIC of the cell (from SCH burst decoding) */
+       uint8_t         bsic;
+       /* whats the delta of the cells current GSM frame number
+        * compared to our current local frame number */
+       int32_t         fn_offset;
+       /* how much does the TPU need adjustment (delta) to synchronize
+        * with the cells burst */
        uint32_t        time_alignment;
+       /* FIXME: should we also store the AFC value? */
 };
 
 enum l1s_chan {
@@ -19,22 +28,60 @@ enum l1s_chan {
        _NUM_L1S_CHAN
 };
 
+enum l1_compl {
+       L1_COMPL_FB,
+};
+
+typedef void l1_compl_cb(enum l1_compl c);
+
+#define L1S_NUM_COMPL          32
+#define L1S_NUM_NEIGH_CELL     6
 
 struct l1s_state {
-       struct gsm_time current_time;   /* current time */
-       struct gsm_time next_time;      /* time at next TMDMA irq */
+       struct gsm_time current_time;   /* current GSM time */
+       struct gsm_time next_time;      /* GSM time at next TMDMA irq */
 
+       /* the cell on which we are camping right now */
        struct l1_cell_info serving_cell;
 
+       /* neighbor cell sync info */
+       struct l1_cell_info neigh_cell[L1S_NUM_NEIGH_CELL];
+
+       /* TDMA scheduler */
        struct tdma_scheduler tdma_sched;
 
+       /* Multiframe scheduler */
+       struct mframe_scheduler mframe_sched;
+
+       /* The current TPU offset register */
        uint32_t        tpu_offset;
 
        /* Transmit queues of pending packets for main DCCH and ACCH */
        struct llist_head tx_queue[_NUM_L1S_CHAN];
 
-       /* bit-mask of multi-frame tasks that are currently active */
-       uint32_t        mf_tasks;
+       /* Which L1A completions are scheduled right now */
+       uint32_t scheduled_compl;
+       /* callbacks for each of the completions */
+       l1_compl_cb *completion[L1S_NUM_COMPL];
+
+       /* Structures below are for L1-task specific parameters, used
+        * to communicate between l1-sync and l1-async (l23_api) */
+       struct {
+               uint8_t mode;   /* FB_MODE 0/1 */
+       } fb;
+
+       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;
@@ -43,11 +90,6 @@ struct l1s_state {
 
 extern struct l1s_state l1s;
 
-enum l1_sig_num {
-       L1_SIG_PM,      /* Power Measurement */
-       L1_SIG_NB,      /* Normal Burst */
-};
-
 struct l1s_meas_hdr {
        uint16_t snr;           /* signal/noise ratio */
        int16_t toa_qbit;       /* time of arrival (qbits) */
@@ -55,27 +97,6 @@ struct l1s_meas_hdr {
        int16_t freq_err;       /* Frequency error in Hz */
 };
 
-struct l1_signal {
-       uint16_t signum;
-       uint16_t arfcn;
-       union {
-               struct {
-                       int16_t dbm8[2];
-               } pm;
-               struct {
-                       struct l1s_meas_hdr meas[4];
-                       uint16_t crc;
-                       uint16_t fire;
-                       uint16_t num_biterr;
-                       uint8_t frame[24];
-               } nb;
-       };
-};
-
-typedef void (*l1s_cb_t)(struct l1_signal *sig);
-
-void l1s_set_handler(l1s_cb_t handler);
-
 int16_t l1s_snr_int(uint16_t snr);
 uint16_t l1s_snr_fract(uint16_t snr);
 
@@ -86,9 +107,33 @@ void l1s_sb_test(uint8_t base_fn);
 void l1s_pm_test(uint8_t base_fn, uint16_t arfcn);
 void l1s_nb_test(uint8_t base_fn);
 
+/* schedule a completion */
+void l1s_compl_sched(enum l1_compl c);
+
 void l1s_init(void);
 
+/* reset the layer1 as part of synchronizing to a new cell */
+void l1s_reset(void);
+
 /* init.c */
 void layer1_init(void);
 
+/* A debug macro to print every TDMA frame */
+#ifdef DEBUG_EVERY_TDMA
+#define putchart(x) putchar(x)
+#else
+#define putchart(x)
+#endif
+
+/* Convert an angle in fx1.15 notatinon into Hz */
+#define BITFREQ_DIV_2PI                43104   /* 270kHz / 2 * pi */
+#define BITFREQ_DIV_PI         86208   /* 270kHz / pi */
+#define ANG2FREQ_SCALING       (2<<15) /* 2^15 scaling factor for fx1.15 */
+#define ANGLE_TO_FREQ(angle)   ((int16_t)angle * BITFREQ_DIV_PI / ANG2FREQ_SCALING)
+
+void l1s_reset_hw(void);
+void synchronize_tdma(struct l1_cell_info *cinfo);
+void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn);
+void l1s_time_dump(const struct gsm_time *time);
+
 #endif /* _L1_SYNC_H */