summaryrefslogtreecommitdiff
path: root/src/lib/gsm_receiver_cf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/gsm_receiver_cf.cc')
-rw-r--r--src/lib/gsm_receiver_cf.cc333
1 files changed, 168 insertions, 165 deletions
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<float> list_float;
typedef std::vector<float> 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; i<BURST_SIZE ; i++){
- output_binary[i] = (output[i]>0);
-// 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
}
}
personal git repositories of Harald Welte. Your mileage may vary