From 58213797c17bc5fe397f067152363eb95f596b92 Mon Sep 17 00:00:00 2001 From: ptrkrysik Date: Thu, 30 Oct 2014 09:05:15 +0100 Subject: First step to add multichannel capability to the GSM receiver. At this moment it might still contain debuging code. The training sequence number for non C0 channels is embedded in the code. --- lib/receiver/gsm_constants.h | 2 +- lib/receiver/receiver_impl.cc | 250 +++++++++++++++++++++++------------------- lib/receiver/receiver_impl.h | 6 +- 3 files changed, 144 insertions(+), 114 deletions(-) (limited to 'lib') diff --git a/lib/receiver/gsm_constants.h b/lib/receiver/gsm_constants.h index 0308d96..01d089b 100644 --- a/lib/receiver/gsm_constants.h +++ b/lib/receiver/gsm_constants.h @@ -37,7 +37,7 @@ #define MAX_SCH_ERRORS 10 //maximum number of subsequent sch errors after which gsm receiver goes to find_next_fcch state -typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal} burst_type; +typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal, normal_or_noise} burst_type; typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type; static const unsigned char SYNC_BITS[] = { diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc index 0917f1e..de3438c 100644 --- a/lib/receiver/receiver_impl.cc +++ b/lib/receiver/receiver_impl.cc @@ -38,7 +38,9 @@ #include #include #include -//#include "plotting/plotting.hpp" + +#include "plotting/plotting.hpp" +#include #define SYNC_SEARCH_RANGE 30 @@ -64,7 +66,7 @@ receiver::make(int osr, int arfcn) */ receiver_impl::receiver_impl(int osr, int arfcn) : gr::sync_block("receiver", - gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, -1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0)), d_OSR(osr), d_chan_imp_length(CHAN_IMP_RESP_LENGTH), @@ -104,7 +106,8 @@ receiver_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - const gr_complex *input = (const gr_complex *) input_items[0]; +// std::vector iii = (std::vector) input_items; // jak zrobić to rzutowanie poprawnie + gr_complex * input = (gr_complex *) input_items[0]; std::vector freq_offset_tags; uint64_t start = nitems_read(0); uint64_t stop = start + noutput_items; @@ -122,7 +125,6 @@ receiver_impl::work(int noutput_items, if(d_state == synchronized && b_type == fcch_burst){ uint64_t last_sample_nr = ceil((GUARD_PERIOD + 2.0 * TAIL_BITS + 156.25) * d_OSR) + 1; if(tag_offset < last_sample_nr){ - DCOUT("Freq change inside FCCH burst!!!!!!!!!!!!!!"); freq_offset_tag_in_fcch = true; } d_freq_offset_setting = pmt::to_double(freq_offset_tag.value); @@ -134,9 +136,8 @@ receiver_impl::work(int noutput_items, switch (d_state) { //bootstrapping - case fcch_search: //this state is used because it takes some time (a bunch of buffered samples) + case fcch_search: { - DCOUT("FCCH search"); double freq_offset_tmp; if (find_fcch_burst(input, noutput_items,freq_offset_tmp)) { @@ -154,7 +155,6 @@ receiver_impl::work(int noutput_items, case sch_search: { - DCOUT("SCH search"); vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR); int t1, t2, t3; int burst_start = 0; @@ -166,8 +166,6 @@ receiver_impl::work(int noutput_items, detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //detect bits using MLSE detection if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //decode SCH burst { - DCOUT("sch burst_start: " << burst_start); - DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3); d_burst_nr.set(t1, t2, t3, 0); //set counter of bursts value d_burst_nr++; @@ -188,109 +186,157 @@ receiver_impl::work(int noutput_items, //in this state receiver is synchronized and it processes bursts according to burst type for given burst number case synchronized: { - DCOUT("Synchronized"); vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR); - int burst_start; int offset = 0; int to_consume = 0; unsigned char output_binary[BURST_SIZE]; - burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr); //get burst type for given burst number - double signal_pwr = 0; - for(int ii=0;ii(round(10*log10(signal_pwr/50/noutput_items))); + burst_type b_type; - switch (b_type) - { - case fcch_burst: //if it's FCCH burst - { - const unsigned first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1; - const unsigned last_sample = first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR; - double freq_offset_tmp = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it - - send_burst(d_burst_nr, fc_fb, b_type); - - pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("synchronized")); - message_port_pub(pmt::mp("measurements"), msg); - } - break; - case sch_burst: //if it's SCH burst + for(int input_nr=0;input_nr= MAX_SCH_ERRORS) + case fcch_burst: //if it's FCCH burst + { + const unsigned first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1; + const unsigned last_sample = first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR; + double freq_offset_tmp = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it + + send_burst(d_burst_nr, fc_fb, b_type); + + pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("synchronized")); + message_port_pub(pmt::mp("measurements"), msg); + break; + } + case sch_burst: //if it's SCH burst + { + int t1, t2, t3, d_ncc, d_bcc; + d_c0_burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response + + detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); //MLSE detection of bits + send_burst(d_burst_nr, output_binary, b_type); + if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //and decode SCH data + { + // d_burst_nr.set(t1, t2, t3, 0); //but only to check if burst_start value is correct + d_failed_sch = 0; + offset = d_c0_burst_start - floor((GUARD_PERIOD) * d_OSR); //compute offset from burst_start - burst should start after a guard period + to_consume += offset; //adjust with offset number of samples to be consumed + } + else { - d_state = fcch_search; - pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(0.0),pmt::mp("sync_loss")); - message_port_pub(pmt::mp("measurements"), msg); - COUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + d_failed_sch++; + if (d_failed_sch >= MAX_SCH_ERRORS) + { + d_state = fcch_search; + pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(0.0),pmt::mp("sync_loss")); + message_port_pub(pmt::mp("measurements"), msg); + DCOUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + } } + break; } - } - break; - - case normal_burst: - { - float normal_corr_max; //if it's normal burst - burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); //get channel impulse response for given training sequence number - d_bcc - detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits - send_burst(d_burst_nr, output_binary, b_type); - break; - } - case dummy_or_normal: - { - unsigned int normal_burst_start; - float dummy_corr_max, normal_corr_max; - get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY); - normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); - - DCOUT("normal_corr_max: " << normal_corr_max << " dummy_corr_max:" << dummy_corr_max); - if (normal_corr_max > dummy_corr_max) + case normal_burst: { - detect_burst(input, &channel_imp_resp[0], normal_burst_start, output_binary); - send_burst(d_burst_nr, output_binary, b_type); + float normal_corr_max; //if it's normal burst + d_c0_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); //get channel impulse response for given training sequence number - d_bcc + detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); //MLSE detection of bits + send_burst(d_burst_nr, output_binary, b_type); + break; } - else + case dummy_or_normal: { + unsigned int normal_burst_start, dummy_burst_start; + float dummy_corr_max, normal_corr_max; + + dummy_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY); + normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); + + if (normal_corr_max > dummy_corr_max) + { + d_c0_burst_start = normal_burst_start; + detect_burst(input, &channel_imp_resp[0], normal_burst_start, output_binary); + send_burst(d_burst_nr, output_binary, b_type); + } + else + { + d_c0_burst_start = dummy_burst_start; + send_burst(d_burst_nr, dummy_burst, b_type); + } + break; + } + case rach_burst: + break; + case dummy: send_burst(d_burst_nr, dummy_burst, b_type); + break; + case normal_or_noise: + { + unsigned int burst_start; + float normal_corr_max_tmp; + float normal_corr_max=-1e6; + int max_tn; + std::vector v(input, input + noutput_items); + if(d_signal_dbm>=d_c0_signal_dbm-13) + { + plot(v); + + burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, 7); +// if(abs(d_c0_burst_start-burst_start)<=2){ + if((normal_corr_max/sqrt(signal_pwr))>=0.9){ + std::cout << static_cast(d_signal_dbm) << std::endl; + COUT("d_c0_burst_start: " << d_c0_burst_start); + COUT("burst_start: " << burst_start); + std::cout << "corr max to signal ratio: " << (normal_corr_max/sqrt(signal_pwr)) << std::endl; + usleep(4e6); + } + detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); + send_burst(d_burst_nr, output_binary, b_type); + } + break; } + case empty: //if it's empty burst + break; //do nothing + } + + if(input_nr==0) + { + d_burst_nr++; //go to next burst + to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); //consume samples of the burst up to next guard period + } + + if(input_nr==input_items.size()-1) + { + consume_each(to_consume); + } + //and add offset which is introduced by + //0.25 fractional part of a guard period } - case rach_burst: - break; - case dummy: - send_burst(d_burst_nr, dummy_burst, b_type); - break; - case empty: //if it's empty burst - break; //do nothing - } - - d_burst_nr++; //go to next burst - to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); //consume samples of the burst up to next guard period - //and add offset which is introduced by - //0.25 fractional part of a guard period - consume_each(to_consume); } break; } - return 0; } @@ -432,7 +478,6 @@ bool receiver_impl::find_fcch_burst(const gr_complex *input, const int nitems, d case fcch_found: { - DCOUT("fcch found on position: " << d_counter + start_pos); to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1; //consume one FCCH burst d_fcch_start_pos = d_counter + start_pos; @@ -531,7 +576,6 @@ int receiver_impl::get_sch_chan_imp_resp(const gr_complex *input, gr_complex * c correlation_buffer.push_back(correlation); power_buffer.push_back(std::pow(abs(correlation), 2)); } - //plot(power_buffer); //compute window energies vector_float::iterator iter = power_buffer.begin(); bool loop_end = false; @@ -693,14 +737,13 @@ int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex * // int search_start_pos = search_center - d_chan_imp_length * d_OSR; int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 5 * d_OSR; - for (int ii = search_start_pos; ii < search_stop_pos; ii++) + for(int ii = search_start_pos; ii < search_stop_pos; ii++) { gr_complex correlation = correlate_sequence(&d_norm_training_seq[bcc][TRAIN_BEGINNING], N_TRAIN_BITS - 10, &input[ii]); - correlation_buffer.push_back(correlation); power_buffer.push_back(std::pow(abs(correlation), 2)); } - + //plot(power_buffer); //compute window energies vector_float::iterator iter = power_buffer.begin(); bool loop_end = false; @@ -748,10 +791,10 @@ int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex * *corr_max = max_correlation; - DCOUT("strongest_window_nr_new: " << strongest_window_nr); + //DCOUT("strongest_window_nr_new: " << strongest_window_nr); burst_start = search_start_pos + strongest_window_nr - TRAIN_POS * d_OSR; //compute first sample posiiton which corresponds to the first sample of the impulse response - DCOUT("burst_start: " << burst_start); + //DCOUT("burst_start: " << burst_start); return burst_start; } @@ -785,21 +828,6 @@ void receiver_impl::configure_receiver() d_channel_conf.set_burst_types(TIMESLOT0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst); d_channel_conf.set_burst_types(TIMESLOT0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst); - // d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT1, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - // d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT2, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - // d_channel_conf.set_multiframe_type(TIMESLOT3, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT3, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - // d_channel_conf.set_multiframe_type(TIMESLOT4, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT4, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - // d_channel_conf.set_multiframe_type(TIMESLOT5, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT5, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - // d_channel_conf.set_multiframe_type(TIMESLOT6, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT6, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - // d_channel_conf.set_multiframe_type(TIMESLOT7, multiframe_26); - // d_channel_conf.set_burst_types(TIMESLOT7, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal); - d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_51); d_channel_conf.set_burst_types(TIMESLOT1, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal); d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_51); diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index 3e962c7..08a2c44 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -34,16 +34,18 @@ namespace gr { class receiver_impl : public receiver { private: + unsigned int d_c0_burst_start; + float d_c0_signal_dbm; /**@name Configuration of the receiver */ //@{ const int d_OSR; ///< oversampling ratio const int d_chan_imp_length; ///< channel impulse length uint16_t d_arfcn; - int8_t d_signal_dbm; + float d_signal_dbm; //@} gr_complex d_sch_training_seq[N_SYNC_BITS]; ///