summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am10
-rw-r--r--src/lib/gsm_constants.h9
-rw-r--r--src/lib/gsm_receiver_cf.cc272
-rw-r--r--src/lib/gsm_receiver_cf.h203
-rw-r--r--src/lib/gsm_receiver_config.cc63
-rw-r--r--src/lib/gsm_receiver_config.h143
-rw-r--r--src/lib/viterbi_detector.h5
7 files changed, 386 insertions, 319 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 78c7511..59504c4 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -66,7 +66,9 @@ _gsm_la_SOURCES = \
gsm.cc
libgsmdemod_la_SOURCES = \
- gsm_receiver_cf.cc
+ gsm_receiver_cf.cc \
+ gsm_receiver_config.cc \
+ viterbi_detector.cc
# magic flags
_gsm_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version
@@ -87,7 +89,11 @@ gsm.cc gsm.py: $(LOCAL_IFILES) $(ALL_IFILES)
# These headers get installed in ${prefix}/include/gnuradio
grinclude_HEADERS = \
- gsm_receiver_cf.h
+ gsm_receiver_cf.h \
+ gsm_receiver_config.h
+
+noinst_HEADERS = \
+ viterbi_detector.h
# These swig headers get installed in ${prefix}/include/gnuradio/swig
swiginclude_HEADERS = \
diff --git a/src/lib/gsm_constants.h b/src/lib/gsm_constants.h
index 520ff4f..bc16902 100644
--- a/src/lib/gsm_constants.h
+++ b/src/lib/gsm_constants.h
@@ -22,7 +22,7 @@
#define FRAME_BITS (TS_PER_FRAME * TS_BITS + 2) // 156.25 * 8
#define FCCH_POS TAIL_BITS
#define SYNC_POS 39
-#define TRAIN_POS TAIL_BITS + DATA_BITS + 5 //first 5 bits of a training sequence
+#define TRAIN_POS ( TAIL_BITS + DATA_BITS + 5) //first 5 bits of a training sequence
//aren't used for channel impulse response estimation
#define TRAIN_BEGINNING 5
#define SAFETY_MARGIN 6 //
@@ -41,9 +41,12 @@ static const unsigned char SYNC_BITS[] = {
};
const unsigned FCCH_FRAMES[] = {0, 10, 20, 30, 40};
-const unsigned SCH_FRAMES[] = {1, 11, 21, 31, 41};
-const unsigned BCCH_FRAMES[] = {2, 3, 4, 5};
+const unsigned SCH_FRAMES[] = {1,11,21,31,41};
+const unsigned BCCH_FRAMES[] = {2,3,4,5}; //!!the receiver shouldn't care about logical
+const unsigned TRAFFIC_CHANNEL_F[] = {0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24};
+ //!!channels so this will be removed from this header
+const unsigned TEST[] = {0, 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};
// Sync : .+...++.+..+++.++++++.++++++....++.+..+.+.+++.+.+...+..++++..+..
// Diff Encoded Sync: .++..+.+++.+..++.....++.....+...+.+++.+++++..+++++..++.+...+.++.
diff --git a/src/lib/gsm_receiver_cf.cc b/src/lib/gsm_receiver_cf.cc
index c1280f4..1ee823c 100644
--- a/src/lib/gsm_receiver_cf.cc
+++ b/src/lib/gsm_receiver_cf.cc
@@ -39,9 +39,54 @@
#define SYNC_SEARCH_RANGE 30
#define TRAIN_SEARCH_RANGE 40
-//TODO !! - move this methods to some else place
+//tutaj umieściłem funkcję która dostaje normalny pakiet + numer
+//numer pakietu to numer ramki + numer szczeliny czasowej
+//w tym przykładzie po prostu wyrzuca zawartość pakietu na wyjście
+//ps. pakiety które nie mają trzech zer na początku zazwyczaj są błędnie odebrane
+//ewentulanie innego typu (np. obierasz dummy jako normalny)
+void gsm_receiver_cf::przetwarzaj_normalny_pakiet(burst_counter burst_nr, unsigned char * pakiet)
+{
+ if (burst_nr.get_timeslot_nr() == 6) {
+ printf("burst = [ ");
+ for (int i = 0; i < BURST_SIZE ; i++) {
+ printf(" %d", pakiet[i]);
+ }
+ printf("];\n");
+// std::cout << " t2: " << burst_nr.get_t2() << "\n";
+ }
+}
+
+// Tutaj ustawia się jekie rodzaje pakietów przypadają na dane stany licznika.
+// Licznik ramek składa składa się z trzech części: t3,t2,t1.
+// T3 liczy modulo 51, a t2 liczy modulo 26.
+// Ja zakładam, że dla danej szczeliny do określenia jaki typ pakietu przypada
+// dla danej chwili może być używany tylko jeden z tych liczników. Z dokumentu
+// 3gpp 04.03 wynika, że to jest prawda w warstwie fizycznej.
+void gsm_receiver_cf::konfiguruj_odbiornik()
+{
+ // poniżej jest przykład jak się konfiguruje odbiornik
+ // najpierw mówię mu, że szczelina w szczelinie nr.0 typy pakietów zmieniają się wg.
+ // licznika t3, czyli modulo 51:
+
+ d_channel_conf.set_multiframe_type(TSC0, multiframe_51);
+ // tutaj mówię mu, gdzie ma szukać pakietów korekcji częstotliwości FCCH
+ // w gsm_constants jest definicja: const unsigned FCCH_FRAMES[] = {0, 10, 20, 30, 40};
+ // kanał fcch jest nadawany zawsze w w szczelinie nr.0 więc podaję najapierw TSC0
+ // potem wartości licznika z tej wcześniej zdefiniowanej tablicy, dalej ilość elementów tablicy,
+ // a na końcu typ pakietu
+ // typy są zdefiniowane w gsm_receiver_config.h
+ d_channel_conf.set_burst_types(TSC0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
+
+ //w plikach z danymi są opisy i tam można znaleźć nr. szczeliny, w której nadawany był głos
+ //w pierwszym to jest:
+ //Traffic channel timeslot: 6
+ //mogę skonfigurować żeby odbiornik na ślepo szukał tam pakietów normalnych, bez uciekania
+ //się do dekodowania informacji sterującej:
+// d_channel_conf.set_multiframe_type(TSC6, multiframe_26);
+// d_channel_conf.set_burst_types(TSC6, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), normal_burst);
+}
+
-// - move it to some else place !!
typedef std::list<float> list_float;
typedef std::vector<float> vector_float;
@@ -71,8 +116,8 @@ gsm_receiver_cf::gsm_receiver_cf(gr_feval_dd *tuner, int osr)
d_counter(0),
d_fcch_start_pos(0),
d_freq_offset(0),
- d_state(first_fcch_search),
- d_burst_nr(osr)
+ d_burst_nr(osr),
+ d_state(first_fcch_search)
{
int i;
gmsk_mapper(SYNC_BITS, N_SYNC_BITS, d_sch_training_seq, gr_complex(0.0, -1.0));
@@ -133,101 +178,106 @@ gsm_receiver_cf::general_work(int noutput_items,
break;
case sch_search: {
- gr_complex chan_imp_resp[CHAN_IMP_RESP_LENGTH*d_OSR];
- int t1, t2, t3;
- int burst_start = 0;
- unsigned char output_binary[BURST_SIZE];
-
- if (find_sch_burst(in, ninput_items[0], out)) {
- 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) {
- DCOUT("sch burst_start: " << burst_start);
- d_burst_nr.set(t1, t2, t3, 0);
- DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
- d_channel_conf.set_multiframe_type(TSC0, multiframe_51);
- d_channel_conf.set_burst_types(TSC0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
- d_channel_conf.set_burst_types(TSC0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst);
- d_channel_conf.set_burst_types(TSC0, BCCH_FRAMES, sizeof(BCCH_FRAMES) / sizeof(unsigned), normal_burst);
- d_burst_nr++;
-
- consume_each(burst_start + BURST_SIZE * d_OSR);
- d_state = synchronized;
+ gr_complex chan_imp_resp[CHAN_IMP_RESP_LENGTH*d_OSR];
+ int t1, t2, t3;
+ int burst_start = 0;
+ unsigned char output_binary[BURST_SIZE];
+
+ if (find_sch_burst(in, ninput_items[0], out)) {
+ 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) {
+ DCOUT("sch burst_start: " << burst_start);
+ d_burst_nr.set(t1, t2, t3, 0);
+ DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
+ d_channel_conf.set_multiframe_type(TSC0, multiframe_51);
+ konfiguruj_odbiornik();//!!
+ d_channel_conf.set_burst_types(TSC0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
+ d_channel_conf.set_burst_types(TSC0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst);
+ d_channel_conf.set_burst_types(TSC0, BCCH_FRAMES, sizeof(BCCH_FRAMES) / sizeof(unsigned), normal_burst);
+ d_burst_nr++;
+
+ consume_each(burst_start + BURST_SIZE * d_OSR);
+ d_state = synchronized;
+ } else {
+ d_state = next_fcch_search;
+ }
} else {
- d_state = next_fcch_search;
+ d_state = sch_search;
}
- } else {
- d_state = sch_search;
+ break;
}
- break;
- }
- //in this state receiver is synchronized and it processes bursts according to burst type for given burst number
+ //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[d_chan_imp_length*d_OSR];
- 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: {
- int ii;
- int first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1;
- int last_sample = first_sample + USEFUL_BITS * d_OSR;
- double phase_sum = 0;
- for (ii = first_sample; ii < last_sample; ii++) {
- double phase_diff = compute_phase_diff(in[ii], in[ii-1]) - (M_PI / 2) / d_OSR;
- phase_sum += phase_diff;
- }
- double freq_offset = compute_freq_offset(phase_sum, last_sample - first_sample);
- if (abs(freq_offset) > FCCH_MAX_FREQ_OFFSET) {
- d_freq_offset -= freq_offset;
- set_frequency(d_freq_offset);
- DCOUT("adjusting frequency, new frequency offset: " << d_freq_offset << "\n");
- }
- }
- break;
+ gr_complex chan_imp_resp[d_chan_imp_length*d_OSR];
+ 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: {
+ int ii;
+ int first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1;
+ int last_sample = first_sample + USEFUL_BITS * d_OSR;
+ double phase_sum = 0;
+ for (ii = first_sample; ii < last_sample; ii++) {
+ double phase_diff = compute_phase_diff(in[ii], in[ii-1]) - (M_PI / 2) / d_OSR;
+ phase_sum += phase_diff;
+ }
+ double freq_offset = compute_freq_offset(phase_sum, last_sample - first_sample);
+ if (abs(freq_offset) > FCCH_MAX_FREQ_OFFSET) {
+ d_freq_offset -= freq_offset;
+ set_frequency(d_freq_offset);
+ DCOUT("adjusting frequency, new frequency offset: " << d_freq_offset << "\n");
+ }
+ }
+ 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, &d_channel_imp_resp[0], burst_start, output_binary);
- if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) {
+ 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, &d_channel_imp_resp[0], 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);
- DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
- offset = burst_start - floor((GUARD_PERIOD) * d_OSR);
- DCOUT(offset);
- to_consume += offset;
- }
+ DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
+ offset = burst_start - floor((GUARD_PERIOD) * d_OSR);
+ DCOUT(offset);
+ to_consume += offset;
+ }
+ }
+ break;
+
+ case normal_burst:
+ burst_start = get_norm_chan_imp_resp(in, chan_imp_resp, TRAIN_SEARCH_RANGE, d_bcc);
+ detect_burst(in, &d_channel_imp_resp[0], burst_start, output_binary);
+ przetwarzaj_normalny_pakiet(d_burst_nr, output_binary);
+ break;
+
+ case rach_burst:
+ //implementation of this channel isn't possible in current gsm_receiver
+ //it would take some realtime processing, counter of samples from USRP to
+ //stay synchronized with this device and possibility to switch frequency from uplink
+ //to C0 (where sch is) back and forth
+
+ break;
+ case dummy:
+ burst_start = get_norm_chan_imp_resp(in, chan_imp_resp, TRAIN_SEARCH_RANGE, 8);
+ detect_burst(in, &d_channel_imp_resp[0], burst_start, output_binary);
+ break;
+ case empty:
+ break;
}
- break;
- case normal_burst:
- burst_start = get_norm_chan_imp_resp(in, chan_imp_resp, TRAIN_SEARCH_RANGE);
- detect_burst(in, &d_channel_imp_resp[0], burst_start, output_binary);
- printf("burst = [ ");
- for (int i = 0; i < BURST_SIZE ; i++) {
- printf(" %d", output_binary[i]);
- }
- printf("];\n");
- break;
-
- case rach_burst:
- break;
- case dummy:
- break;
- case empty:
- break;
- }
+ d_burst_nr++;
- d_burst_nr++;
- to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset();
- consume_each(to_consume);
- }
- break;
+ to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset();
+ consume_each(to_consume);
+ }
+ break;
}
return produced_out;
@@ -244,7 +294,7 @@ bool gsm_receiver_cf::find_fcch_burst(const gr_complex *in, const int nitems)
int start_pos = -1;
float min_phase_diff;
float max_phase_diff;
- double best_sum;
+ double best_sum = 0;
float lowest_max_min_diff = 99999;
int to_consume = 0;
@@ -388,7 +438,7 @@ bool gsm_receiver_cf::find_sch_burst(const gr_complex *in, const int nitems , fl
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;
+ unsigned sample_nr_near_sch_start = d_fcch_start_pos + (FRAME_BITS - SAFETY_MARGIN) * d_OSR;
enum states {
start, reach_sch, search_not_finished, sch_found
@@ -442,7 +492,7 @@ int gsm_receiver_cf::get_sch_chan_imp_resp(const gr_complex *in, gr_complex * ch
int strongest_window_nr;
int burst_start = 0;
- int chan_imp_resp_center;
+ int chan_imp_resp_center = 0;
float max_correlation = 0;
float energy = 0;
@@ -564,7 +614,6 @@ 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;
@@ -583,7 +632,7 @@ inline void gsm_receiver_cf::mafi(const gr_complex * input, int input_length, gr
}
}
-int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *in, gr_complex * chan_imp_resp, unsigned search_range)
+int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *in, gr_complex * chan_imp_resp, unsigned search_range, int bcc)
{
vector_complex correlation_buffer;
vector_float power_buffer;
@@ -591,16 +640,16 @@ int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *in, gr_complex * c
int strongest_window_nr;
int burst_start = 0;
- int chan_imp_resp_center;
+ int chan_imp_resp_center = 0;
float max_correlation = 0;
float energy = 0;
int search_center = (int)((TRAIN_POS + GUARD_PERIOD) * d_OSR);
- int search_start_pos = search_center+1;
- int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 2*d_OSR;
+ int search_start_pos = search_center + 1;
+ int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 2 * d_OSR;
for (int ii = search_start_pos; ii < search_stop_pos; ii++) {
- gr_complex correlation = correlate_sequence(&d_norm_training_seq[d_bcc][TRAIN_BEGINNING], &in[ii], N_TRAIN_BITS - 10);
+ gr_complex correlation = correlate_sequence(&d_norm_training_seq[bcc][TRAIN_BEGINNING], &in[ii], N_TRAIN_BITS - 10);
correlation_buffer.push_back(correlation);
power_buffer.push_back(pow(abs(correlation), 2));
@@ -614,27 +663,22 @@ int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *in, gr_complex * c
energy = 0;
for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++, iter_ii++) {
-// for (int ii = 0; ii < (d_chan_imp_length); ii++) {
if (iter_ii == power_buffer.end()) {
loop_end = true;
break;
}
energy += (*iter_ii);
-// iter_ii = iter_ii + d_OSR;
}
if (loop_end) {
break;
}
iter++;
-// std::cout << energy << "\n";
window_energy_buffer.push_back(energy);
}
-// std::cout << window_energy_buffer.size() << "\n";
strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin();
d_channel_imp_resp.clear();
-// strongest_window_nr = 3;
max_correlation = 0;
for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++) {
@@ -646,20 +690,22 @@ int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *in, gr_complex * c
d_channel_imp_resp.push_back(correlation);
chan_imp_resp[ii] = correlation;
}
-//WE WANT TO USE THE FIRST SAMPLE OF THE IMPULSERESPONSE, AND THE
-// CORRESPONDING SAMPLES OF THE RECEIVED SIGNAL.
-// THE VARIABLE sync_w SHOULD CONTAIN THE BEGINNING OF THE USED PART OF
-// TRAINING SEQUENCE, WHICH IS 3+57+1+6=67 BITS INTO THE BURST. THAT IS
-// WE HAVE THAT sync_T16 EQUALS FIRST SAMPLE IN BIT NUMBER 67.
+ // We want to use the first sample of the impulseresponse, and the
+ // corresponding samples of the received signal.
+ // the variable sync_w should contain the beginning of the used part of
+ // training sequence, which is 3+57+1+6=67 bits into the burst. That is
+ // we have that sync_t16 equals first sample in bit number 67.
+ burst_start = search_start_pos + chan_imp_resp_center + strongest_window_nr - TRAIN_POS * d_OSR;
- burst_start = search_start_pos + chan_imp_resp_center + strongest_window_nr - 66 * d_OSR - 2 * d_OSR + 2;
-// COMPENSATING FOR THE 2 Tb DELAY INTRODUCED IN THE GMSK MODULATOR.
-// EACH BIT IS STRECHED OVER A PERIOD OF 3 Tb WITH ITS MAXIMUM VALUE
-// IN THE LAST BIT PERIOD. HENCE, burst_start IS 2 * OSR
-//compute burst start
- std::cout << " burst_start: " << (float)burst_start/(float)d_OSR<< " center: " << ((float)(search_start_pos + strongest_window_nr + chan_imp_resp_center))/d_OSR << " stronegest window nr: " << strongest_window_nr << "\n";
+ // GMSK modulator introduces ISI - each bit is expanded for 3*Tb
+ // and it's maximum value is in the last bit period, so burst starts
+ // 2*Tb earlier
+ burst_start -= 2 * d_OSR;
+ burst_start += 2;
+ //std::cout << " burst_start: " << burst_start << " center: " << ((float)(search_start_pos + strongest_window_nr + chan_imp_resp_center)) / d_OSR << " stronegest window nr: " << strongest_window_nr << "\n";
return burst_start;
}
+
diff --git a/src/lib/gsm_receiver_cf.h b/src/lib/gsm_receiver_cf.h
index e07eb60..8e30b42 100644
--- a/src/lib/gsm_receiver_cf.h
+++ b/src/lib/gsm_receiver_cf.h
@@ -22,206 +22,12 @@
#ifndef INCLUDED_GSM_RECEIVER_CF_H
#define INCLUDED_GSM_RECEIVER_CF_H
+#include <vector>
#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;
- }
- //!!
- float get_first_sample_offset(){
- return d_first_sample_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 !!
+#include <gsm_receiver_config.h>
class gsm_receiver_cf;
@@ -245,7 +51,6 @@ gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, int osr);
class gsm_receiver_cf : public gr_block
{
-
private:
const int d_OSR;
const int d_chan_imp_length;
@@ -288,7 +93,9 @@ class gsm_receiver_cf : public gr_block
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);
+ int get_norm_chan_imp_resp(const gr_complex *in, gr_complex * chan_imp_resp, unsigned search_range, int bcc);
+ void przetwarzaj_normalny_pakiet(burst_counter burst_nr, unsigned char * pakiet);
+ void konfiguruj_odbiornik();
public:
~gsm_receiver_cf();
diff --git a/src/lib/gsm_receiver_config.cc b/src/lib/gsm_receiver_config.cc
index 1d4cf1d..1eaff7f 100644
--- a/src/lib/gsm_receiver_config.cc
+++ b/src/lib/gsm_receiver_config.cc
@@ -1,7 +1,10 @@
//
// C++ Implementation: gsm_receiver_config
//
-// Description:
+// Description:
+// This file contains classes which define gsm_receiver configuration
+// and the burst_counter which is used to store internal state of the receiver
+// when it's synchronized
//
//
// Author: Piotr Krysik <perper@o2.pl>, (C) 2009
@@ -9,3 +12,61 @@
// Copyright: See COPYING file that comes with this distribution
//
//
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gsm_receiver_config.h>
+
+burst_counter & 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;
+ }
+
+ //update offset - this is integer for d_OSR which is multiple of four
+ d_offset_fractional += GUARD_FRACTIONAL * d_OSR;
+ d_offset_integer = floor(d_offset_fractional);
+ d_offset_fractional = d_offset_fractional - d_offset_integer;
+ return (*this);
+}
+
+void burst_counter::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_offset_fractional = first_sample_position - floor(first_sample_position);
+ d_offset_integer = 0;
+}
+
+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);
+}
diff --git a/src/lib/gsm_receiver_config.h b/src/lib/gsm_receiver_config.h
index 1d4cf1d..9222602 100644
--- a/src/lib/gsm_receiver_config.h
+++ b/src/lib/gsm_receiver_config.h
@@ -1,11 +1,150 @@
//
// C++ Implementation: gsm_receiver_config
//
-// Description:
-//
+// Description:
+// This file contains classes which define gsm_receiver configuration
+// and the burst_counter which is used to store internal state of the receiver
+// when it's synchronized
//
// Author: Piotr Krysik <perper@o2.pl>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
+#ifndef INCLUDED_GSM_RECEIVER_CONFIG_H
+#define INCLUDED_GSM_RECEIVER_CONFIG_H
+
+#include <vector>
+#include <algorithm>
+#include <math.h>
+#include <stdint.h>
+#include <gsm_constants.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() {}
+
+ 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_offset_fractional;
+ double d_offset_integer;
+ public:
+ burst_counter(int osr):
+ d_OSR(osr),
+ d_t1(0),
+ d_t2(0),
+ d_t3(0),
+ d_timeslot_nr(0),
+ d_offset_fractional(0.0),
+ d_offset_integer(0.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_fractional(0.0),
+ d_offset_integer(0.0) {
+ double first_sample_position = (get_frame_nr() * 8 + timeslot_nr) * TS_BITS;
+ d_offset_integer = floor(first_sample_position);
+ d_offset_fractional = first_sample_position - floor(first_sample_position);
+ }
+
+ burst_counter & operator++(int);
+ void set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr);
+
+ 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_integer;
+ }
+};
+
+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_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);
+};
+
+#endif /* INCLUDED_GSM_RECEIVER_CONFIG_H */
diff --git a/src/lib/viterbi_detector.h b/src/lib/viterbi_detector.h
index 9ecb2a0..03f483f 100644
--- a/src/lib/viterbi_detector.h
+++ b/src/lib/viterbi_detector.h
@@ -53,4 +53,9 @@
** TEST(S): Tested with real world normal burst.
*/
+#ifndef INCLUDED_VITERBI_DETECTOR_H
+#define INCLUDED_VITERBI_DETECTOR_H
+
void viterbi_detector(const gr_complex * input, unsigned int samples_num, gr_complex * rhh, unsigned int start_state, const unsigned int * stop_states, unsigned int stops_num, float * output);
+
+#endif /* INCLUDED_VITERBI_DETECTOR_H */
personal git repositories of Harald Welte. Your mileage may vary