airprobe/src/lib/gsm_receiver_cf.h

306 lines
9.0 KiB
C++

/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio 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.
*
* GNU Radio 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 GNU Radio; 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 <gr_block.h>
#include <gr_complex.h>
#include <gr_feval.h>
#include <gsm_constants.h>
#include <vector>
//TODO !! - move this classes to some other place
#include <vector>
#include <algorithm>
#include <math.h>
typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy} burst_type;
typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type;
class multiframe_configuration
{
private:
multiframe_type d_type;
std::vector<burst_type> d_burst_types;
public:
multiframe_configuration() {
d_type = unknown;
fill(d_burst_types.begin(), d_burst_types.end(), empty);
}
// multiframe_configuration(multiframe_type type, const std::vector<burst_type> & burst_types):
// d_type(type) {
// d_burst_types.resize(burst_types.size());
// copy(burst_types.begin(), burst_types.end(), d_burst_types.begin());
// }
// multiframe_configuration(multiframe_configuration & conf) {
// d_type = conf.d_type;
// copy(conf.d_burst_types.begin(), conf.d_burst_types.end(), d_burst_types.begin());
// }
~multiframe_configuration() {}
void set_type(multiframe_type type) {
if (type == multiframe_26) {
d_burst_types.resize(26);
} else {
d_burst_types.resize(51);
}
d_type = type;
}
void set_burst_type(int nr, burst_type type) {
d_burst_types[nr] = type;
}
multiframe_type get_type() {
return d_type;
}
burst_type get_burst_type(int nr) {
return d_burst_types[nr];
}
};
class burst_counter
{
private:
const int d_OSR;
uint32_t d_t1, d_t2, d_t3, d_timeslot_nr;
double d_first_sample_offset;
double d_offset;
public:
burst_counter(int osr):
d_OSR(osr),
d_t1(0),
d_t2(0),
d_t3(0),
d_timeslot_nr(0),
d_first_sample_offset(0),
d_offset(0) {
}
burst_counter(int osr, uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr):
d_OSR(osr),
d_t1(t1),
d_t2(t2),
d_t3(t3),
d_timeslot_nr(timeslot_nr),
d_offset(0) {
double first_sample_position = (get_frame_nr()*8+timeslot_nr)*TS_BITS;
d_first_sample_offset = first_sample_position - floor(first_sample_position);
}
burst_counter & operator++(int) {
d_timeslot_nr++;
if (d_timeslot_nr == TS_PER_FRAME) {
d_timeslot_nr = 0;
if ((d_t2 == 25) && (d_t3 == 50)) {
d_t1 = (d_t1 + 1) % (1 << 11);
}
d_t2 = (d_t2 + 1) % 26;
d_t3 = (d_t3 + 1) % 51;
}
d_first_sample_offset += GUARD_FRACTIONAL * d_OSR;
d_offset = floor(d_first_sample_offset);
d_first_sample_offset = d_first_sample_offset - d_offset;
return (*this);
}
void set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr) {
d_t1 = t1;
d_t2 = t2;
d_t3 = t3;
d_timeslot_nr = timeslot_nr;
double first_sample_position = (get_frame_nr()*8+timeslot_nr)*TS_BITS;
d_first_sample_offset = first_sample_position - floor(first_sample_position);
d_offset = 0;
}
uint32_t get_t1() {
return d_t1;
}
uint32_t get_t2() {
return d_t2;
}
uint32_t get_t3() {
return d_t3;
}
uint32_t get_timeslot_nr() {
return d_timeslot_nr;
}
uint32_t get_frame_nr() {
return (51 * 26 * d_t1) + (51 * (((d_t3 + 26) - d_t2) % 26)) + d_t3;
}
unsigned get_offset(){
return (unsigned)d_offset;
}
};
class channel_configuration
{
private:
multiframe_configuration d_timeslots_descriptions[TS_PER_FRAME];
public:
channel_configuration() {
for (int i = 0; i < TS_PER_FRAME; i++) {
d_timeslots_descriptions[i].set_type(unknown);
}
}
// void set_timeslot_desc(int timeslot_nr, multiframe_configuration conf){
// d_timeslots_descriptions[timeslot_nr] = conf;
// }
void set_multiframe_type(int timeslot_nr, multiframe_type type) {
d_timeslots_descriptions[timeslot_nr].set_type(type);
}
void set_burst_types(int timeslot_nr, const unsigned mapping[], unsigned mapping_size, burst_type b_type) {
unsigned i;
for (i = 0; i < mapping_size; i++) {
d_timeslots_descriptions[timeslot_nr].set_burst_type(mapping[i], b_type);
}
}
void set_single_burst_type(int timeslot_nr, int burst_nr, burst_type b_type) {
d_timeslots_descriptions[timeslot_nr].set_burst_type(burst_nr, b_type);
}
burst_type get_burst_type(burst_counter burst_nr);
};
burst_type channel_configuration::get_burst_type(burst_counter burst_nr)
{
uint32_t timeslot_nr = burst_nr.get_timeslot_nr();
multiframe_type m_type = d_timeslots_descriptions[timeslot_nr].get_type();
uint32_t nr;
switch (m_type) {
case multiframe_26:
nr = burst_nr.get_t2();
break;
case multiframe_51:
nr = burst_nr.get_t3();
break;
default:
nr = 0;
break;
}
return d_timeslots_descriptions[timeslot_nr].get_burst_type(nr);
}
// move it to some other place !!
class gsm_receiver_cf;
typedef boost::shared_ptr<gsm_receiver_cf> gsm_receiver_cf_sptr;
typedef std::vector<gr_complex> vector_complex;
/*!
* \brief Return a shared_ptr to a new instance of gsm_receiver_cf.
*
* To avoid accidental use of raw pointers, gsm_receiver_cf's
* constructor is private. howto_make_square_ff is the public
* interface for creating new instances.
*/
gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, int osr);
/*!
* \brief Receives fcch
* \ingroup block
* \sa
*/
class gsm_receiver_cf : public gr_block
{
private:
const int d_OSR;
const int d_chan_imp_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];
gr_feval_dd *d_tuner;
unsigned d_counter;
//variables used to store result of the find_fcch_burst fuction
int d_fcch_start_pos;
float d_freq_offset;
// double d_best_sum;
// int d_fcch_count; //!!!
// double d_x_temp, d_x2_temp, d_mean;//!!
burst_counter d_burst_nr;
channel_configuration d_channel_conf;
vector_complex d_channel_imp_resp;
int d_ncc;
int d_bcc;
enum states {
//synchronization search part
first_fcch_search, next_fcch_search, sch_search, synchronized
//
} d_state;
friend gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, int osr);
gsm_receiver_cf(gr_feval_dd *tuner, int osr);
bool find_fcch_burst(const gr_complex *in, const int nitems);
double compute_freq_offset(double best_sum, unsigned denominator);
void set_frequency(double freq_offset);
inline float compute_phase_diff(gr_complex val1, gr_complex val2);
bool find_sch_burst(const gr_complex *in, const int nitems , float *out);
int get_sch_chan_imp_resp(const gr_complex *in, gr_complex * chan_imp_resp);
void detect_burst(const gr_complex * in, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary);
void gmsk_mapper(const unsigned char * input, int ninput, gr_complex * gmsk_output, gr_complex start_point);
gr_complex correlate_sequence(const gr_complex * sequence, const gr_complex * input_signal, int ninput);
inline void autocorrelation(const gr_complex * input, gr_complex * out, int length);
inline void mafi(const gr_complex * input, int input_length, gr_complex * filter, int filter_length, gr_complex * output);
int get_norm_chan_imp_resp(const gr_complex *in, gr_complex * chan_imp_resp, unsigned search_range);
void detect_norm_burst(const gr_complex * in, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary);
inline void mafi_norm(const gr_complex * input, int input_length, gr_complex * filter, int filter_length, gr_complex * output);
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 */