[layer1] Adding neighbour cell measurement code to layer1.
[osmocom-bb.git] / src / target / firmware / include / layer1 / sync.h
1 #ifndef _L1_SYNC_H
2 #define _L1_SYNC_H
3
4 #include <osmocom/core/linuxlist.h>
5 #include <osmocom/gsm/gsm_utils.h>
6 #include <layer1/tdma_sched.h>
7 #include <layer1/mframe_sched.h>
8 #include <l1ctl_proto.h>
9
10 /* structure representing L1 sync information about a cell */
11 struct l1_cell_info {
12         /* on which ARFCN (+band) is the cell? */
13         uint16_t        arfcn;
14         /* what's the BSIC of the cell (from SCH burst decoding) */
15         uint8_t         bsic;
16         /* Combined or non-combined CCCH */
17         uint8_t         ccch_mode; /* enum ccch_mode */
18         /* whats the delta of the cells current GSM frame number
19          * compared to our current local frame number */
20         int32_t         fn_offset;
21         /* how much does the TPU need adjustment (delta) to synchronize
22          * with the cells burst */
23         uint32_t        time_alignment;
24         /* FIXME: should we also store the AFC value? */
25 };
26
27 enum l1s_chan {
28         L1S_CHAN_MAIN,
29         L1S_CHAN_SACCH,
30         _NUM_L1S_CHAN
31 };
32
33 enum l1_compl {
34         L1_COMPL_FB,
35         L1_COMPL_RACH,
36         L1_COMPL_TX_NB,
37         L1_COMPL_TX_TCH,
38 };
39
40 typedef void l1_compl_cb(enum l1_compl c);
41
42 #define L1S_NUM_COMPL           32
43 #define L1S_NUM_NEIGH_CELL      6
44
45 struct l1s_h0 {
46         uint16_t arfcn;
47 };
48
49 struct l1s_h1 {
50         uint8_t hsn;
51         uint8_t maio;
52         uint8_t n;
53         uint16_t ma[64];
54 };
55
56 struct l1s_state {
57         struct gsm_time current_time;   /* current GSM time */
58         struct gsm_time next_time;      /* GSM time at next TMDMA irq */
59
60         /* the cell on which we are camping right now */
61         struct l1_cell_info serving_cell;
62
63         /* neighbor cell sync info */
64         struct l1_cell_info neigh_cell[L1S_NUM_NEIGH_CELL];
65
66         /* TDMA scheduler */
67         struct tdma_scheduler tdma_sched;
68
69         /* Multiframe scheduler */
70         struct mframe_scheduler mframe_sched;
71
72         /* The current TPU offset register */
73         uint32_t        tpu_offset;
74         int32_t         tpu_offset_correction;
75
76         /* TX parameters */
77         int8_t          ta;
78         uint8_t         tx_power;
79
80         /* TCH */
81         uint8_t         tch_mode;
82         uint8_t         tch_sync;
83
84         /* Transmit queues of pending packets for main DCCH and ACCH */
85         struct llist_head tx_queue[_NUM_L1S_CHAN];
86         struct msgb *tx_meas;
87
88         /* Which L1A completions are scheduled right now */
89         uint32_t scheduled_compl;
90         /* callbacks for each of the completions */
91         l1_compl_cb *completion[L1S_NUM_COMPL];
92
93         /* Structures below are for L1-task specific parameters, used
94          * to communicate between l1-sync and l1-async (l23_api) */
95         struct {
96                 uint8_t mode;   /* FB_MODE 0/1 */
97         } fb;
98
99         struct {
100                 /* power measurement l1 task */
101                 unsigned int mode;
102                 union {
103                         struct {
104                                 uint16_t arfcn_start;
105                                 uint16_t arfcn_next;
106                                 uint16_t arfcn_end;
107                         } range;
108                 };
109                 struct msgb *msg;
110         } pm;
111
112         struct {
113                 uint8_t         ra;
114         } rach;
115
116         struct {
117                 enum {
118                         GSM_DCHAN_NONE = 0,
119                         GSM_DCHAN_SDCCH_4,
120                         GSM_DCHAN_SDCCH_8,
121                         GSM_DCHAN_TCH_H,
122                         GSM_DCHAN_TCH_F,
123                         GSM_DCHAN_UNKNOWN,
124                 } type;
125
126                 uint8_t scn;
127                 uint8_t tsc;
128                 uint8_t tn;
129                 uint8_t h;
130
131                 union {
132                         struct l1s_h0 h0;
133                         struct l1s_h1 h1;
134                 };
135
136                 uint8_t st_tsc;
137                 uint8_t st_tn;
138                 uint8_t st_h;
139
140                 union {
141                         struct l1s_h0 st_h0;
142                         struct l1s_h1 st_h1;
143                 };
144         } dedicated;
145
146         /* neighbour cell power measurement process */
147         struct {
148                 uint8_t n, second;
149                 uint8_t pos;
150                 uint8_t running;
151                 uint16_t band_arfcn[64];
152                 uint8_t level[64];
153         } neigh_pm;
154 };
155
156 extern struct l1s_state l1s;
157
158 struct l1s_meas_hdr {
159         uint16_t snr;           /* signal/noise ratio */
160         int16_t toa_qbit;       /* time of arrival (qbits) */
161         int16_t pm_dbm8;        /* power level in dbm/8 */
162         int16_t freq_err;       /* Frequency error in Hz */
163 };
164
165 int16_t l1s_snr_int(uint16_t snr);
166 uint16_t l1s_snr_fract(uint16_t snr);
167
168 void l1s_dsp_abort(void);
169
170 void l1s_tx_apc_helper(uint16_t arfcn);
171
172 /* schedule a completion */
173 void l1s_compl_sched(enum l1_compl c);
174
175 void l1s_init(void);
176
177 /* reset the layer1 as part of synchronizing to a new cell */
178 void l1s_reset(void);
179
180 /* init.c */
181 void layer1_init(void);
182
183 /* A debug macro to print every TDMA frame */
184 #ifdef DEBUG_EVERY_TDMA
185 #define putchart(x) putchar(x)
186 #else
187 #define putchart(x)
188 #endif
189
190 /* Convert an angle in fx1.15 notatinon into Hz */
191 #define BITFREQ_DIV_2PI         43104   /* 270kHz / 2 * pi */
192 #define BITFREQ_DIV_PI          86208   /* 270kHz / pi */
193 #define ANG2FREQ_SCALING        (2<<15) /* 2^15 scaling factor for fx1.15 */
194 #define ANGLE_TO_FREQ(angle)    ((int16_t)angle * BITFREQ_DIV_PI / ANG2FREQ_SCALING)
195
196 void l1s_reset_hw(void);
197 void synchronize_tdma(struct l1_cell_info *cinfo);
198 void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn);
199 void l1s_time_dump(const struct gsm_time *time);
200
201 #endif /* _L1_SYNC_H */