summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortvoid <tvoid@lesaige.com>2008-04-04 00:25:27 -0600
committertvoid <tvoid@lesaige.com>2008-04-04 00:25:27 -0600
commitcac311da272dc0607979d7f8ad85c62a52fb80aa (patch)
tree771082b612a27c9b3472683eda3b0afd3f77ca16
parent9cdb53878ddd6c93c05bf701b1665c58fe7d16d1 (diff)
tvoid working copy as of 2008-04-03
-rwxr-xr-xgsm-tvoid/src/lib/gsm.i56
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst.cc363
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst.h72
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst_cf.cc11
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst_cf.h6
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst_ff.cc12
-rwxr-xr-xgsm-tvoid/src/lib/gsm_burst_ff.h6
-rwxr-xr-xgsm-tvoid/src/lib/gsm_constants.h1
-rwxr-xr-xgsm-tvoid/src/python/gsm_scan.py96
9 files changed, 444 insertions, 179 deletions
diff --git a/gsm-tvoid/src/lib/gsm.i b/gsm-tvoid/src/lib/gsm.i
index cb4db43..624cc30 100755
--- a/gsm-tvoid/src/lib/gsm.i
+++ b/gsm-tvoid/src/lib/gsm.i
@@ -1,17 +1,15 @@
/* -*- c++ -*- */
-
-%feature("autodoc", "1"); // generate python docstrings
-
-%include "exception.i"
+//%feature("autodoc", "1"); // generate python docstrings
+//%include "exception.i"
%import "gnuradio.i" // the common stuff
%{
#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
-#include "gsm_constants.h"
-#include "gsm_burst.h"
+//#include "gsm_constants.h"
+//#include "gsm_burst.h"
#include "gsm_burst_ff.h"
#include "gsm_burst_cf.h"
-#include <stdexcept>
+//#include <stdexcept>
%}
@@ -22,9 +20,10 @@
#define PRINT_BITS 0x00000001
#define PRINT_ALL_BITS 0x00000002
#define PRINT_CORR_BITS 0x00000004
+#define PRINT_STATE 0x00000008
#define PRINT_ALL_TYPES 0x00000FF0
-#define PRINT_KNOWN 0x00000008
+#define PRINT_KNOWN 0x00000FE0
#define PRINT_UNKNOWN 0x00000010
#define PRINT_TS0 0x00000020
#define PRINT_FCCH 0x00000040
@@ -32,6 +31,7 @@
#define PRINT_DUMMY 0x00000100
#define PRINT_NORMAL 0x00000200
+#define PRINT_HEX 0x00001000
//Timing/clock options
#define QB_NONE 0x00000000
@@ -51,8 +51,9 @@ enum EQ_TYPE {
EQ_VITERBI
};
-class gsm_burst
-{
+//GR_SWIG_BLOCK_MAGIC(gsm,burst);
+
+class gsm_burst {
public:
~gsm_burst ();
@@ -70,33 +71,38 @@ public:
long d_unknown_count;
int sync_state();
- float freq_offset();
+ float last_freq_offset(void);
+ double mean_freq_offset(void);
+
+ //Methods
+ //void set_tuner_callback(gsm_tuner_callback *);
+ //void set_tuner_callback(gr_feval_dd *);
+
+ void full_reset(void);
protected:
- gsm_burst();
+// gsm_tuner_callback *p_tuner;
+ gsm_burst(gr_feval_dd *);
};
-GR_SWIG_BLOCK_MAGIC(gsm,burst_ff);
-gsm_burst_ff_sptr gsm_make_burst_ff ();
+GR_SWIG_BLOCK_MAGIC(gsm,burst_ff);
+gsm_burst_ff_sptr gsm_make_burst_ff (gr_feval_dd *);
-class gsm_burst_ff : public gr_block, public gsm_burst
-{
-//public:
+class gsm_burst_ff : public gr_block, public gsm_burst {
private:
- gsm_burst_ff ();
+ gsm_burst_ff (gr_feval_dd *);
};
-
GR_SWIG_BLOCK_MAGIC(gsm,burst_cf);
+gsm_burst_cf_sptr gsm_make_burst_cf (gr_feval_dd *,float);
-gsm_burst_cf_sptr gsm_make_burst_cf (float);
-
-class gsm_burst_cf : public gr_block, public gsm_burst
-{
-//public:
+class gsm_burst_cf : public gr_block, public gsm_burst {
private:
- gsm_burst_cf (float);
+ gsm_burst_cf (gr_feval_dd *,float);
};
+
+
+
diff --git a/gsm-tvoid/src/lib/gsm_burst.cc b/gsm-tvoid/src/lib/gsm_burst.cc
index 5415b2f..c95b460 100755
--- a/gsm-tvoid/src/lib/gsm_burst.cc
+++ b/gsm-tvoid/src/lib/gsm_burst.cc
@@ -3,44 +3,93 @@
#include "config.h"
#endif
+#include "gsm_burst.h"
#include <gr_math.h>
#include <stdio.h>
#include <math.h>
#include <memory.h>
-#include <gsm_burst.h>
#include <assert.h>
-#include "system.h"
-#include "gsmstack.h"
-
-gsm_burst::gsm_burst (void) :
- d_bbuf_pos(0),
- d_burst_start(MAX_CORR_DIST),
- d_sample_count(0),
- d_last_burst_s_count(0),
- d_corr_pattern(0),
- d_corr_pat_size(0),
- d_corr_max(0.0),
- d_corr_maxpos(0),
- d_corr_center(0),
- d_sync_state(WAIT_FCCH),
- d_ts(0),
- d_burst_count(0),
- d_freq_offset(0.0),
- d_sync_loss_count(0),
- d_fcch_count(0),
- d_part_sch_count(0),
- d_sch_count(0),
- d_normal_count(0),
- d_dummy_count(0),
- d_unknown_count(0),
+
+/*
+void do_tuner_callback(gsm_tuner_callback *t, double f)
+{
+ if (t) t->do_tune(f);
+}
+
+
+//this should be overridden by a python class
+void gsm_tuner_callback::tune(double x) {
+ printf("t1: %f\n",x);
+}
+
+void gsm_tuner_callback::do_tune(double x) {
+ printf("do_");
+ tune(x);
+}
+
+
+void gsm_burst::set_tuner_callback(gsm_tuner_callback *f) {
+ printf("set_tuner_callback: %8.8x\n",(unsigned int)f);
+ p_tuner = f;
+}
+*/
+
+/*
+void gsm_burst::set_tuner_callback(gr_feval_dd *t) {
+ p_tuner = t;
+}
+*/
+
+/*
+void gsm_burst::set_status_callback(PSTAT_FUNC func, void *clientdata) {
+ p_stat_func = func;
+ stat_func_data = clientdata;
+}
+
+void gsm_burst::py_set_status_callback(PyObject *pyfunc) {
+ //set_status_callback(PythonCallBack, (void *) pyfunc);
+ stat_func_data = (void *) pyfunc;
+ Py_INCREF(pyfunc);
+}
+*/
+
+
+/*
+static void PythonCallBack(int a, void *clientdata)
+{
+ PyObject *func, *arglist, *result;
+// long int dres = 0;
+
+ func = (PyObject *) clientdata; // Get Python function
+ arglist = Py_BuildValue("(i)",a); // Build argument list
+ result = PyEval_CallObject(func,arglist); // Call Python
+ Py_DECREF(arglist); // Trash arglist
+// if (result) { // If no errors, return double
+// dres = PyInt_AsLong(result);
+// }
+ Py_XDECREF(result);
+// return dres;
+}
+*/
+
+gsm_burst::gsm_burst (gr_feval_dd *t) :
d_clock_options(DEFAULT_CLK_OPTS),
d_print_options(0),
d_equalizer_type(EQ_FIXED_DFE)
-
{
-
+
+ printf("gsm_burst: enter constructor (t=%8.8x)\n",(unsigned int)t);
+
// M_PI = M_PI; //4.0 * atan(1.0);
+ //p_stat_func = 0;
+ //stat_func_data = 0;
+
+ //p_callback = 0;
+ p_tuner = t;
+
+ full_reset();
+
//encode sync bits
float tsync[N_SYNC_BITS];
@@ -48,14 +97,14 @@ gsm_burst::gsm_burst (void) :
tsync[i] = 2.0*SYNC_BITS[i] - 1.0;
}
- fprintf(stdout," Sync: ");
+ fprintf(stderr," Sync: ");
print_bits(tsync,N_SYNC_BITS);
- fprintf(stdout,"\n");
+ fprintf(stderr,"\n");
diff_encode(tsync,corr_sync,N_SYNC_BITS);
- fprintf(stdout,"DSync: ");
+ fprintf(stderr,"DSync: ");
print_bits(corr_sync,N_SYNC_BITS);
- fprintf(stdout,"\n\n");
+ fprintf(stderr,"\n\n");
for (int i=0; i < 10; i++) {
@@ -64,19 +113,68 @@ gsm_burst::gsm_burst (void) :
}
diff_encode(tsync,corr_train_seq[i],N_TRAIN_BITS);
- fprintf(stdout,"TSC%d: ",i);
+ fprintf(stderr,"TSC%d: ",i);
print_bits(corr_train_seq[i],N_TRAIN_BITS);
- fprintf(stdout,"\n");
+ fprintf(stderr,"\n");
}
-
- /* Initialize GSM Stack */
- GS_new(&d_gs_ctx);
+
+ print_hex(dummy_burst,USEFUL_BITS);
+ fprintf(stdout,"\n");
+
}
gsm_burst::~gsm_burst ()
{
}
+void gsm_burst::sync_reset(void)
+{
+ d_sync_state = WAIT_FCCH;
+ d_last_good = 0;
+ d_last_sch = 0;
+ d_burst_count = 0;
+}
+
+//TODO: check this for thread safeness
+void gsm_burst::full_reset(void)
+{
+ sync_reset();
+
+ d_sync_loss_count=0;
+ d_fcch_count=0;
+ d_part_sch_count=0;
+ d_sch_count=0;
+ d_normal_count=0;
+ d_dummy_count=0;
+ d_unknown_count=0;
+
+ d_freq_offset=0.0;
+ d_freq_off_sum=0.0;
+ d_freq_off_weight=0;
+
+ d_ts=0;
+
+ d_bbuf_pos=0;
+ d_burst_start=MAX_CORR_DIST;
+ d_sample_count=0;
+ d_last_burst_s_count=0;
+ d_corr_pattern=0;
+ d_corr_pat_size=0;
+ d_corr_max=0.0;
+ d_corr_maxpos=0;
+ d_corr_center=0;
+ d_last_sync_state=WAIT_FCCH;
+
+}
+
+double gsm_burst::mean_freq_offset(void)
+{
+ if (d_freq_off_weight)
+ return d_freq_off_sum / d_freq_off_weight;
+ else
+ return 0.0;
+}
+
void gsm_burst::diff_encode(const float *in,float *out,int length,float lastbit) {
for (int i=0; i < length; i++) {
@@ -94,24 +192,53 @@ void gsm_burst::diff_decode(const float *in,float *out,int length,float lastbit)
}
}
-void gsm_burst::print_bits(const float *data,int length)
+void gsm_burst::diff_decode_burst(void) {
+ char lastbit = 0;
+
+ //slice
+ for (int i = 0; i < USEFUL_BITS; i++) {
+ d_decoded_burst[i] = d_burst_buffer[d_burst_start + i] > 0 ? 0 : 1;
+ }
+
+ //diff decode
+ for (int i=0; i < USEFUL_BITS; i++) {
+ d_decoded_burst[i] ^= lastbit;
+ lastbit = d_decoded_burst[i];
+ }
+
+}
+
+void gsm_burst::print_hex(const unsigned char *data,int length)
{
+ unsigned char tbyte;
+ int i,bitpos=0;
+
assert(data);
assert(length >= 0);
- for (int i=0; i < length; i++)
- data[i] < 0 ? fprintf(stdout,"+") : fprintf(stdout,".");
+
+
+ while (bitpos < length) {
+ tbyte = 0;
+ for (i=0; (i < 8) && (bitpos < length); i++) {
+ tbyte <<= 1;
+ tbyte |= data[bitpos++];
+ }
+ if (i<8)
+ tbyte <<= 8 - i;
+ fprintf(stdout,"%2.2X ",tbyte);
+ }
}
-void gsm_burst::soft2hardbit(char *dst, const float *data, int len)
+
+void gsm_burst::print_bits(const float *data,int length)
{
- for (int i=0; i < len; i++)
- {
- if (data[i] < 0)
- dst[i] = 0;
- else
- dst[i] = 1;
- }
+ assert(data);
+ assert(length >= 0);
+
+ for (int i=0; i < length; i++)
+ data[i] < 0 ? fprintf(stderr,"+") : fprintf(stderr,".");
+
}
void gsm_burst::print_burst(void)
@@ -120,7 +247,7 @@ void gsm_burst::print_burst(void)
int print = 0;
- //fprintf(stdout,"p=%8.8X ", d_print_options);
+ //fprintf(stderr,"p=%8.8X ", d_print_options);
if ( PRINT_EVERYTHING == d_print_options )
print = 1;
@@ -139,35 +266,16 @@ void gsm_burst::print_burst(void)
if ( print && (d_print_options & PRINT_BITS) ) {
if (d_print_options & PRINT_ALL_BITS)
- {
print_bits(d_burst_buffer,BBUF_SIZE);
- } else {
- /* 142 useful bits: 2*58 + 26 training */
+ else
print_bits(d_burst_buffer + d_burst_start,USEFUL_BITS);
- }
- fprintf(stdout," ");
+ fprintf(stderr," ");
}
- /*
- * Pass information to GSM stack. GSM stack will try to extract
- * information (fn, layer 2 messages, ...)
- */
-
- char buf[156];
- /* In hardbits include the 3 trial bits */
- /* FIXME: access burst has 8 trail bits? what is d_burst_start
- * set to? make sure we start at the right position here.
- */
- soft2hardbit(buf, d_burst_buffer + d_burst_start - 3, 156);
- /* GS_process will differentially decode the data and then
- * extract SCH infos (and later bcch infos).
- */
- GS_process(&d_gs_ctx, d_ts, d_burst_type, buf);
-
if (print) {
- fprintf(stdout,"%d/%d/%+d/%lu/%lu ",
+ fprintf(stderr,"%d/%d/%+d/%lu/%lu ",
d_sync_state,
d_ts,
d_burst_start - MAX_CORR_DIST,
@@ -176,38 +284,38 @@ void gsm_burst::print_burst(void)
switch (d_burst_type) {
case FCCH:
- fprintf(stdout,"[FCCH] foff:%g cnt:%lu",d_freq_offset,d_fcch_count);
+ fprintf(stderr,"[FCCH] foff:%g cnt:%lu",d_freq_offset,d_fcch_count);
break;
case PARTIAL_SCH:
bursts_since_sch = d_burst_count - d_last_sch;
- fprintf(stdout,"[P-SCH] cor:%.2f last:%d cnt: %lu",
+ fprintf(stderr,"[P-SCH] cor:%.2f last:%d cnt: %lu",
d_corr_max,bursts_since_sch,d_sch_count);
break;
case SCH:
bursts_since_sch = d_burst_count - d_last_sch;
- fprintf(stdout,"[SCH] cor:%.2f last:%d cnt: %lu",
+ fprintf(stderr,"[SCH] cor:%.2f last:%d cnt: %lu",
d_corr_max,bursts_since_sch,d_sch_count);
break;
case DUMMY:
- fprintf(stdout,"[DUMMY] cor:%.2f",d_corr_max);
+ fprintf(stderr,"[DUMMY] cor:%.2f",d_corr_max);
break;
case ACCESS:
- fprintf(stdout,"[ACCESS]"); //We don't detect this yet
+ fprintf(stderr,"[ACCESS]"); //We don't detect this yet
break;
case NORMAL:
- fprintf(stdout,"[NORM] clr:%d cor:%.2f",d_color_code,d_corr_max);
+ fprintf(stderr,"[NORM] clr:%d cor:%.2f",d_color_code,d_corr_max);
break;
case UNKNOWN:
- fprintf(stdout,"[?]");
+ fprintf(stderr,"[?]");
break;
default:
- fprintf(stdout,"[oops! default]");
+ fprintf(stderr,"[oops! default]");
break;
}
- fprintf(stdout,"\n");
+ fprintf(stderr,"\n");
//print the correlation pattern for visual inspection
@@ -224,20 +332,39 @@ void gsm_burst::print_burst(void)
pat_indent = d_corr_center - MAX_CORR_DIST; //useful bits will already be offset
for (int i = 0; i < pat_indent; i++)
- fprintf(stdout," ");
+ fprintf(stderr," ");
- fprintf(stdout," "); //extra space for skipped bit
+ fprintf(stderr," "); //extra space for skipped bit
print_bits(d_corr_pattern+1,d_corr_pat_size-1); //skip first bit (diff encoding)
- fprintf(stdout,"\t\toffset:%d, max: %.2f \n",d_corr_maxpos,d_corr_max);
+ fprintf(stderr,"\t\toffset:%d, max: %.2f \n",d_corr_maxpos,d_corr_max);
}
}
+
+ //Print Burst data in hex
+ if ( d_print_options & PRINT_HEX ) {
+ fprintf(stdout,"%d,%d,",d_ts,d_burst_type);
+ diff_decode_burst();
+ print_hex(d_decoded_burst,USEFUL_BITS);
+ fprintf(stdout,"\n");
+ }
+
+ //Print State related messages
+ if ( d_print_options & PRINT_STATE ) {
+ if ( (SYNCHRONIZED == d_sync_state) && (SYNCHRONIZED != d_last_sync_state) ) {
+ fprintf(stderr,"====== SYNC GAINED (FOff: %g Corr: %.2f, Color: %d ) ======\n",d_freq_offset,d_corr_max,d_color_code);
+ }
+ else if ( (SYNCHRONIZED != d_sync_state) && (SYNCHRONIZED == d_last_sync_state) ) {
+ fprintf(stderr,"====== SYNC LOST (%ld) ======\n",d_sync_loss_count);
+ }
+ }
+
}
void gsm_burst::shift_burst(int shift_bits)
{
- //fprintf(stdout,"sft:%d\n",shift_bits);
+ //fprintf(stderr,"sft:%d\n",shift_bits);
assert(shift_bits >= 0);
assert(shift_bits < BBUF_SIZE );
@@ -273,6 +400,14 @@ void gsm_burst::calc_freq_offset(void)
float p_off = mean - (M_PI / 2);
d_freq_offset = p_off * 1625000.0 / (12.0 * M_PI);
+
+ //maintain a 100 weight mean
+ if (d_freq_off_weight < 100)
+ d_freq_off_weight++;
+ else
+ d_freq_off_sum *= 99.0/100.0;
+
+ d_freq_off_sum += d_freq_offset;
}
// This will look for a series of positive phase differences comprising
@@ -292,10 +427,12 @@ BURST_TYPE gsm_burst::get_fcch_burst(void)
if (d_burst_buffer[i] > 0) {
if ( ! hit_count++ )
start_pos = i;
- } else {
+ }
+ else {
if (hit_count >= FCCH_HITS_NEEDED) {
break;
- } else if ( ++miss_count > FCCH_MAX_MISSES ) {
+ }
+ else if ( ++miss_count > FCCH_MAX_MISSES ) {
start_pos = -1;
hit_count = miss_count = 0;
}
@@ -310,11 +447,13 @@ BURST_TYPE gsm_burst::get_fcch_burst(void)
d_bbuf_pos = 0; //load buffer from start
return FCCH;
- } else {
+ }
+ else {
//TODO: don't shift a tiny amount
shift_burst(start_pos - MAX_CORR_DIST);
}
- } else {
+ }
+ else {
//Didn't find anything
d_burst_start = MAX_CORR_DIST;
d_bbuf_pos = 0; //load buffer from start
@@ -344,7 +483,7 @@ void gsm_burst::equalize(void)
}
break;
default:
- fprintf(stdout,"!EQ");
+ fprintf(stderr,"!EQ");
case EQ_NONE:
break;
}
@@ -408,7 +547,8 @@ BURST_TYPE gsm_burst::get_sch_burst(void)
} else {
type = SCH;
}
- } else {
+ }
+ else {
d_burst_start = MAX_CORR_DIST;
}
@@ -434,7 +574,8 @@ BURST_TYPE gsm_burst::get_norm_burst(void)
d_burst_start = MAX_CORR_DIST;
d_corr_maxpos = 0; //we don't want to affect timing
- } else {
+ }
+ else {
equalize();
eq=1;
@@ -451,7 +592,8 @@ BURST_TYPE gsm_burst::get_norm_burst(void)
if ( NORM_CORR_THRESHOLD < correlate_pattern(corr_train_seq[TS_DUMMY],N_TRAIN_BITS,MAX_CORR_DIST+TRAIN_POS,MAX_CORR_DIST) ) {
type = DUMMY;
- } else {
+ }
+ else {
//Match normal training sequences
//TODO: start with current color code
for (int i=0; i < 8; i++) {
@@ -493,7 +635,8 @@ int gsm_burst::get_burst(void)
d_sync_state = WAIT_SCH_ALIGN;
d_bbuf_pos = 0; //load buffer from start
- } else {
+ }
+ else {
got_burst = 0;
}
@@ -565,7 +708,30 @@ int gsm_burst::get_burst(void)
break;
}
+ if (UNKNOWN != d_burst_type) {
+ d_last_good = d_burst_count;
+ }
+
+
+ //Check for loss of sync
+ int bursts_since_good = d_burst_count - d_last_good;
+ if (bursts_since_good > MAX_SYNC_WAIT) {
+ d_sync_loss_count++;
+ sync_reset();
+ }
+
if (got_burst) {
+ //do callback
+ //do_tuner_callback(p_tuner,1.0);
+ //if (p_callback)
+ if (p_tuner)
+ //p_tuner->eval(1.0);
+ p_tuner->calleval(1.0);
+ //p_tuner->do_tune(1.0);
+ //PythonCallBack(STAT_GOT_BURST,stat_func_data);
+ //(*p_stat_func)(STAT_GOT_BURST,stat_func_data);
+ //p_callback->(1.0);
+
//print info
print_burst();
@@ -574,19 +740,10 @@ int gsm_burst::get_burst(void)
d_bbuf_pos += MAX_CORR_DIST - d_burst_start;
}
- //Check for loss of sync
- int bursts_since_sch = d_burst_count - d_last_sch;
- if (bursts_since_sch > MAX_SYNC_WAIT) {
- d_sync_loss_count++;
- d_sync_state = WAIT_FCCH;
- d_last_sch = 0;
- d_burst_count = 0;
- fprintf(stdout,"====== SYNC LOST (%ld) ======\n",d_sync_loss_count); //TODO: move this to the print routine
- }
-
+ d_last_sync_state = d_sync_state;
+
d_ts = (++d_ts)%8; //next TS
return got_burst;
}
-
diff --git a/gsm-tvoid/src/lib/gsm_burst.h b/gsm-tvoid/src/lib/gsm_burst.h
index 951cef2..15566a9 100755
--- a/gsm-tvoid/src/lib/gsm_burst.h
+++ b/gsm-tvoid/src/lib/gsm_burst.h
@@ -6,9 +6,10 @@
// everything but I/O & clocking & sync_state?
// What about handling complex&diff&bin data?
-#include <gsm_constants.h>
+#include "gsm_constants.h"
#include <gr_math.h>
-#include "gsmstack.h"
+//#include <Python.h> //for callback testing
+#include <gr_feval.h>
//Console printing options
#define PRINT_NOTHING 0x00000000
@@ -16,9 +17,10 @@
#define PRINT_BITS 0x00000001
#define PRINT_ALL_BITS 0x00000002
#define PRINT_CORR_BITS 0x00000004
+#define PRINT_STATE 0x00000008
#define PRINT_ALL_TYPES 0x00000FF0
-#define PRINT_KNOWN 0x00000008
+#define PRINT_KNOWN 0x00000FE0
#define PRINT_UNKNOWN 0x00000010
#define PRINT_TS0 0x00000020
#define PRINT_FCCH 0x00000040
@@ -26,6 +28,8 @@
#define PRINT_DUMMY 0x00000100
#define PRINT_NORMAL 0x00000200
+#define PRINT_HEX 0x00001000
+
//Timing/clock options
#define QB_NONE 0x00000000
#define QB_QUARTER 0x00000001 //only for internal clocked versions
@@ -46,7 +50,7 @@
// G T D1 TS D2 T G
// Start ^
-#define MAX_SYNC_WAIT 176 //Bursts between SCH before reverting to WAIT_FCCH. (TODO: 88 should be max?)
+#define MAX_SYNC_WAIT 32 //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
@@ -65,13 +69,28 @@ enum EQ_TYPE {
EQ_VITERBI
};
+//typedef void (*PSTAT_FUNC)(int, void *);
+//#define STAT_GOT_BURST 1
+//double gr_feval_callback(gr_feval_dd *f, double x);
+
+/*
+class gsm_tuner_callback {
+protected:
+ virtual void tune(double x);
+
+public:
+ virtual void do_tune(double x);
+};
+*/
+//void do_tuner_callback(gsm_tuner_callback *t, double f);
+
class gsm_burst;
class gsm_burst
{
protected:
- gsm_burst();
+ gsm_burst(gr_feval_dd *t);
//Burst Buffer: Storage for burst data
float d_burst_buffer[BBUF_SIZE];
@@ -80,29 +99,37 @@ protected:
unsigned long d_sample_count; //sample count at end (TODO:beginning) of BBUF (bit count if external clock)
unsigned long d_last_burst_s_count; //sample count from previous burst
+ unsigned char d_decoded_burst[USEFUL_BITS]; //Differentially Decoded burst buffer {0,1}
+
///// Sync/training sequence correlation
- //TODO: need all sync patterns
float corr_sync[N_SYNC_BITS]; //encoded sync bits for correlation
float corr_train_seq[10][N_TRAIN_BITS];
-// float d_corr[50];
const float *d_corr_pattern;
int d_corr_pat_size;
float d_corr_max;
int d_corr_maxpos;
int d_corr_center;
- ///// GSM Stack
- GS_CTX d_gs_ctx;
-
///// Burst information
SYNC_STATE d_sync_state;
+ SYNC_STATE d_last_sync_state;
BURST_TYPE d_burst_type;
unsigned d_ts; //timeslot 0-7
+ unsigned long d_last_good; //Burst count of last good burst
unsigned long d_burst_count; //Bursts received starting w/ initial FCCH reset after lost sync
unsigned long d_last_sch; //Burst count of last SCH
- float d_freq_offset;
int d_color_code;
+ float d_freq_offset;
+ double d_freq_off_sum;
+ double d_freq_off_weight;
+
+ //PSTAT_FUNC p_stat_func;
+ //void *stat_func_data;
+
+ gr_feval_dd *p_tuner;
+ //gsm_tuner_callback *p_tuner;
+
//////// Methods
int get_burst(void);
BURST_TYPE get_fcch_burst(void);
@@ -113,18 +140,31 @@ protected:
void calc_freq_offset(void);
void equalize(void);
float correlate_pattern(const float *,const int,const int,const int);
+ void diff_decode_burst(void);
+
+ void sync_reset(void);
void print_bits(const float *data,int length);
- void soft2hardbit(char *dst, const float *data, int len);
+ void print_hex(const unsigned char *data,int length);
void print_burst(void);
void diff_encode(const float *in,float *out,int length,float lastbit = 1.0);
void diff_decode(const float *in,float *out,int length,float lastbit = 1.0);
-
public:
~gsm_burst ();
+ //Set status callback function, needed for quick tune()
+ //void py_set_status_callback(PyObject *pyfunc);
+ //void set_status_callback(PSTAT_FUNC func, void *clientdata);
+
+ //void set_tuner_callback(gr_feval_dd *t);
+
+ //use swig directors to privide a python override
+ //virtual void notify_status(int status);
+
+ //void set_tuner_callback(gsm_tuner_callback *f);
+
////// General Stats
//TODO: Maybe there should be a burst_stats class?
long d_sync_loss_count;
@@ -141,11 +181,11 @@ public:
EQ_TYPE d_equalizer_type;
int sync_state() { return d_sync_state;}
- float freq_offset() {return d_freq_offset;}
+ float last_freq_offset() {return d_freq_offset;}
+ double mean_freq_offset(void);
//Methods
- //TODO: reset state (e.g. channel change)
- //void reset(void);
+ void full_reset(void);
};
diff --git a/gsm-tvoid/src/lib/gsm_burst_cf.cc b/gsm-tvoid/src/lib/gsm_burst_cf.cc
index 8954b3f..f08424d 100755
--- a/gsm-tvoid/src/lib/gsm_burst_cf.cc
+++ b/gsm-tvoid/src/lib/gsm_burst_cf.cc
@@ -9,9 +9,9 @@
#include <stdio.h>
#include <gri_mmse_fir_interpolator_cc.h>
-gsm_burst_cf_sptr gsm_make_burst_cf (float sample_rate)
+gsm_burst_cf_sptr gsm_make_burst_cf (gr_feval_dd *t,float sample_rate)
{
- return gsm_burst_cf_sptr (new gsm_burst_cf (sample_rate));
+ return gsm_burst_cf_sptr (new gsm_burst_cf (t,sample_rate));
}
static const int MIN_IN = 1; // minimum number of input streams
@@ -19,15 +19,17 @@ static const int MAX_IN = 1; // maximum number of input streams
static const int MIN_OUT = 1; // minimum number of output streams
static const int MAX_OUT = 1; // maximum number of output streams
-gsm_burst_cf::gsm_burst_cf (float sample_rate) :
+gsm_burst_cf::gsm_burst_cf (gr_feval_dd *t, float sample_rate) :
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))),
+ gsm_burst(t),
d_clock_counter(0.0),
d_last_sample(0.0,0.0),
d_interp(new gri_mmse_fir_interpolator_cc())
{
+ printf("gsm_burst_cf: enter constructor\n");
//clocking parameters
d_sample_interval = 1.0 / sample_rate;
@@ -78,7 +80,8 @@ int gsm_burst_cf::general_work (int noutput_items,
d_clock_counter -= GSM_SYMBOL_PERIOD; //reset clock for next sample, keep the remainder
- float mu = 1.0 - d_clock_counter / GSM_SYMBOL_PERIOD;
+ //float mu = 1.0 - d_clock_counter / GSM_SYMBOL_PERIOD;
+ float mu = d_clock_counter / GSM_SYMBOL_PERIOD;
gr_complex sample = d_interp->interpolate (&in[ii], mu); //FIXME: this seems noisy, make sure it is being used correctly
gr_complex conjprod = sample * conj(d_last_sample);
diff --git a/gsm-tvoid/src/lib/gsm_burst_cf.h b/gsm-tvoid/src/lib/gsm_burst_cf.h
index 33f61f6..fe742c4 100755
--- a/gsm-tvoid/src/lib/gsm_burst_cf.h
+++ b/gsm-tvoid/src/lib/gsm_burst_cf.h
@@ -8,7 +8,7 @@ class gsm_burst_cf;
typedef boost::shared_ptr<gsm_burst_cf> gsm_burst_cf_sptr;
-gsm_burst_cf_sptr gsm_make_burst_cf(float);
+gsm_burst_cf_sptr gsm_make_burst_cf(gr_feval_dd *,float);
class gri_mmse_fir_interpolator_cc;
@@ -16,8 +16,8 @@ class gsm_burst_cf : public gr_block, public gsm_burst
{
private:
- friend gsm_burst_cf_sptr gsm_make_burst_cf(float);
- gsm_burst_cf(float);
+ friend gsm_burst_cf_sptr gsm_make_burst_cf(gr_feval_dd *,float);
+ gsm_burst_cf(gr_feval_dd *,float);
//clocking parameters
float d_relative_sample_rate;
diff --git a/gsm-tvoid/src/lib/gsm_burst_ff.cc b/gsm-tvoid/src/lib/gsm_burst_ff.cc
index e31b3a9..25f9421 100755
--- a/gsm-tvoid/src/lib/gsm_burst_ff.cc
+++ b/gsm-tvoid/src/lib/gsm_burst_ff.cc
@@ -9,9 +9,9 @@
#include <stdio.h>
#include <gri_mmse_fir_interpolator_cc.h>
-gsm_burst_ff_sptr gsm_make_burst_ff (void)
+gsm_burst_ff_sptr gsm_make_burst_ff (gr_feval_dd *t)
{
- return gsm_burst_ff_sptr (new gsm_burst_ff );
+ return gsm_burst_ff_sptr (new gsm_burst_ff(t));
}
static const int MIN_IN = 1; // minimum number of input streams
@@ -19,11 +19,13 @@ static const int MAX_IN = 1; // maximum number of input streams
static const int MIN_OUT = 1; // minimum number of output streams
static const int MAX_OUT = 1; // maximum number of output streams
-gsm_burst_ff::gsm_burst_ff () :
- gr_block ( "burst_ff",
+gsm_burst_ff::gsm_burst_ff (gr_feval_dd *t) :
+ gr_block( "burst_ff",
gr_make_io_signature (MIN_IN, MAX_IN, sizeof (float)),
- gr_make_io_signature (MIN_OUT, MAX_OUT, USEFUL_BITS * sizeof (float)))
+ gr_make_io_signature (MIN_OUT, MAX_OUT, USEFUL_BITS * sizeof (float))),
+ gsm_burst(t)
{
+ printf("gsm_burst_ff: enter constructor\n");
set_history(1);
diff --git a/gsm-tvoid/src/lib/gsm_burst_ff.h b/gsm-tvoid/src/lib/gsm_burst_ff.h
index c9a05f4..30047f2 100755
--- a/gsm-tvoid/src/lib/gsm_burst_ff.h
+++ b/gsm-tvoid/src/lib/gsm_burst_ff.h
@@ -8,14 +8,14 @@ class gsm_burst_ff;
typedef boost::shared_ptr<gsm_burst_ff> gsm_burst_ff_sptr;
-gsm_burst_ff_sptr gsm_make_burst_ff(void);
+gsm_burst_ff_sptr gsm_make_burst_ff(gr_feval_dd *);
class gsm_burst_ff : public gr_block, public gsm_burst
{
private:
- friend gsm_burst_ff_sptr gsm_make_burst_ff(void);
- gsm_burst_ff();
+ friend gsm_burst_ff_sptr gsm_make_burst_ff(gr_feval_dd *);
+ gsm_burst_ff(gr_feval_dd *t);
public:
~gsm_burst_ff ();
diff --git a/gsm-tvoid/src/lib/gsm_constants.h b/gsm-tvoid/src/lib/gsm_constants.h
index 3cc771e..c404b57 100755
--- a/gsm-tvoid/src/lib/gsm_constants.h
+++ b/gsm-tvoid/src/lib/gsm_constants.h
@@ -90,6 +90,7 @@ static const unsigned char train_seq[10][N_TRAIN_BITS] = {
{0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1} // DUMMY
};
+//Dummy burst 0xFB 76 0A 4E 09 10 1F 1C 5C 5C 57 4A 33 39 E9 F1 2F A8
static const unsigned char dummy_burst[] = {
1, 1, 1, 1, 1, 0, 1, 1, 0, 1,
1, 1, 0, 1, 1, 0, 0, 0, 0, 0,
diff --git a/gsm-tvoid/src/python/gsm_scan.py b/gsm-tvoid/src/python/gsm_scan.py
index 42f7944..f8fa033 100755
--- a/gsm-tvoid/src/python/gsm_scan.py
+++ b/gsm-tvoid/src/python/gsm_scan.py
@@ -1,9 +1,13 @@
#!/usr/bin/env python
# TODO:
-# * Auto-tune offset
+# * Adjust offset by PPM
+# * Auto-tune offset (add option to enable)
# * Add status info to window (frequency, offset, etc)
# * Put direct frequency tuning back
-# * Add rate-limited of file reads (Fix throttle?)
+# * Add rate-limited file reads (throttle?)
+# * Make console only version
+# * Reset burst_stats on retune
+# * Add better option checking
import sys
@@ -65,10 +69,29 @@ def get_freq_from_arfcn(chan,region):
return freq * 1e6
+#class gsm_tuner(gsm.gsm_tuner_callback):
+class gsm_tuner(gr.feval_dd):
+ def __init__(self, fg):
+ gr.feval_dd.__init__(self)
+ self.fg = fg
+
+ def eval(self, x):
+ try:
+ print "tune: ", x, "\n";
+ fg.cb_count += 1
+ return 0.0
+
+ except Exception, e:
+ print "tune: Exception: ", e
+
+
class app_flow_graph(stdgui.gui_flow_graph):
def __init__(self, frame, panel, vbox, argv):
stdgui.gui_flow_graph.__init__(self)
+ #testing
+ self.cb_count = 0
+
self.frame = frame
self.panel = panel
@@ -81,7 +104,7 @@ class app_flow_graph(stdgui.gui_flow_graph):
help="What to print on console. [default=%default]\n" +
"(n)othing, (e)verything, (s)tatus, (a)ll Types, (k)nown, (u)nknown, \n" +
"TS(0), (F)CCH, (S)CH, (N)ormal, (D)ummy\n" +
- "Usefull (b)its, All TS (B)its, (C)orrelation bits")
+ "Usefull (b)its, All TS (B)its, (C)orrelation bits, he(x) burst data")
#decoder options
@@ -110,6 +133,7 @@ class app_flow_graph(stdgui.gui_flow_graph):
#usrp options
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
help="Select USRP Rx side A or B (default=first one with a daughterboard)")
+ #FIXME: gain not working?
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=None,
@@ -144,7 +168,12 @@ class app_flow_graph(stdgui.gui_flow_graph):
if options.clock_offset:
clock_rate = 64e6 + options.clock_offset
elif options.channel:
- percent_offset = options.offset / get_freq_from_arfcn(options.channel,options.region)
+ f = get_freq_from_arfcn(options.channel,options.region)
+ if f:
+ percent_offset = options.offset / get_freq_from_arfcn(options.channel,options.region)
+ else:
+ percent_offset = 0.0
+
clock_rate += clock_rate * percent_offset
print "% offset = ", percent_offset, "clock = ", clock_rate
@@ -206,9 +235,12 @@ class app_flow_graph(stdgui.gui_flow_graph):
if self.scopes.count("I"):
self.connect(self.u, self.input_fft_scope)
+ #create a tuner callback
+ self.tuner = gsm_tuner(self)
+
# Setup flow based on decoder selection
if options.decoder.count("c"):
- self.burst = gsm.burst_cf(input_rate)
+ self.burst = gsm.burst_cf(self.tuner,input_rate)
self.connect(self.filter, self.burst)
elif options.decoder.count("f"):
@@ -225,7 +257,7 @@ class app_flow_graph(stdgui.gui_flow_graph):
gain_mu,
0.3) #omega_relative_limit,
- self.burst = gsm.burst_ff()
+ self.burst = gsm.burst_ff(self.tuner)
self.connect(self.filter, self.demod, self.clocker, self.burst)
if self.scopes.count("d"):
@@ -284,6 +316,9 @@ class app_flow_graph(stdgui.gui_flow_graph):
#console print options
popts = 0
+ if options.print_console.count('s'):
+ popts |= gsm.PRINT_STATE
+
if options.print_console.count('e'):
popts |= gsm.PRINT_EVERYTHING
@@ -313,6 +348,9 @@ class app_flow_graph(stdgui.gui_flow_graph):
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
if options.print_console.count('B'):
popts |= gsm.PRINT_BITS | gsm.PRINT_ALL_BITS
@@ -320,7 +358,12 @@ class app_flow_graph(stdgui.gui_flow_graph):
elif options.print_console.count('b'):
popts |= gsm.PRINT_BITS
- self.burst.d_print_options = popts
+ self.burst.d_print_options = popts
+
+ ##########################
+ #set burst tuning callback
+ #self.tuner = gsm_tuner()
+ #self.burst.set_tuner_callback(self.tuner)
# connect the primary path after source
self.v2s = gr.vector_to_stream(gr.sizeof_float,142) #burst output is 142 (USEFUL_BITS)
@@ -434,21 +477,34 @@ class app_flow_graph(stdgui.gui_flow_graph):
self.set_freq(freq)
else:
self._set_status_msg("Invalid Channel")
-
+
+ def print_stats(self):
+ n_known = self.burst.d_fcch_count + self.burst.d_sch_count + self.burst.d_normal_count + self.burst.d_dummy_count
+ n_total = n_known + self.burst.d_dummy_count
+
+ print "======== STATS ========="
+ print 'freq_offset: ',self.burst.mean_freq_offset()
+ print 'sync_loss_count:',self.burst.d_sync_loss_count
+ print 'total_bursts: ',n_total
+ print 'fcch_count: ',self.burst.d_fcch_count
+ print 'part_sch_count: ',self.burst.d_part_sch_count
+ print 'sch_count: ',self.burst.d_sch_count
+ print 'normal_count: ',self.burst.d_normal_count
+ print 'dummy_count: ',self.burst.d_dummy_count
+ print 'unknown_count: ',self.burst.d_unknown_count
+ print 'known_count: ',n_known
+ if n_total:
+ print '%known: ', 100.0 * n_known / n_total
+ print 'CB count: ',self.cb_count
+ print ""
+
def on_tick(self, evt):
+ #if option.autotune
+ #tune offset
+
if self.print_status:
- #TODO: def print_stats:
- print "======== STATS ========="
- print 'freq_offset:',self.burst.freq_offset()
- print 'sync_loss_count:',self.burst.d_sync_loss_count
- print 'fcch_count:',self.burst.d_fcch_count
- print 'part_sch_count:',self.burst.d_part_sch_count
- print 'sch_count:',self.burst.d_sch_count
- print 'normal_count:',self.burst.d_normal_count
- print 'dummy_count:',self.burst.d_dummy_count
- print 'unknown_count:',self.burst.d_unknown_count
- print ""
-
+ self.print_stats()
+
def main ():
app = stdgui.stdapp(app_flow_graph, "GSM Scanner", nstatus=1)
app.MainLoop()
personal git repositories of Harald Welte. Your mileage may vary