summaryrefslogtreecommitdiff
path: root/gsm-tvoid/src/lib/gsm_burst.h
blob: d6ab3816faa63b177e2d834005d719ee178ba88e (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#ifndef INCLUDED_GSM_BURST_H
#define INCLUDED_GSM_BURST_H

//TODO: rename to gsm_burst_receiver ?  use gsm_burst as encapsulation of an actual burst, incl bbuf, etc.
//			need to determine what is a decoder vs. burst function.  E.g. calc_freq_offset
//			everything but I/O & clocking & sync_state?
//			What about handling complex&diff&bin data?

#include "gsm_constants.h"
#include <gr_math.h>
#include <gr_feval.h>
#include "gsmstack.h"

//Testing Modes
//Tune test measures hopping latency by hopping between good and empty ARFCNs
#undef TEST_TUNE_TIMING
#define TEST_TUNE_GOOD_ARFCN	658
#define TEST_TUNE_EMPTY_ARFCN	655


//Console printing options
#define PRINT_NOTHING		0x00000000
#define PRINT_EVERYTHING	0x7FFFFFFF		//7 for SWIG overflow check work around
#define PRINT_BITS			0x00000001
#define PRINT_ALL_BITS		0x00000002
#define PRINT_CORR_BITS		0x00000004
#define PRINT_STATE			0x00000008

#define PRINT_ALL_TYPES		0x00000FF0
#define PRINT_KNOWN			0x00000FE0
#define PRINT_UNKNOWN		0x00000010
#define PRINT_TS0			0x00000020
#define PRINT_FCCH			0x00000040
#define PRINT_SCH			0x00000080
#define PRINT_DUMMY			0x00000100
#define PRINT_NORMAL		0x00000200

#define PRINT_GSM_DECODE	0x00000400

#define PRINT_HEX			0x00001000

//Timing/clock options
#define QB_NONE				0x00000000
#define QB_QUARTER			0x00000001		//only for internal clocked versions
#define QB_FULL04			0x00000003
#define QB_MASK				0x0000000F

#define CLK_CORR_TRACK		0x00000010		//adjust timing based on correlation offsets

#define DEFAULT_CLK_OPTS	( QB_QUARTER | CLK_CORR_TRACK )

#define SIGNUM(x)	((x>0)-(x<0))
		  
#define BBUF_SIZE	   TS_BITS

// Center bursts in the TS, splitting the guard period
//
// +--+--+---...-----+--...---+----...----+--+--+
//  G  T     D1         TS         D2      T   G
// Start ^

#define MAX_SYNC_WAIT	32	//Number of missed bursts before reverting to WAIT_FCCH. 

#define MAX_CORR_DIST   7	// 4 + 3 =  1/2 GUARD + TAIL
#define SCH_CORR_THRESHOLD	0.80
#define FCCH_CORR_THRESHOLD 0.90
#define NORM_CORR_THRESHOLD 0.80

#define	FCCH_HITS_NEEDED	(USEFUL_BITS - 4)
#define FCCH_MAX_MISSES		1

enum EQ_TYPE {
	EQ_NONE,
	EQ_FIXED_LINEAR,
	EQ_ADAPTIVE_LINEAR,
	EQ_FIXED_DFE,
	EQ_ADAPTIVE_DFE,
	EQ_VITERBI
};

#define BURST_CB_SYNC_OFFSET	1
#define BURST_CB_ADJ_OFFSET		2
#define BURST_CB_TUNE			3


class gsm_burst;

class gsm_burst
{
protected:
	
	gsm_burst(gr_feval_ll *t);  

	//Burst Buffer: Storage for burst data
	float			d_burst_buffer[BBUF_SIZE];
	int				d_bbuf_pos;			//write position
	int				d_burst_start;		//first useful bit (beginning of output)
	unsigned long   d_sample_count;		//sample count at end (TODO:beginning) of BBUF (bit count if external clock)
	unsigned long   d_last_burst_s_count;		//sample count from previous burst

	unsigned char	d_decoded_burst[USEFUL_BITS];	//Differentially Decoded burst buffer {0,1}
	
	///// Sync/training sequence correlation
	float			corr_sync[N_SYNC_BITS];	//encoded sync bits for correlation
	float			corr_train_seq[10][N_TRAIN_BITS];
	const float		*d_corr_pattern;
	int				d_corr_pat_size;
	float 			d_corr_max;
	int 			d_corr_maxpos;
	int				d_corr_center;
		
	///// GSM Stack
	GS_CTX			d_gs_ctx;

	///// Burst information
	SYNC_STATE		d_sync_state;
	SYNC_STATE		d_last_sync_state;
	BURST_TYPE		d_burst_type;
	unsigned		d_ts;					//timeslot 0-7
	unsigned long	d_last_good;			//Burst count of last good burst
	unsigned long   d_burst_count;			//Bursts received starting w/ initial FCCH reset after lost sync
	unsigned long   d_last_sch;				//Burst count of last SCH
	int				d_color_code;

	float			d_freq_offset;
	double			d_freq_off_sum;
	double			d_freq_off_weight;

	gr_feval_ll 	*p_tuner;
	
	//////// Methods
	int				get_burst(void);
	BURST_TYPE		get_fcch_burst(void);
	BURST_TYPE		get_sch_burst(void);
	BURST_TYPE		get_norm_burst(void);
	
	void	shift_burst(int);
	void	calc_freq_offset(void); 
	void	equalize(void);
	float	correlate_pattern(const float *,const int,const int,const int);
	void	diff_decode_burst(void);

	void	sync_reset(void);

	void	print_bits(const float *data,int length);
	void	print_hex(const unsigned char *data,int length);
	void	soft2hardbit(char *dst, const float *data, int len);
	void	print_burst(void);

	void	diff_encode(const float *in,float *out,int length,float lastbit = 1.0);	
	void	diff_decode(const float *in,float *out,int length,float lastbit = 1.0);	

public:
	~gsm_burst ();	

	////// General Stats
	//TODO: Maybe there should be a burst_stats class?
	long			d_sync_loss_count;
	long			d_fcch_count;
	long			d_part_sch_count;
	long			d_sch_count;
	long			d_normal_count;
	long			d_dummy_count;
	long			d_unknown_count;
	long			d_total_count;
	
	////// Options
	unsigned long	d_clock_options;
	unsigned long	d_print_options;
	EQ_TYPE			d_equalizer_type;
	
	
	//Methods
	void full_reset(void);

	int sync_state() { return d_sync_state;}

	//Frequency
	float last_freq_offset() {return d_freq_offset;}
	double mean_freq_offset(void);

	long next_arfcn;
};


#endif /* INCLUDED_GSM_BURST_H */
personal git repositories of Harald Welte. Your mileage may vary