summaryrefslogtreecommitdiff
path: root/gsm-receiver/src/lib/gsm_receiver_cf.h
blob: 039a7745990b9bc04d903dec1a31aad3295ea5dd (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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/* -*- c++ -*- */
/*
 * @file
 * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
 * @section LICENSE
 *
 * 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 3, 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; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */
#ifndef INCLUDED_GSM_RECEIVER_CF_H
#define INCLUDED_GSM_RECEIVER_CF_H

#include <vector>
#include <list>
#include <gr_block.h>
#include <gr_complex.h>
#include <gr_feval.h>
#include <gsm_constants.h>
#include <gsm_receiver_config.h>

#include <decoder/gsmstack.h> //TODO: remember to remove this line in the future!
#include "GSML1FEC.h" //!!
#include <string>//!!
#include <map>//!!

#define N_TCH_DECODER 7 /* for TS1..TS7 */

class gsm_receiver_cf;

typedef boost::shared_ptr<gsm_receiver_cf> gsm_receiver_cf_sptr;
typedef std::vector<gr_complex> vector_complex;

gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key, std::string configuration);

/** GSM Receiver GNU Radio block
 *
 * GSM Receiver class supports frequency correction, synchronisation and
 * MLSE (Maximum Likelihood Sequence Estimation) estimation of synchronisation
 * bursts and normal bursts.
 * \ingroup block
 */

class gsm_receiver_cf : public gr_block
{
  private:
    std::map<char,int> d_hex_to_int;
    FILE * d_speech_file; //!!
    uint8_t d_KC[8]; //!!
    GSM::TCHFACCHL1Decoder *d_tch_decoder[N_TCH_DECODER]; //!!
    bool d_trace_sch;

    enum {
        TM_NONE,
        TM_SPEECH_FR,
        TM_SPEECH_EFR,
    } d_tch_mode;

    /**@name Configuration of the receiver */
    //@{
    const int d_OSR; ///< oversampling ratio
    const int d_chan_imp_length; ///< channel impulse length
    //@}

    gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a SCH burst
    gr_complex d_norm_training_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS]; ///<encoded training sequences of a normal bursts and dummy bursts

    gr_feval_dd *d_tuner; ///<callback to a python object which is used for frequency tunning
    gr_feval_dd *d_synchronizer; ///<callback to a python object which is used to correct offset of USRP's internal clock

    /** Countes samples consumed by the receiver
     *
     * It is used in beetween find_fcch_burst and reach_sch_burst calls.
     * My intention was to synchronize this counter with some internal sample
     * counter of the USRP. Simple access to such USRP's counter isn't possible
     * so this variable isn't used in the "synchronized" state of the receiver yet.
     */
    unsigned d_counter;

    /**@name Variables used to store result of the find_fcch_burst fuction */
    //@{
    unsigned d_fcch_start_pos; ///< position of the first sample of the fcch burst
    float d_freq_offset; ///< frequency offset of the received signal
    //@}
    std::list<double> d_freq_offset_vals;

    /**@name Identifiers of the BTS extracted from the SCH burst */
    //@{
    int d_ncc; ///< network color code
    int d_bcc; ///< base station color code
    //@}

    /**@name Internal state of the gsm receiver */
    //@{
    enum states {
      first_fcch_search, next_fcch_search, sch_search, // synchronization search part
      synchronized // receiver is synchronized in this state
    } d_state;
    //@}

    /**@name Variables which make internal state in the "synchronized" state */
    //@{
    burst_counter d_burst_nr; ///< frame number and timeslot number
    channel_configuration d_channel_conf; ///< mapping of burst_counter to burst_type
    //@}
    
    unsigned d_failed_sch; ///< number of subsequent erroneous SCH bursts
    
    // GSM Stack
    GS_CTX d_gs_ctx;//TODO: remove it! it'a not right place for a decoder

    friend gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key, std::string configuration);
    gsm_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key, std::string configuration);

    /** Function whis is used to search a FCCH burst and to compute frequency offset before
     * "synchronized" state of the receiver
     *
     * TODO: Describe the FCCH search algorithm in the documentation
     * @param input vector with input signal
     * @param nitems number of samples in the input vector
     * @return
     */
    bool find_fcch_burst(const gr_complex *input, const int nitems);

    /** Computes frequency offset from FCCH burst samples
     *
     * @param input vector with input samples
     * @param first_sample number of the first sample of the FCCH busrt
     * @param last_sample number of the last sample of the FCCH busrt
     * @return frequency offset
     */
    double compute_freq_offset(const gr_complex * input, unsigned first_sample, unsigned last_sample);

    /** Calls d_tuner's method to set frequency offset from Python level
     *
     * @param freq_offset absolute frequency offset of the received signal
     */
    void set_frequency(double freq_offset);

    /** Computes angle between two complex numbers
     *
     * @param val1 first complex number
     * @param val2 second complex number
     * @return
     */
    inline float compute_phase_diff(gr_complex val1, gr_complex val2);

    /** Function whis is used to get near to SCH burst
     *
     * @param nitems number of samples in the gsm_receiver's buffer
     * @return true if SCH burst is near, false otherwise
     */
    bool reach_sch_burst(const int nitems);

    /** Extracts channel impulse response from a SCH burst and computes first sample number of this burst
     *
     * @param input vector with input samples
     * @param chan_imp_resp complex vector where channel impulse response will be stored
     * @return number of first sample of the burst
     */
    int get_sch_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp);

    /** MLSE detection of a burst bits
     *
     * Detects bits of burst using viterbi algorithm.
     * @param input vector with input samples
     * @param chan_imp_resp vector with the channel impulse response
     * @param burst_start number of the first sample of the burst
     * @param output_binary vector with output bits
     */
    void detect_burst(const gr_complex * input, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary);

    /** Encodes differentially input bits and maps them into MSK states
     *
     * @param input vector with input bits
     * @param nitems number of samples in the "input" vector
     * @param gmsk_output bits mapped into MSK states
     * @param start_point first state
     */
    void gmsk_mapper(const unsigned char * input, int nitems, gr_complex * gmsk_output, gr_complex start_point);

    /** Correlates MSK mapped sequence with input signal
     *
     * @param sequence MKS mapped sequence
     * @param length length of the sequence
     * @param input_signal vector with input samples
     * @return correlation value
     */
    gr_complex correlate_sequence(const gr_complex * sequence, int length, const gr_complex * input);

    /** Computes autocorrelation of input vector for positive arguments
     *
     * @param input vector with input samples
     * @param out output vector
     * @param nitems length of the input vector
     */
    inline void autocorrelation(const gr_complex * input, gr_complex * out, int nitems);

    /** Filters input signal through channel impulse response
     *
     * @param input vector with input samples
     * @param nitems number of samples to pass through filter
     * @param filter filter taps - channel impulse response
     * @param filter_length nember of filter taps
     * @param output vector with filtered samples
     */
    inline void mafi(const gr_complex * input, int nitems, gr_complex * filter, int filter_length, gr_complex * output);

    /**  Extracts channel impulse response from a normal burst and computes first sample number of this burst
     *
     * @param input vector with input samples
     * @param chan_imp_resp complex vector where channel impulse response will be stored
     * @param search_range possible absolute offset of a channel impulse response start
     * @param bcc base station color code - number of a training sequence
     * @return first sample number of normal burst
     */
    int get_norm_chan_imp_resp(const gr_complex * input, gr_complex * chan_imp_resp, int bcc);

    
    /**
     *
     */
    void read_key(std::string key);
    
    /**
     *
     */
    void read_configuration(std::string configuration);

    /**
     *
     */
    void process_normal_burst(burst_counter burst_nr, const unsigned char * burst_binary, bool first_burst);

    /**
     *
     */
    void configure_receiver();
    
    

  public:
    ~gsm_receiver_cf();
    void forecast(int noutput_items, gr_vector_int &ninput_items_required);
    int general_work(int noutput_items,
                     gr_vector_int &ninput_items,
                     gr_vector_const_void_star &input_items,
                     gr_vector_void_star &output_items);
};

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