summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]gsm-tvoid/src/lib/Makefile.am24
-rwxr-xr-xgsm-tvoid/src/lib/gsm.i16
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst.cc63
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst.h26
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst_cf.cc70
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst_cf.h21
-rwxr-xr-x[-rw-r--r--]gsm-tvoid/src/lib/gsm_burst_ff_single.cc0
-rwxr-xr-x[-rw-r--r--]gsm-tvoid/src/lib/gsm_burst_ff_single.h0
-rwxr-xr-x[-rw-r--r--]gsm-tvoid/src/lib/gsm_burst_sink_c.cc0
-rwxr-xr-x[-rw-r--r--]gsm-tvoid/src/lib/gsm_burst_sink_c.h0
-rw-r--r--[-rwxr-xr-x]gsm-tvoid/src/lib/gsm_constants.h2
-rw-r--r--gsm-tvoid/src/lib/mm_c.cc73
-rw-r--r--gsm-tvoid/src/lib/mm_c.h48
-rw-r--r--gsm-tvoid/src/lib/mm_f.cc55
-rw-r--r--gsm-tvoid/src/lib/mm_f.h34
-rwxr-xr-xgsm-tvoid/src/python/gsm_scan.py80
16 files changed, 407 insertions, 105 deletions
diff --git a/gsm-tvoid/src/lib/Makefile.am b/gsm-tvoid/src/lib/Makefile.am
index e8f093f..fa876b2 100755..100644
--- a/gsm-tvoid/src/lib/Makefile.am
+++ b/gsm-tvoid/src/lib/Makefile.am
@@ -37,17 +37,19 @@ ourpython_PYTHON = \
ourlib_LTLIBRARIES = _gsm.la
# These are the source files that go into the shared library
-_gsm_la_SOURCES = \
+_gsm_la_SOURCES = \
fire_crc.c \
gsmstack.c \
- interleave.c \
+ interleave.c \
conv.c \
sch.c \
cch.c \
gsm.cc \
- gsm_burst.cc \
- gsm_burst_ff.cc \
- gsm_burst_cf.cc \
+ gsm_burst.cc \
+ gsm_burst_ff.cc \
+ mm_c.cc \
+ mm_f.cc \
+ gsm_burst_cf.cc \
gsm_burst_sink_c.cc
@@ -64,18 +66,20 @@ gsm.cc gsm.py: $(LOCAL_IFILES) $(ALL_IFILES)
$(SWIG) $(SWIGPYTHONARGS) -module gsm -o gsm.cc $(LOCAL_IFILES)
# These headers get installed in ${prefix}/include/gnuradio
-grinclude_HEADERS = \
+grinclude_HEADERS = \
fire_crc.h \
gsm_burst.h \
gsmstack.h \
- interleave.h \
+ interleave.h \
conv.h \
sch.h \
cch.h \
system.h \
- gsm_burst_ff.h \
- gsm_burst_cf.h \
- gsm_burst_sink_c.h \
+ gsm_burst_ff.h \
+ mm_c.h \
+ mm_f.h \
+ gsm_burst_cf.h \
+ gsm_burst_sink_c.h \
gsm_constants.h
diff --git a/gsm-tvoid/src/lib/gsm.i b/gsm-tvoid/src/lib/gsm.i
index 106e378..af644d9 100755
--- a/gsm-tvoid/src/lib/gsm.i
+++ b/gsm-tvoid/src/lib/gsm.i
@@ -16,6 +16,9 @@
// ----------------------------------------------------------------
+#define OPT_TEST_HOP_SPEED 0x00000001
+
+
#define PRINT_NOTHING 0x00000000
#define PRINT_EVERYTHING 0x7FFFFFFF //7 for SWIG overflow check work around
#define PRINT_BITS 0x00000001
@@ -32,7 +35,7 @@
#define PRINT_DUMMY 0x00000100
#define PRINT_NORMAL 0x00000200
-#define PRINT_GSM_DECODE 0x00000400
+#define PRINT_GSM_DECODE 0x00004000
#define PRINT_HEX 0x00001000
@@ -66,6 +69,8 @@ public:
unsigned long d_clock_options;
unsigned long d_print_options;
+ unsigned long d_test_options;
+
EQ_TYPE d_equalizer_type;
//stats
@@ -80,9 +85,13 @@ public:
long next_arfcn;
+ //hop testing
+ long d_hop_good_arfcn;
+ long d_hop_bad_arfcn;
+
int sync_state();
float last_freq_offset(void);
- double mean_freq_offset(void);
+ float mean_freq_offset(void);
//Methods
void full_reset(void);
@@ -104,6 +113,9 @@ GR_SWIG_BLOCK_MAGIC(gsm,burst_cf);
gsm_burst_cf_sptr gsm_make_burst_cf (gr_feval_ll *,float);
class gsm_burst_cf : public gr_block, public gsm_burst {
+public:
+ float get_omega();
+
private:
gsm_burst_cf (gr_feval_ll *,float);
};
diff --git a/gsm-tvoid/src/lib/gsm_burst.cc b/gsm-tvoid/src/lib/gsm_burst.cc
index c7f0acc..c52ff38 100755
--- a/gsm-tvoid/src/lib/gsm_burst.cc
+++ b/gsm-tvoid/src/lib/gsm_burst.cc
@@ -17,6 +17,9 @@ gsm_burst::gsm_burst (gr_feval_ll *t) :
p_tuner(t),
d_clock_options(DEFAULT_CLK_OPTS),
d_print_options(0),
+ d_test_options(0),
+ d_hop_good_arfcn(1),
+ d_hop_bad_arfcn(2),
d_equalizer_type(EQ_FIXED_DFE)
{
@@ -33,15 +36,17 @@ gsm_burst::gsm_burst (gr_feval_ll *t) :
tsync[i] = 2.0*SYNC_BITS[i] - 1.0;
}
+ diff_encode(tsync,corr_sync,N_SYNC_BITS);
+
+/*
fprintf(stderr," Sync: ");
print_bits(tsync,N_SYNC_BITS);
fprintf(stderr,"\n");
- diff_encode(tsync,corr_sync,N_SYNC_BITS);
fprintf(stderr,"DSync: ");
print_bits(corr_sync,N_SYNC_BITS);
fprintf(stderr,"\n\n");
-
+*/
for (int i=0; i < 10; i++) {
for (int j=0; j < N_TRAIN_BITS; j++) {
@@ -49,9 +54,11 @@ gsm_burst::gsm_burst (gr_feval_ll *t) :
}
diff_encode(tsync,corr_train_seq[i],N_TRAIN_BITS);
+/*
fprintf(stderr,"TSC%d: ",i);
print_bits(corr_train_seq[i],N_TRAIN_BITS);
fprintf(stderr,"\n");
+*/
}
/* Initialize GSM Stack */
@@ -103,7 +110,7 @@ void gsm_burst::full_reset(void)
}
-double gsm_burst::mean_freq_offset(void)
+float gsm_burst::mean_freq_offset(void)
{
if (d_freq_off_weight)
return d_freq_off_sum / d_freq_off_weight;
@@ -650,7 +657,6 @@ int gsm_burst::get_burst(void)
d_ts = 0; //TODO: check this
break;
case SCH:
-#ifndef TEST_TUNE_TIMING
//TODO: it would be better to adjust tuning on first FCCH (for better SCH detection),
// but tuning can run away with false FCCHs
// Some logic to retune back to original offset on false FCCH might work
@@ -661,7 +667,6 @@ int gsm_burst::get_burst(void)
p_tuner->calleval(BURST_CB_SYNC_OFFSET);
}
-#endif
d_burst_count++;
d_sch_count++;
d_last_sch = d_burst_count;
@@ -704,35 +709,39 @@ int gsm_burst::get_burst(void)
/////////////////////
//start tune testing
-#ifdef TEST_TUNE_TIMING
-
+#ifdef TEST_HOP_SPEED
static int good_count = -1; //-1: wait sch, >=0: got sch, counting
static int wait_count = 0;
+
+ if (OPT_TEST_HOP_SPEED & d_test_options ) {
+ //have we started counting?
+ if ( good_count >= 0 ) {
+
+ if (UNKNOWN == d_burst_type) {
+ if (good_count >= 0) {
+ fprintf(stdout,"good_count: %d\n",good_count);
- if (UNKNOWN == d_burst_type) {
- if (good_count >= 0) {
- fprintf(stdout,"good_count: %d\n",good_count);
-
- if (p_tuner) {
- next_arfcn = TEST_TUNE_GOOD_ARFCN;
- p_tuner->calleval(BURST_CB_TUNE);
+ if (p_tuner) {
+ next_arfcn = d_hop_good_arfcn;
+ p_tuner->calleval(BURST_CB_TUNE);
+ }
+ }
+ good_count = -1; // start again at resync
+
+ } else {
+ //count good bursts
+ good_count++;
}
- }
- good_count = -1; // start again at resync
-
- } else {
-
- if (good_count >= 0 ) {
- good_count++;
- }
-
- if (SCH == d_burst_type) {
- if ((good_count < 0) && (++wait_count > 20)) { // get some good syncs before trying again
- fprintf(stdout,"restarting good_count\n");
+
+ } else {
+ //haven't started counting
+ // get some good syncs before trying again
+ if ((SCH == d_burst_type) && (++wait_count > 5)) {
+ //fprintf(stdout,"restarting good_count\n");
good_count = wait_count = 0;
//tune away
if (p_tuner) {
- next_arfcn = TEST_TUNE_EMPTY_ARFCN;
+ next_arfcn = d_hop_bad_arfcn;
p_tuner->calleval(BURST_CB_TUNE);
}
}
diff --git a/gsm-tvoid/src/lib/gsm_burst.h b/gsm-tvoid/src/lib/gsm_burst.h
index 48fafac..056516c 100755
--- a/gsm-tvoid/src/lib/gsm_burst.h
+++ b/gsm-tvoid/src/lib/gsm_burst.h
@@ -13,10 +13,10 @@
//Testing Modes
//Tune test measures hopping latency by hopping between good and empty ARFCNs
-#undef TEST_TUNE_TIMING
-#define TEST_TUNE_GOOD_ARFCN 658
-#define TEST_TUNE_EMPTY_ARFCN 655
+#define TEST_HOP_SPEED
+//Test Options
+#define OPT_TEST_HOP_SPEED 0x00000001
//Console printing options
#define PRINT_NOTHING 0x00000000
@@ -35,7 +35,7 @@
#define PRINT_DUMMY 0x00000100
#define PRINT_NORMAL 0x00000200
-#define PRINT_GSM_DECODE 0x00000400
+#define PRINT_GSM_DECODE 0x00004000
#define PRINT_HEX 0x00001000
@@ -59,7 +59,8 @@
// G T D1 TS D2 T G
// Start ^
-#define MAX_SYNC_WAIT 32 //Number of missed bursts before reverting to WAIT_FCCH.
+//#define MAX_SYNC_WAIT 32 //Number of missed bursts before reverting to WAIT_FCCH.
+#define MAX_SYNC_WAIT 64 //Number of missed bursts before reverting to WAIT_FCCH.
#define MAX_CORR_DIST 7 // 4 + 3 = 1/2 GUARD + TAIL
#define SCH_CORR_THRESHOLD 0.80
@@ -75,6 +76,7 @@ enum EQ_TYPE {
EQ_ADAPTIVE_LINEAR,
EQ_FIXED_DFE,
EQ_ADAPTIVE_DFE,
+ EQ_ADAPT_TRAINING,
EQ_VITERBI
};
@@ -123,8 +125,8 @@ protected:
int d_color_code;
float d_freq_offset;
- double d_freq_off_sum;
- double d_freq_off_weight;
+ float d_freq_off_sum;
+ float d_freq_off_weight;
gr_feval_ll *p_tuner;
@@ -166,11 +168,15 @@ public:
long d_total_count;
////// Options
+ unsigned long d_test_options;
unsigned long d_clock_options;
unsigned long d_print_options;
EQ_TYPE d_equalizer_type;
-
-
+
+ //Hop speed info
+ long d_hop_good_arfcn;
+ long d_hop_bad_arfcn;
+
//Methods
void full_reset(void);
@@ -178,7 +184,7 @@ public:
//Frequency
float last_freq_offset() {return d_freq_offset;}
- double mean_freq_offset(void);
+ float mean_freq_offset(void);
long next_arfcn;
};
diff --git a/gsm-tvoid/src/lib/gsm_burst_cf.cc b/gsm-tvoid/src/lib/gsm_burst_cf.cc
index a584cd6..caddb5f 100755
--- a/gsm-tvoid/src/lib/gsm_burst_cf.cc
+++ b/gsm-tvoid/src/lib/gsm_burst_cf.cc
@@ -20,24 +20,30 @@ static const int MIN_OUT = 0; // minimum number of output streams
static const int MAX_OUT = 1; // maximum number of output streams
gsm_burst_cf::gsm_burst_cf (gr_feval_ll *t, float sample_rate) :
- gsm_burst(t),
- gr_block ( "burst_cf",
+ gr_block( "burst_cf",
gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)),
- gr_make_io_signature (MIN_OUT, MAX_OUT, USEFUL_BITS * sizeof (float))),
+ gr_make_io_signature (MIN_OUT, MAX_OUT, USEFUL_BITS * sizeof (float)) //TODO: pad to ^2 = 256 ?
+ ),
+ gsm_burst(t),
d_clock_counter(0.0),
- d_mu(0.5),
d_last_sample(0.0,0.0),
- d_interp(new gri_mmse_fir_interpolator_cc())
+ mm(sample_rate / GSM_SYMBOL_RATE),
+ d_interp(new gri_mmse_fir_interpolator_cc()
+ )
{
//clocking parameters
- d_sample_interval = 1.0 / sample_rate;
- d_relative_sample_rate = sample_rate / GSM_SYMBOL_RATE;
+ //d_sample_interval = 1.0 / sample_rate;
+ //d_omega = sample_rate / GSM_SYMBOL_RATE;
- fprintf(stderr,"Sample interval : %e\n",d_sample_interval);
- fprintf(stderr,"Relative sample rate : %g\n",d_relative_sample_rate);
-
+// fprintf(stderr,"Sample interval : %e\n",d_sample_interval);
+// fprintf(stderr,"Relative sample rate : %g\n",d_omega);
+
+
+ //set_relative_rate( mm.d_omega / 156);
+ set_relative_rate( 1.0 / (mm.d_omega * 156) );
+
set_history(4); //need history for interpolator
}
@@ -49,12 +55,13 @@ gsm_burst_cf::~gsm_burst_cf ()
void gsm_burst_cf::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
- unsigned ninputs = ninput_items_required.size ();
- for (unsigned i = 0; i < ninputs; i++)
- ninput_items_required[i] = noutput_items * (int)ceil(d_relative_sample_rate) * BBUF_SIZE + history();
+ unsigned ninputs = ninput_items_required.size ();
+ for (unsigned i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = noutput_items * (int)ceil(mm.d_omega) * TS_BITS;
+ //fprintf(stderr,"forecast[%d]: %d = %d\n",i,noutput_items,ninput_items_required[i]);
+ }
}
-
int gsm_burst_cf::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
@@ -65,27 +72,30 @@ int gsm_burst_cf::general_work (int noutput_items,
int ii=0;
int rval = 0; //default to no output
- int do_output = output_items.size() > 0 ? 1 : 0;
+ int num_outputs = output_items.size();
+ int do_output = num_outputs > 0 ? 1 : 0;
int ninput = ninput_items[0];
- //fprintf(stderr,"#i=%d/#o=%d",n_input,noutput_items);
+ //fprintf(stderr,"#i=%d/#o=%d",ninput,noutput_items);
int ni = ninput - d_interp->ntaps() - 16; // interpolator need -4/+3 samples NTAPS = 8 , - 16 for safety margin
while (( rval < noutput_items) && ( ii < ni ) ) {
//clock symbols
//TODO: this is very basic and can be improved. Need tracking...
- //TODO: use burst_start offsets as timing feedback
//TODO: save complex samples for Viterbi EQ
- //from m&m
- gr_complex sample = d_interp->interpolate (&in[ii], d_mu); //FIXME: this seems noisy, make sure it is being used correctly
+ //get interpolated sample
+ gr_complex x_0 = d_interp->interpolate (&in[ii], mm.d_mu);
- gr_complex conjprod = sample * conj(d_last_sample);
+ //calulate phase difference (demod)
+ gr_complex conjprod = x_0 * conj(d_last_sample);
float diff_angle = gr_fast_atan2f(imag(conjprod), real(conjprod));
- d_last_sample = sample;
-
+ //mM&M
+ //mm.update(x_0); //mm_c
+ mm.update(diff_angle); //mm_f
+
assert(d_bbuf_pos <= BBUF_SIZE );
if (d_bbuf_pos >= 0) //could be negative offset from burst alignment. TODO: perhaps better just to add some padding to the buffer
@@ -111,12 +121,12 @@ int gsm_burst_cf::general_work (int noutput_items,
switch ( d_clock_options & QB_MASK ) {
case QB_QUARTER: //extra 1/4 bit each burst
- d_mu -= d_relative_sample_rate / 4.0;
+ mm.d_mu -= mm.d_omega / 4.0;
//d_clock_counter -= GSM_SYMBOL_PERIOD / 4.0;
break;
case QB_FULL04: //extra bit on timeslot 0 & 4
if (!(d_ts%4))
- d_mu -= d_relative_sample_rate;
+ mm.d_mu -= mm.d_omega;
//d_clock_counter -= GSM_SYMBOL_PERIOD;
break;
case QB_NONE: //don't adjust for quarter bits at all
@@ -130,12 +140,12 @@ int gsm_burst_cf::general_work (int noutput_items,
}
}
- //TODO: timing adjust
- //d_mu = d_mu + d_omega + d_gain_mu * mm_val;
- d_mu += d_relative_sample_rate;
- ii += (int)floor(d_mu);
- d_sample_count += (int)floor(d_mu);
- d_mu -= floor(d_mu);
+ //process mu / ii advance
+ ii += (int)floor(mm.d_mu);
+ d_sample_count += (int)floor(mm.d_mu);
+ mm.d_mu -= floor(mm.d_mu);
+
+ d_last_sample = x_0;
}
//fprintf(stderr,"/ii=%d/rval=%d\n",ii,rval);
diff --git a/gsm-tvoid/src/lib/gsm_burst_cf.h b/gsm-tvoid/src/lib/gsm_burst_cf.h
index 40ccc83..fe3663c 100755
--- a/gsm-tvoid/src/lib/gsm_burst_cf.h
+++ b/gsm-tvoid/src/lib/gsm_burst_cf.h
@@ -2,7 +2,8 @@
#define INCLUDED_GSM_BURST_CF_H
#include <gr_block.h>
-#include <gsm_burst.h>
+#include "gsm_burst.h"
+#include "mm_f.h"
class gsm_burst_cf;
@@ -20,15 +21,18 @@ private:
gsm_burst_cf(gr_feval_ll *,float);
//clocking parameters
- double d_sample_interval;
- double d_clock_counter;
+ float d_sample_interval;
+ float d_clock_counter; //??? sample count ???
+
gr_complex d_last_sample;
- float d_relative_sample_rate; //omega
- float d_mu;
-
- gri_mmse_fir_interpolator_cc *d_interp; //sub-sample interpolator from GR
+ //M&M clock recovery
+ mm_f mm;
+ gri_mmse_fir_interpolator_cc *d_interp; //sub-sample interpolator from GR
+
+ gr_complex slicer(gr_complex x);
+
public:
~gsm_burst_cf ();
@@ -38,6 +42,9 @@ public:
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
+
+ float get_omega() {return mm.d_omega;}
+
};
#endif /* INCLUDED_GSM_BURST_CF_H */
diff --git a/gsm-tvoid/src/lib/gsm_burst_ff_single.cc b/gsm-tvoid/src/lib/gsm_burst_ff_single.cc
index ff6c354..ff6c354 100644..100755
--- a/gsm-tvoid/src/lib/gsm_burst_ff_single.cc
+++ b/gsm-tvoid/src/lib/gsm_burst_ff_single.cc
diff --git a/gsm-tvoid/src/lib/gsm_burst_ff_single.h b/gsm-tvoid/src/lib/gsm_burst_ff_single.h
index 553fe65..553fe65 100644..100755
--- a/gsm-tvoid/src/lib/gsm_burst_ff_single.h
+++ b/gsm-tvoid/src/lib/gsm_burst_ff_single.h
diff --git a/gsm-tvoid/src/lib/gsm_burst_sink_c.cc b/gsm-tvoid/src/lib/gsm_burst_sink_c.cc
index 58787bb..58787bb 100644..100755
--- a/gsm-tvoid/src/lib/gsm_burst_sink_c.cc
+++ b/gsm-tvoid/src/lib/gsm_burst_sink_c.cc
diff --git a/gsm-tvoid/src/lib/gsm_burst_sink_c.h b/gsm-tvoid/src/lib/gsm_burst_sink_c.h
index 1197a2c..1197a2c 100644..100755
--- a/gsm-tvoid/src/lib/gsm_burst_sink_c.h
+++ b/gsm-tvoid/src/lib/gsm_burst_sink_c.h
diff --git a/gsm-tvoid/src/lib/gsm_constants.h b/gsm-tvoid/src/lib/gsm_constants.h
index c404b57..942736d 100755..100644
--- a/gsm-tvoid/src/lib/gsm_constants.h
+++ b/gsm-tvoid/src/lib/gsm_constants.h
@@ -13,7 +13,7 @@
#define USEFUL_BITS 142 //(2*DATA_BITS + N_TRAIN_BITS )
#define FCCH_BITS USEFUL_BITS
-#define TS_BITS (TAIL_BITS+USEFUL_BITS+TAIL_BITS+GUARD_BITS) //a full TS
+#define TS_BITS (TAIL_BITS+USEFUL_BITS+TAIL_BITS+GUARD_BITS) //a full TS (156)
#define TS_PER_FRAME 8
#define FRAME_BITS (TS_PER_FRAME * TS_BITS + 2) // +2 for extra 8*0.25 guard bits
#define FCCH_POS TAIL_BITS
diff --git a/gsm-tvoid/src/lib/mm_c.cc b/gsm-tvoid/src/lib/mm_c.cc
new file mode 100644
index 0000000..7b3e335
--- /dev/null
+++ b/gsm-tvoid/src/lib/mm_c.cc
@@ -0,0 +1,73 @@
+
+#include "mm_c.h"
+
+mm_c::mm_c(float omega):
+ d_omega(omega),
+ d_mu(0.5),
+ d_x_1(0.0,0.0),
+ d_x_2(0.0,0.0),
+ d_a_1(0.0,0.0),
+ d_a_2(0.0,0.0),
+ d_gain_mu(0.01),
+ d_gain_omega(0.25 * d_gain_mu * d_gain_mu)
+{}
+
+
+gr_complex mm_c::slicer(gr_complex x)
+{
+ float real=SLICE_0_R, imag=SLICE_0_I;
+
+ if(x.real() > 0.0)
+ real = SLICE_1_R;
+
+ if(x.imag() > 0.0)
+ imag = SLICE_1_I;
+
+ return gr_complex(real,imag);
+}
+
+float mm_c::update(gr_complex x_0, gr_complex a_0)
+{
+ //mm vars
+ gr_complex x,y,u;
+
+ x = (a_0 - d_a_2) * conj(d_x_1);
+ y = (x_0 - d_x_2) * conj(d_a_1);
+ u = y - x;
+ d_mm = u.real(); //error signal
+
+ //limit d_mm
+ if (d_mm > 1.0) d_mm = 1.0;
+ else if (d_mm < -1.0) d_mm = -1.0;
+
+ //error feedback
+ d_omega = d_omega + d_gain_omega * d_mm;
+
+ //limit omega
+/*
+ if (d_omega > d_max_omega)
+ d_omega = d_max_omega;
+ else if (d_omega < d_min_omega)
+ d_omega = d_min_omega;
+*/
+ //update mu
+ d_mu = d_mu + d_omega + d_gain_mu * d_mm;
+ //process mu / ii advances after burst processing for burst timing
+
+ //update delay taps
+ d_x_2 = d_x_1;
+ d_x_1 = x_0;
+ d_a_2 = d_a_1;
+ d_a_1 = a_0;
+
+ return d_mu;
+}
+
+
+float mm_c::update(gr_complex x_0)
+{
+ return update(x_0, slicer(x_0) );
+}
+
+
+
diff --git a/gsm-tvoid/src/lib/mm_c.h b/gsm-tvoid/src/lib/mm_c.h
new file mode 100644
index 0000000..e9881dd
--- /dev/null
+++ b/gsm-tvoid/src/lib/mm_c.h
@@ -0,0 +1,48 @@
+#ifndef INCLUDED_MM_C_H
+#define INCLUDED_MM_C_H
+
+#include <gr_math.h>
+
+#if 0
+#define SLICE_0_R 0.0
+#define SLICE_0_I 0.0
+#define SLICE_1_R 1.0
+#define SLICE_1_I 1.0
+#else
+#define SLICE_0_R -1.0
+#define SLICE_0_I -1.0
+#define SLICE_1_R 1.0
+#define SLICE_1_I 1.0
+#endif
+
+class mm_c {
+private:
+public:
+
+ float d_mm;
+
+ float d_omega; //relative sample rate
+ float d_mu;
+
+ float d_gain_mu;
+ float d_gain_omega;
+
+ //delay taps
+ gr_complex d_x_1; //last input sample
+ gr_complex d_x_2;
+ gr_complex d_a_1; //last decision
+ gr_complex d_a_2;
+
+ mm_c (float omega);
+
+ gr_complex slicer(gr_complex x);
+
+ float update(gr_complex sample, gr_complex decision); //return mu
+
+ float update(gr_complex sample); //use built in decision
+
+};
+
+
+
+#endif
diff --git a/gsm-tvoid/src/lib/mm_f.cc b/gsm-tvoid/src/lib/mm_f.cc
new file mode 100644
index 0000000..4637149
--- /dev/null
+++ b/gsm-tvoid/src/lib/mm_f.cc
@@ -0,0 +1,55 @@
+
+#include "mm_f.h"
+
+mm_f::mm_f(float omega):
+ d_omega(omega),
+ d_mu(0.5),
+ d_x_1(0.0),
+ d_a_1(0.0),
+ d_gain_mu(0.01),
+ d_gain_omega(0.25 * d_gain_mu * d_gain_mu)
+{}
+
+
+float mm_f::slicer(float x)
+{
+ return x < 0 ? -1.0 : 1.0;
+}
+
+float mm_f::update(float x_0, float a_0)
+{
+ d_mm = (d_a_1 * x_0) - (a_0 * d_x_1);
+
+ //limit d_mm
+ if (d_mm > 1.0) d_mm = 1.0;
+ else if (d_mm < -1.0) d_mm = -1.0;
+
+ //error feedback
+ d_omega = d_omega + d_gain_omega * d_mm;
+
+ //limit omega
+/*
+ if (d_omega > d_max_omega)
+ d_omega = d_max_omega;
+ else if (d_omega < d_min_omega)
+ d_omega = d_min_omega;
+*/
+ //update mu
+ d_mu = d_mu + d_omega + d_gain_mu * d_mm;
+ //process mu / ii advances after burst processing for burst timing
+
+ //update delay taps
+ d_x_1 = x_0;
+ d_a_1 = a_0;
+
+ return d_mu;
+}
+
+
+float mm_f::update(float x_0)
+{
+ return update(x_0, slicer(x_0) );
+}
+
+
+
diff --git a/gsm-tvoid/src/lib/mm_f.h b/gsm-tvoid/src/lib/mm_f.h
new file mode 100644
index 0000000..8b359be
--- /dev/null
+++ b/gsm-tvoid/src/lib/mm_f.h
@@ -0,0 +1,34 @@
+#ifndef INCLUDED_MM_F_H
+#define INCLUDED_MM_F_H
+
+#include <gr_math.h>
+
+class mm_f {
+private:
+public:
+
+ float d_mm;
+
+ float d_omega; //relative sample rate
+ float d_mu;
+
+ float d_gain_mu;
+ float d_gain_omega;
+
+ //delay taps
+ float d_x_1; //last input sample
+ float d_a_1; //last decision
+
+ mm_f (float omega);
+
+ float slicer(float x);
+
+ float update(float sample, float decision); //return mu
+
+ float update(float sample); //use built in decision
+
+};
+
+
+
+#endif
diff --git a/gsm-tvoid/src/python/gsm_scan.py b/gsm-tvoid/src/python/gsm_scan.py
index 5e3edfc..fab6ce8 100755
--- a/gsm-tvoid/src/python/gsm_scan.py
+++ b/gsm-tvoid/src/python/gsm_scan.py
@@ -39,7 +39,6 @@ class burst_callback(gr.feval_ll):
def eval(self, x):
#print "burst_callback: eval(",x,")\n";
try:
- #TODO: rework so this will work on file input
if gsm.BURST_CB_SYNC_OFFSET == x:
#print "burst_callback: SYNC_OFFSET\n";
if self.fg.options.tuning.count("o"):
@@ -72,7 +71,7 @@ class burst_callback(gr.feval_ll):
self.fg.offset -= self.fg.mean_offset
self.fg.set_channel(self.fg.channel)
- elif gsm.BURST_CB_TUNE == x and self.fg.options.tuning.count("h"):
+ elif gsm.BURST_CB_TUNE == x:
#print "burst_callback: BURST_CB_TUNE: ARFCN: ", self.fg.burst.next_arfcn, "\n";
if self.fg.options.tuning.count("h"):
#print "burst_callback: tuning.\n";
@@ -173,10 +172,10 @@ class app_flow_graph(stdgui.gui_flow_graph):
#decoder options
- parser.add_option("-D", "--decoder", type="string", default="f",
+ parser.add_option("-D", "--decoder", type="string", default="c",
help="Select decoder block to use. (c)omplex,(f)loat [default=%default]")
parser.add_option("-E", "--equalizer", type="string", default="none",
- help="Type of equalizer to use. none, fixed-dfe [default=%default]")
+ help="Type of equalizer to use. none, fixed-dfe, fixed-linear [default=%default]")
parser.add_option("-t", "--timing", type="string", default="cn",
help="Type of timing techniques to use. [default=%default] \n" +
"(n)one, (c)orrelation track, (q)uarter bit, (f)ull04 ")
@@ -214,13 +213,20 @@ class app_flow_graph(stdgui.gui_flow_graph):
parser.add_option("-g", "--gain", type="eng_float", default=None,
help="Set gain in dB (default is midpoint)")
parser.add_option("-c", "--channel", type="int", default=1,
- help="Tune to GSM ARFCN. Overrides --freq")
+ help="Tune to GSM ARFCN.")
parser.add_option("-r", "--region", type="string", default="u",
help="Frequency bands to use for channels. (u)s or (e)urope [default=%default]")
+ #testing options
+ parser.add_option("--test-hop-speed",action="store_true", dest="test_hop_speed",
+ help="Test hopping speed.")
+ parser.add_option("--hopgood", type="int", default=658,
+ help="Good ARFCN [default=%default]")
+ parser.add_option("--hopbad", type="int", default=655,
+ help="Emtpy ARFCN [default=%default]")
(options, args) = parser.parse_args()
- if (len(args) != 0) or (not (options.channel or options.inputfile)):
+ if (len(args) != 0):
parser.print_help()
sys.exit(1)
@@ -228,6 +234,9 @@ class app_flow_graph(stdgui.gui_flow_graph):
# print "datafile option cannot be used with USRP options."
# sys.exit(1)
+ if options.test_hop_speed:
+ options.tuning = 'h' #hopping only, no offset
+ options.channel = options.hopgood
self.options = options
self.scopes = options.scopes
@@ -280,9 +289,6 @@ class app_flow_graph(stdgui.gui_flow_graph):
if options.print_console.count('D'):
popts |= gsm.PRINT_DUMMY
- if options.print_console.count('C'):
- popts |= gsm.PRINT_BITS | gsm.PRINT_CORR_BITS
-
if options.print_console.count('x'):
popts |= gsm.PRINT_BITS | gsm.PRINT_HEX
@@ -292,7 +298,10 @@ class app_flow_graph(stdgui.gui_flow_graph):
elif options.print_console.count('b'):
popts |= gsm.PRINT_BITS
- print "Print flags: 0x%8.8x\n" %(popts)
+ elif options.print_console.count('C'):
+ popts |= gsm.PRINT_BITS | gsm.PRINT_CORR_BITS
+
+ #print "Print flags: 0x%8.8x\n" %(popts)
self.burst.d_print_options = popts
@@ -357,12 +366,16 @@ class app_flow_graph(stdgui.gui_flow_graph):
print >> sys.stderr, "% offset = ", percent_offset, "clock = ", clock_rate
self.clock_rate = clock_rate
- self.input_rate = clock_rate / options.decim
+ self.input_rate = clock_rate / options.decim #TODO: what about usrp value?
self.gsm_symb_rate = 1625000.0 / 6.0
self.sps = self.input_rate / self.gsm_symb_rate
####################
def setup_filter(self):
+ #test w/o filter (for buffer latency)
+ #self.filter = self.source
+ #return
+
options = self.options
# configure channel filter
@@ -394,7 +407,7 @@ class app_flow_graph(stdgui.gui_flow_graph):
gain_omega,
0.5, #mu
gain_mu,
- 0.3) #omega_relative_limit,
+ 0.5) #omega_relative_limit,
self.burst = gsm.burst_ff(self.burst_cb)
self.connect(self.filter, self.demod, self.clocker, self.burst)
@@ -402,10 +415,12 @@ class app_flow_graph(stdgui.gui_flow_graph):
####################
def setup_c_flowgraph(self):
#use the sink version if burst scope not selected
- if self.scopes.count("b"):
- self.burst = gsm.burst_cf(self.burst_cb,input_rate)
- else:
- self.burst = gsm.burst_sink_c(self.burst_cb,input_rate)
+# if self.scopes.count("b"):
+# self.burst = gsm.burst_cf(self.burst_cb,self.input_rate)
+# else:
+# self.burst = gsm.burst_sink_c(self.burst_cb,self.input_rate)
+
+ self.burst = gsm.burst_cf(self.burst_cb,self.input_rate)
self.connect(self.filter, self.burst)
@@ -418,7 +433,7 @@ class app_flow_graph(stdgui.gui_flow_graph):
#Filter FFT
if self.scopes.count("F"):
- self.filter_fft_scope = fftsink.fft_sink_c (self, self.panel, fft_size=1024, sample_rate=input_rate)
+ self.filter_fft_scope = fftsink.fft_sink_c (self, self.panel, fft_size=1024, sample_rate=self.input_rate)
self.connect(self.filter, self.filter_fft_scope)
#Burst Scope
@@ -433,15 +448,20 @@ class app_flow_graph(stdgui.gui_flow_graph):
self.connect(self.demod, self.demod_scope)
if self.scopes.count("c"):
+ #f_flowgraph
self.clocked_scope = scopesink.scope_sink_f(self, self.panel, sample_rate=self.gsm_symb_rate,v_scale=1)
self.connect(self.clocker, self.clocked_scope)
+ #for testing: f_flowgraph2
+ #self.clocked_scope = scopesink.scope_sink_c(self, self.panel, sample_rate=self.gsm_symb_rate,v_scale=1)
+ #self.connect(self.clocker, self.clocked_scope)
+ #self.connect((self.clocker,1),(self.clocked_scope,1))
####################
def configure_burst_decoder(self):
options = self.options
# equalizer
- eq_types = {'none': gsm.EQ_NONE, 'fixed-dfe': gsm.EQ_FIXED_DFE}
+ eq_types = {'none': gsm.EQ_NONE, 'fixed-dfe': gsm.EQ_FIXED_DFE, 'fixed-linear': gsm.EQ_FIXED_LINEAR }
self.burst.d_equalizer_type = eq_types[options.equalizer]
# timing
@@ -458,6 +478,20 @@ class app_flow_graph(stdgui.gui_flow_graph):
self.burst.d_clock_options = topts
+ #test modes
+ testopts = 0
+
+ if options.test_hop_speed:
+ testopts |= gsm.OPT_TEST_HOP_SPEED
+ self.burst.d_hop_good_arfcn = options.hopgood
+ self.burst.d_hop_bad_arfcn = options.hopbad
+
+ print "!!!!! Enabling Hop Speed Testing (good=%d, bad=%d) !!!!!" % (options.hopgood,options.hopbad)
+
+ self.burst.d_test_options = testopts
+ #print "Test Options: 0x%8.8x" % (self.burst.d_test_options)
+
+
####################
def setup_flowgraph(self):
@@ -630,6 +664,16 @@ class app_flow_graph(stdgui.gui_flow_graph):
print >> out, 'known_count: ',n_known
if n_total:
print >> out, '%known: ', 100.0 * n_known / n_total
+
+ #timing
+ if self.options.decoder.count("c"):
+ omega = self.burst.get_omega()
+ else:
+ omega = self.clocker.omega()
+
+ percent_sps = omega / self.sps
+ print >> out, 'omega: %f (%f / %f)' % (omega,self.sps,percent_sps)
+
print >> out, ""
####################
personal git repositories of Harald Welte. Your mileage may vary