summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/include/layer1/sync.h
blob: f136c9a63a7172567dea0775c034fd5c87b085ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifndef _L1_SYNC_H
#define _L1_SYNC_H

#include <osmocore/linuxlist.h>
#include <osmocore/gsm_utils.h>
#include <layer1/tdma_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;
	/* what's the BSIC of the cell (from SCH burst decoding) */
	uint32_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 {
	L1S_CHAN_MAIN,
	L1S_CHAN_SACCH,
	_NUM_L1S_CHAN
};

#define L1S_NUM_NEIGH_CELL	6

struct l1s_state {
	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;

	/* 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;

	/* Structures below are for L1-task specific parameters, used
	 * to communicate between l1-sync and l1-async (l23_api) */
	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;
};

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) */
	int16_t pm_dbm8;	/* power level in dbm/8 */
	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);

void l1s_dsp_abort(void);

void l1s_fb_test(uint8_t base_fn, uint8_t fb_mode);
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);

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);

#endif /* _L1_SYNC_H */