From 0a452fcc8e030f5bdb7187e1db7182cfc488aa31 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 28 May 2009 19:39:56 +0200 Subject: cleanup of unneeded test code, separation of longer parts of fch_search into two functions, addidion of 'synchronized' state and reading of sch in this state --- src/lib/gsm_receiver_cf.cc | 333 +++++++++++++++++++++++---------------------- 1 file changed, 168 insertions(+), 165 deletions(-) (limited to 'src/lib/gsm_receiver_cf.cc') diff --git a/src/lib/gsm_receiver_cf.cc b/src/lib/gsm_receiver_cf.cc index 578cd80..089a563 100644 --- a/src/lib/gsm_receiver_cf.cc +++ b/src/lib/gsm_receiver_cf.cc @@ -38,6 +38,9 @@ #define FCCH_BUFFER_SIZE (FCCH_HITS_NEEDED) #define SYNC_SEARCH_RANGE 40 +//TODO !! - move this methods to some else place + +// - move it to some else place !! typedef std::list list_float; typedef std::vector vector_float; @@ -62,14 +65,15 @@ gsm_receiver_cf::gsm_receiver_cf(gr_feval_dd *tuner, int osr) gr_make_io_signature(MIN_IN, MAX_IN, sizeof(gr_complex)), gr_make_io_signature(MIN_OUT, MAX_OUT, 142 * sizeof(float))), d_OSR(osr), + d_chan_imp_length(CHAN_IMP_RESP_LENGTH), d_tuner(tuner), d_counter(0), d_fcch_start_pos(0), d_freq_offset(0), - d_state(first_fcch_search), - d_fcch_count(0), //!! - d_x_temp(0),//!! - d_x2_temp(0)//!! + d_state(first_fcch_search) +// d_fcch_count(0), //!! +// d_x_temp(0),//!! +// d_x2_temp(0)//!! { gmsk_mapper(SYNC_BITS, d_sch_training_seq, N_SYNC_BITS); } @@ -98,6 +102,7 @@ gsm_receiver_cf::general_work(int noutput_items, float prev_freq_offset; switch (d_state) { + //bootstrapping case first_fcch_search: if (find_fcch_burst(in, ninput_items[0])) { set_frequency(d_freq_offset); @@ -113,7 +118,6 @@ gsm_receiver_cf::general_work(int noutput_items, prev_freq_offset = d_freq_offset; if (find_fcch_burst(in, ninput_items[0])) { if (abs(d_freq_offset) > 100) { - float mean_freq_offset = (prev_freq_offset + d_freq_offset) / 2; set_frequency(d_freq_offset); } produced_out = 0; @@ -126,15 +130,59 @@ gsm_receiver_cf::general_work(int noutput_items, case sch_search: if (find_sch_burst(in, ninput_items[0], out)) { -// d_state = read_bcch; - d_state = next_fcch_search;//read_bcch; + d_channel_conf.set_multiframe_type(0, multiframe_51); + d_channel_conf.set_burst_types(0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst); + d_channel_conf.set_burst_types(0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst); + d_burst_nr++; + d_state = synchronized; } else { d_state = sch_search; } break; - case read_bcch: - consume_each(ninput_items[0]); + //in this state receiver is synchronized and it processes bursts according to burst type for given burst number + case synchronized: { + gr_complex chan_imp_resp[100];//!! + burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr); + int burst_start; + int offset = 0; + int to_consume = 0; + unsigned char output_binary[BURST_SIZE]; + + switch (b_type) { + case fcch_burst: { + + } + break; + case sch_burst: { + int t1, t2, t3, d_ncc, d_bcc; + burst_start = get_sch_chan_imp_resp(in, chan_imp_resp); + detect_burst(in, chan_imp_resp, burst_start, output_binary); + if(decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0){ +// d_burst_nr.set(t1, t2, t3, 0); + printf("bcc: %d, ncc: %d, t1: %d, t2: %d, t3: %d\n", d_bcc, d_ncc, t1, t2, t3); + offset = burst_start - GUARD_BITS * d_OSR; + to_consume += offset; + } + std::cout << offset << std::endl; + } + break; + case normal_burst: + + break; + + case rach_burst: + break; + case dummy: + break; + case empty: + break; + } + + d_burst_nr++; + to_consume += floor(TS_BITS * d_OSR); + consume_each(to_consume); + } break; } @@ -158,7 +206,6 @@ bool gsm_receiver_cf::find_fcch_burst(const gr_complex *in, const int nitems) int sample_number = 0; bool end = false; bool result = false; -// float mean=0, phase_offset=0, freq_offset=0; circular_buffer_float::iterator buffer_iter; enum states { @@ -208,7 +255,6 @@ bool gsm_receiver_cf::find_fcch_burst(const gr_complex *in, const int nitems) if ((miss_count >= FCCH_MAX_MISSES * d_OSR) && (hit_count <= FCCH_HITS_NEEDED * d_OSR)) { fcch_search_state = init; - //DCOUT("hit_count: " << hit_count << " miss_count: " << miss_count << " d_counter: " << d_counter); continue; } else if (((miss_count >= FCCH_MAX_MISSES * d_OSR) && (hit_count > FCCH_HITS_NEEDED * d_OSR)) || (hit_count > 2 * FCCH_HITS_NEEDED * d_OSR)) { fcch_search_state = fcch_found; @@ -241,18 +287,15 @@ bool gsm_receiver_cf::find_fcch_burst(const gr_complex *in, const int nitems) } phase_diff = compute_phase_diff(in[sample_number], in[sample_number-1]); -// std::cout << phase_diff << "\n"; phase_diff_buffer.push_back(phase_diff); fcch_search_state = found_something; break; case fcch_found: - DCOUT("znalezione fcch na pozycji" << d_counter + start_pos); + DCOUT("fcch found on position: " << d_counter + start_pos); to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1; -// mean = d_best_sum / FCCH_HITS_NEEDED; -// phase_offset = mean - (M_PI / 2); -// freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI); + d_fcch_start_pos = d_counter + start_pos; compute_freq_offset(); end = true; @@ -281,13 +324,13 @@ double gsm_receiver_cf::compute_freq_offset() freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI); d_freq_offset -= freq_offset; - d_fcch_count++; - d_x_temp += freq_offset; - d_x2_temp += freq_offset * freq_offset; - d_mean = d_x_temp / d_fcch_count; +// d_fcch_count++; +// d_x_temp += freq_offset; +// d_x2_temp += freq_offset * freq_offset; +// d_mean = d_x_temp / d_fcch_count; - DCOUT("freq_offset: " << freq_offset );//" d_best_sum: " << d_best_sum -// DCOUT("wariancja: " << sqrt((d_x2_temp / d_fcch_count - d_mean * d_mean)) << " fcch_count:" << d_fcch_count << " d_mean: " << d_mean); + DCOUT("freq_offset: " << freq_offset );//" d_best_sum: " << d_best_sum +// DCOUT("wariance: " << sqrt((d_x2_temp / d_fcch_count - d_mean * d_mean)) << " fcch_count:" << d_fcch_count << " d_mean: " << d_mean); return freq_offset; } @@ -305,41 +348,23 @@ inline float gsm_receiver_cf::compute_phase_diff(gr_complex val1, gr_complex val bool gsm_receiver_cf::find_sch_burst(const gr_complex *in, const int nitems , float *out) { -// int sample_number = 0; int to_consume = 0; bool end = false; bool result = false; int sample_nr_near_sch_start = d_fcch_start_pos + (FRAME_BITS - SAFETY_MARGIN) * d_OSR; - vector_complex correlation_buffer; - vector_float power_buffer; - vector_float window_energy_buffer; - int strongest_window_nr; - int chan_imp_resp_center; - float max_correlation = 0; + gr_complex chan_imp_resp[CHAN_IMP_RESP_LENGTH*d_OSR]; +// vector_complex correlation_buffer; +// vector_float power_buffer; +// vector_float window_energy_buffer; enum states { - start, reach_sch, find_sch_start, search_not_finished, sch_found + start, reach_sch, find_sch_start, detect_and_decode_sch, search_not_finished, sch_found } sch_search_state; sch_search_state = start; - //!!!! - int chan_imp_length = 5; - //!!!! - gr_complex chan_imp_resp[100]; - gr_complex rhh_temp[100]; - gr_complex rhh[6]; - gr_complex filtered_burst[148]; - //!!!! - int fn_o; - int bsic_o; + int t1, t2, t3; int burst_start = 0; - unsigned int stop_states[2] = {4,12}; - float output[BURST_SIZE]; unsigned char output_binary[BURST_SIZE]; - - float energy = 0; - bool loop_end = false; - vector_float::iterator iter; while (!end) { switch (sch_search_state) { @@ -362,115 +387,16 @@ bool gsm_receiver_cf::find_sch_burst(const gr_complex *in, const int nitems , fl break; case find_sch_start: -// DCOUT("find_sch_start d_counter" << d_counter); - for (int ii = SYNC_POS * d_OSR; ii < (SYNC_POS + SYNC_SEARCH_RANGE)*d_OSR; ii++) { - to_consume++; - gr_complex correlation = correlate_sequence(&d_sch_training_seq[5], &in[ii], N_SYNC_BITS - 10); - correlation_buffer.push_back(correlation); // tylko do znalezienia odp imp kanału - power_buffer.push_back(pow(abs(correlation), 2)); - if (abs(correlation) > 30000 / 54) { -// DCOUT("znaleziono środek sch na pozycji: " << ii - SYNC_POS * d_OSR); - } - } - - //compute window energies - - iter = power_buffer.begin(); - while (iter != power_buffer.end()) { - vector_float::iterator iter_ii = iter; - energy = 0; - - for (int ii = 0; ii < (chan_imp_length)*d_OSR; ii++, iter_ii++) { - if (iter_ii == power_buffer.end()) { - loop_end = true; - break; - } - energy += (*iter_ii); - } -// std::cout << "\n"; - - if (loop_end) { - break; - } - iter++; -// std::cout << energy << "\n"; - window_energy_buffer.push_back(energy); - } - - strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin(); - d_channel_imp_resp.clear(); - -// std::cout << "# name: h_est\n" ; -// std::cout << "# type: complex matrix\n" ; -// std::cout << "# rows: 1\n" ; -// std::cout << "# columns: " << (chan_imp_length)*d_OSR << "\n"; - - max_correlation = 0; - for (int ii = 0; ii < (chan_imp_length)*d_OSR; ii++) { - gr_complex correlation = correlation_buffer[strongest_window_nr + ii]; - if (abs(correlation) > max_correlation) { - chan_imp_resp_center = ii; - max_correlation = abs(correlation); - } -// std::cout << correlation << " "; - d_channel_imp_resp.push_back(correlation); - chan_imp_resp[ii] = correlation; - } -// DCOUT("\nSrodek odp_imp:" << chan_imp_resp_center ); - - autocorrelation(chan_imp_resp, rhh_temp, chan_imp_length*d_OSR); -// std::cout << "\n# name: rhh_temp\n" ; -// std::cout << "# type: complex matrix\n" ; -// std::cout << "# rows: 1\n" ; -// std::cout << "# columns: " << (chan_imp_length)*d_OSR << "\n"; - -// for (int ii = 0; ii < (chan_imp_length)*d_OSR; ii++) { -// std::cout << rhh_temp[ii] << " "; -// } - -// std::cout << "\n# name: Rhh\n" ; -// std::cout << "# type: complex matrix\n" ; -// std::cout << "# rows: 1\n" ; -// std::cout << "# columns: " << (chan_imp_length) << "\n"; - - for (int ii = 0; ii < (chan_imp_length); ii++) { - rhh[ii] = conj(rhh_temp[ii*d_OSR]); -// std::cout << rhh[ii] << " "; - } - -// std::cout << "\n# name: normal_burst\n" ; -// std::cout << "# type: complex matrix\n" ; -// std::cout << "# rows: 1\n" ; -// std::cout << "# columns: " << 156*d_OSR << "\n"; - burst_start = strongest_window_nr + chan_imp_resp_center - 48 * d_OSR - 2 * d_OSR + 2 + SYNC_POS * d_OSR; - for (int ii = 0; ii < 156*d_OSR; ii++) { - gr_complex sample = in[burst_start+ii]; -// std::cout << sample << " "; - } - - mafi(&in[burst_start], 148, chan_imp_resp, chan_imp_length*d_OSR, filtered_burst); - -// std::cout << "\n# name: Y\n" ; -// std::cout << "# type: complex matrix\n" ; -// std::cout << "# rows: 1\n" ; -// std::cout << "# columns: " << 148 << "\n"; - for (int ii = 0; ii < 148; ii++) { - gr_complex filtered_sample = filtered_burst[ii]; -// std::cout << filtered_sample << " "; - } - - viterbi_detector(filtered_burst, 148, rhh, 3, stop_states, 2, output); -// printf("# name: output\n# type: matrix\n# rows: 1\n# columns: 148\n"); - for(int i=0; i0); -// printf(" %d", output_binary[i]); - } -// printf("\n"); - decode_sch(&output_binary[3], &fn_o, &bsic_o); - -// std::cout << "fn: " << fn_o << " bsic: " << bsic_o << "\n"; -// DCOUT("strongest_window_nr: " << strongest_window_nr); + burst_start = get_sch_chan_imp_resp(in, chan_imp_resp); + sch_search_state = detect_and_decode_sch; + break; + case detect_and_decode_sch: + detect_burst(in, chan_imp_resp, burst_start, output_binary); + decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc); + d_burst_nr.set(t1, t2, t3, 0); + printf("bcc: %d, ncc: %d, t1: %d, t2: %d, t3: %d\n", d_bcc, d_ncc, t1, t2, t3); + to_consume += burst_start + BURST_SIZE * d_OSR; sch_search_state = sch_found; break; @@ -491,6 +417,87 @@ bool gsm_receiver_cf::find_sch_burst(const gr_complex *in, const int nitems , fl return result; } +int gsm_receiver_cf::get_sch_chan_imp_resp(const gr_complex *in, gr_complex * chan_imp_resp) +{ + vector_complex correlation_buffer; + vector_float power_buffer; + vector_float window_energy_buffer; + + int strongest_window_nr; + int burst_start = 0; + int chan_imp_resp_center; + float max_correlation = 0; + float energy = 0; + + for (int ii = SYNC_POS * d_OSR; ii < (SYNC_POS + SYNC_SEARCH_RANGE)*d_OSR; ii++) { + gr_complex correlation = correlate_sequence(&d_sch_training_seq[5], &in[ii], N_SYNC_BITS - 10); + correlation_buffer.push_back(correlation); + power_buffer.push_back(pow(abs(correlation), 2)); + } + + //compute window energies + vector_float::iterator iter = power_buffer.begin(); + bool loop_end = false; + while (iter != power_buffer.end()) { + vector_float::iterator iter_ii = iter; + energy = 0; + + for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++, iter_ii++) { + if (iter_ii == power_buffer.end()) { + loop_end = true; + break; + } + energy += (*iter_ii); + } + if (loop_end) { + break; + } + iter++; + window_energy_buffer.push_back(energy); + } + + strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin(); + d_channel_imp_resp.clear(); + + max_correlation = 0; + for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++) { + gr_complex correlation = correlation_buffer[strongest_window_nr + ii]; + if (abs(correlation) > max_correlation) { + chan_imp_resp_center = ii; + max_correlation = abs(correlation); + } + d_channel_imp_resp.push_back(correlation); + chan_imp_resp[ii] = correlation; + } + + burst_start = strongest_window_nr + chan_imp_resp_center - 48 * d_OSR - 2 * d_OSR + 2 + SYNC_POS * d_OSR; + return burst_start; +} + +void gsm_receiver_cf::detect_burst(const gr_complex * in, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary) +{ + float output[BURST_SIZE]; + gr_complex rhh_temp[CHAN_IMP_RESP_LENGTH*d_OSR]; + gr_complex rhh[CHAN_IMP_RESP_LENGTH]; + gr_complex filtered_burst[BURST_SIZE]; + int start_state = 3; + unsigned int stop_states[2] = {4, 12}; + + autocorrelation(chan_imp_resp, rhh_temp, d_chan_imp_length*d_OSR); + for (int ii = 0; ii < (d_chan_imp_length); ii++) { + rhh[ii] = conj(rhh_temp[ii*d_OSR]); + } + + mafi(&in[burst_start], BURST_SIZE, chan_imp_resp, d_chan_imp_length*d_OSR, filtered_burst); + + viterbi_detector(filtered_burst, BURST_SIZE, rhh, start_state, stop_states, 2, output); + + for (int i = 0; i < BURST_SIZE ; i++) { + output_binary[i] = (output[i] > 0); + } +} + +//TODO consider placing this funtion in a separate class for signal processing void gsm_receiver_cf::gmsk_mapper(const int * input, gr_complex * output, int ninput) { gr_complex j = gr_complex(0.0, 1.0); @@ -511,6 +518,7 @@ void gsm_receiver_cf::gmsk_mapper(const int * input, gr_complex * output, int ni } } +//TODO consider use of some generalized function for correlation and placing it in a separate class for signal processing gr_complex gsm_receiver_cf::correlate_sequence(const gr_complex * sequence, const gr_complex * input_signal, int length) { gr_complex result(0.0, 0.0); @@ -521,7 +529,7 @@ gr_complex gsm_receiver_cf::correlate_sequence(const gr_complex * sequence, cons result += sequence[ii] * conj(input_signal[sample_number]); } - result = result/gr_complex(length, 0); + result = result / gr_complex(length, 0); return result; } @@ -543,6 +551,7 @@ gr_complex gsm_receiver_cf::correlate_sequence(const gr_complex * sequence, cons // } //oblicza dodatnią część autokorelacji +//TODO consider placing this funtion in a separate class for signal processing inline void gsm_receiver_cf::autocorrelation(const gr_complex * input, gr_complex * out, int length) { int i, k; @@ -554,29 +563,23 @@ inline void gsm_receiver_cf::autocorrelation(const gr_complex * input, gr_comple } } +//TODO consider use of some generalized function for filtering and placing it in a separate class for signal processing //funkcja matched filter inline void gsm_receiver_cf::mafi(const gr_complex * input, int input_length, gr_complex * filter, int filter_length, gr_complex * output) { int ii = 0, n, a; -// std::cout << "\nfilter:"; -// for(n = 0; n < filter_length; n++) -// { -// std::cout << filter[n] << " "; -// } -// std::cout << "\n"; + for (n = 0; n < input_length; n++) { a = n * d_OSR; output[n] = 0; ii = 0; - + while (ii < filter_length) { if ((a + ii) >= input_length*d_OSR) break; -// if(n==0) -// std::cout << input[a+ii] << " "; output[n] += input[a+ii] * filter[ii]; //!!conj ii++; } - output[n] = output[n]*gr_complex(0,-1);//!!nie powinno tego tu być + output[n] = output[n] * gr_complex(0, -1);//!!this shouldn't be here } } -- cgit v1.2.3