First step to add multichannel capability to the GSM receiver. At this moment it might still contain debuging code. The training sequence number for non C0 channels is embedded in the code.

This commit is contained in:
ptrkrysik 2014-10-30 09:05:15 +01:00
parent a25bb7030b
commit 58213797c1
6 changed files with 524 additions and 483 deletions

View File

@ -25,6 +25,7 @@ cmake_minimum_required(VERSION 2.6)
project(gr-gsm CXX C)
enable_testing()
#set(CMAKE_BUILD_TYPE "Debug")
#select the release build type by default to get optimization flags
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")

View File

@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
<timestamp>Wed Aug 13 19:03:28 2014</timestamp>
<timestamp>Thu Aug 21 20:40:28 2014</timestamp>
<block>
<key>options</key>
<param>
@ -209,6 +209,259 @@
<value>0</value>
</param>
</block>
<block>
<key>gsm_get_bcch_or_ccch_bursts</key>
<param>
<key>id</key>
<value>gsm_get_bcch_or_ccch_bursts_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>d_fn51_start</key>
<value>2</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(660, 243)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>blocks_tag_debug</key>
<param>
<key>id</key>
<value>blocks_tag_debug_0</value>
</param>
<param>
<key>_enabled</key>
<value>False</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>name</key>
<value></value>
</param>
<param>
<key>filter</key>
<value>""</value>
</param>
<param>
<key>num_inputs</key>
<value>1</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
<param>
<key>display</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(456, 477)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_receiver_hier</key>
<param>
<key>id</key>
<value>gsm_receiver_hier_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>input_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>osr</key>
<value>4</value>
</param>
<param>
<key>arfcn</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(455, 244)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_control_channels_decoder</key>
<param>
<key>id</key>
<value>gsm_control_channels_decoder_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(920, 247)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_message_printer</key>
<param>
<key>id</key>
<value>gsm_message_printer_0</value>
</param>
<param>
<key>_enabled</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(1128, 169)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_message_printer</key>
<param>
<key>id</key>
<value>gsm_message_printer_1</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(1141, 247)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>blocks_message_debug</key>
<param>
<key>id</key>
<value>blocks_message_debug_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(240, 405)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>variable_qtgui_range</key>
<param>
@ -225,15 +478,15 @@
</param>
<param>
<key>value</key>
<value>0</value>
<value>84</value>
</param>
<param>
<key>start</key>
<value>-50</value>
<value>-100</value>
</param>
<param>
<key>stop</key>
<value>50</value>
<value>100</value>
</param>
<param>
<key>step</key>
@ -268,6 +521,100 @@
<value>0</value>
</param>
</block>
<block>
<key>gsm_clock_offset_control</key>
<param>
<key>id</key>
<value>gsm_clock_offset_control_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fc</key>
<value>fc</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(329, 155)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
</block>
<block>
<key>clock_offset_corrector</key>
<param>
<key>id</key>
<value>clock_offset_corrector_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fc</key>
<value>fc</value>
</param>
<param>
<key>ppm</key>
<value>0</value>
</param>
<param>
<key>samp_rate_in</key>
<value>samp_rate</value>
</param>
<param>
<key>samp_rate_out</key>
<value>samp_rate</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(251, 236)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>rtlsdr_source</key>
<param>
@ -614,353 +961,6 @@
<value>0</value>
</param>
</block>
<block>
<key>gsm_get_bcch_or_ccch_bursts</key>
<param>
<key>id</key>
<value>gsm_get_bcch_or_ccch_bursts_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>d_fn51_start</key>
<value>2</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(660, 243)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_clock_offset_control</key>
<param>
<key>id</key>
<value>gsm_clock_offset_control_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fc</key>
<value>fc</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(329, 155)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
</block>
<block>
<key>clock_offset_corrector</key>
<param>
<key>id</key>
<value>clock_offset_corrector_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fc</key>
<value>fc</value>
</param>
<param>
<key>ppm</key>
<value>0</value>
</param>
<param>
<key>samp_rate_in</key>
<value>samp_rate</value>
</param>
<param>
<key>samp_rate_out</key>
<value>samp_rate</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(251, 236)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>blocks_tag_debug</key>
<param>
<key>id</key>
<value>blocks_tag_debug_0</value>
</param>
<param>
<key>_enabled</key>
<value>False</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>name</key>
<value></value>
</param>
<param>
<key>filter</key>
<value>""</value>
</param>
<param>
<key>num_inputs</key>
<value>1</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
<param>
<key>display</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(456, 477)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_receiver_hier</key>
<param>
<key>id</key>
<value>gsm_receiver_hier_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>input_rate</key>
<value>samp_rate</value>
</param>
<param>
<key>osr</key>
<value>4</value>
</param>
<param>
<key>arfcn</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(455, 244)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>blocks_message_debug</key>
<param>
<key>id</key>
<value>blocks_message_debug_0</value>
</param>
<param>
<key>_enabled</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(240, 406)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_control_channels_decoder</key>
<param>
<key>id</key>
<value>gsm_control_channels_decoder_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(920, 247)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_message_printer</key>
<param>
<key>id</key>
<value>gsm_message_printer_0</value>
</param>
<param>
<key>_enabled</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(1128, 169)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<block>
<key>gsm_message_printer</key>
<param>
<key>id</key>
<value>gsm_message_printer_1</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
<value>(1141, 247)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
<connection>
<source_block_id>clock_offset_corrector_0</source_block_id>
<sink_block_id>gsm_receiver_hier_0</sink_block_id>
@ -973,12 +973,6 @@
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>clock_offset_corrector_0</source_block_id>
<sink_block_id>qtgui_sink_x_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>gsm_get_bcch_or_ccch_bursts_0</source_block_id>
<sink_block_id>gsm_control_channels_decoder_0</sink_block_id>
@ -1003,6 +997,18 @@
<source_key>msgs</source_key>
<sink_key>msgs</sink_key>
</connection>
<connection>
<source_block_id>gsm_control_channels_decoder_0</source_block_id>
<sink_block_id>gsm_message_printer_1</sink_block_id>
<source_key>msgs</source_key>
<sink_key>msgs</sink_key>
</connection>
<connection>
<source_block_id>gsm_clock_offset_control_0</source_block_id>
<sink_block_id>blocks_message_debug_0</sink_block_id>
<source_key>ppm</source_key>
<sink_key>print</sink_key>
</connection>
<connection>
<source_block_id>gsm_clock_offset_control_0</source_block_id>
<sink_block_id>clock_offset_corrector_0</sink_block_id>
@ -1016,15 +1022,9 @@
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>gsm_receiver_hier_0</source_block_id>
<sink_block_id>blocks_message_debug_0</sink_block_id>
<source_key>measurements</source_key>
<sink_key>print</sink_key>
</connection>
<connection>
<source_block_id>gsm_control_channels_decoder_0</source_block_id>
<sink_block_id>gsm_message_printer_1</sink_block_id>
<source_key>msgs</source_key>
<sink_key>msgs</sink_key>
<source_block_id>rtlsdr_source_0</source_block_id>
<sink_block_id>qtgui_sink_x_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
</flow_graph>

View File

@ -20,10 +20,20 @@
<type>int</type>
</param>
<param>
<name>Num Streams</name>
<key>num_streams</key>
<value>1</value>
<type>int</type>
</param>
<check>$num_streams &gt;= 0</check>
<sink>
<name>in</name>
<type>complex</type>
<nports>$num_streams</nports>
</sink>
<source>
<name>bursts</name>
<type>message</type>

View File

@ -37,7 +37,7 @@
#define MAX_SCH_ERRORS 10 //maximum number of subsequent sch errors after which gsm receiver goes to find_next_fcch state
typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal} burst_type;
typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal, normal_or_noise} burst_type;
typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type;
static const unsigned char SYNC_BITS[] = {

View File

@ -38,7 +38,9 @@
#include <iomanip>
#include <assert.h>
#include <boost/scoped_ptr.hpp>
//#include "plotting/plotting.hpp"
#include "plotting/plotting.hpp"
#include <pthread.h>
#define SYNC_SEARCH_RANGE 30
@ -64,7 +66,7 @@ receiver::make(int osr, int arfcn)
*/
receiver_impl::receiver_impl(int osr, int arfcn)
: gr::sync_block("receiver",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, -1, sizeof(gr_complex)),
gr::io_signature::make(0, 0, 0)),
d_OSR(osr),
d_chan_imp_length(CHAN_IMP_RESP_LENGTH),
@ -104,7 +106,8 @@ receiver_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const gr_complex *input = (const gr_complex *) input_items[0];
// std::vector<const gr_complex *> iii = (std::vector<const gr_complex *>) input_items; // jak zrobić to rzutowanie poprawnie
gr_complex * input = (gr_complex *) input_items[0];
std::vector<tag_t> freq_offset_tags;
uint64_t start = nitems_read(0);
uint64_t stop = start + noutput_items;
@ -122,7 +125,6 @@ receiver_impl::work(int noutput_items,
if(d_state == synchronized && b_type == fcch_burst){
uint64_t last_sample_nr = ceil((GUARD_PERIOD + 2.0 * TAIL_BITS + 156.25) * d_OSR) + 1;
if(tag_offset < last_sample_nr){
DCOUT("Freq change inside FCCH burst!!!!!!!!!!!!!!");
freq_offset_tag_in_fcch = true;
}
d_freq_offset_setting = pmt::to_double(freq_offset_tag.value);
@ -134,9 +136,8 @@ receiver_impl::work(int noutput_items,
switch (d_state)
{
//bootstrapping
case fcch_search: //this state is used because it takes some time (a bunch of buffered samples)
case fcch_search:
{
DCOUT("FCCH search");
double freq_offset_tmp;
if (find_fcch_burst(input, noutput_items,freq_offset_tmp))
{
@ -154,7 +155,6 @@ receiver_impl::work(int noutput_items,
case sch_search:
{
DCOUT("SCH search");
vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR);
int t1, t2, t3;
int burst_start = 0;
@ -166,8 +166,6 @@ receiver_impl::work(int noutput_items,
detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //detect bits using MLSE detection
if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //decode SCH burst
{
DCOUT("sch burst_start: " << burst_start);
DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
d_burst_nr.set(t1, t2, t3, 0); //set counter of bursts value
d_burst_nr++;
@ -188,109 +186,157 @@ receiver_impl::work(int noutput_items,
//in this state receiver is synchronized and it processes bursts according to burst type for given burst number
case synchronized:
{
DCOUT("Synchronized");
vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR);
int burst_start;
int offset = 0;
int to_consume = 0;
unsigned char output_binary[BURST_SIZE];
burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr); //get burst type for given burst number
double signal_pwr = 0;
for(int ii=0;ii<noutput_items;ii++)
{
signal_pwr += abs(input[ii])*abs(input[ii]);
}
d_signal_dbm=static_cast<int8_t>(round(10*log10(signal_pwr/50/noutput_items)));
burst_type b_type;
switch (b_type)
for(int input_nr=0;input_nr<input_items.size();input_nr++)
{
case fcch_burst: //if it's FCCH burst
{
const unsigned first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1;
const unsigned last_sample = first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR;
double freq_offset_tmp = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it
send_burst(d_burst_nr, fc_fb, b_type);
pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("synchronized"));
message_port_pub(pmt::mp("measurements"), msg);
}
break;
case sch_burst: //if it's SCH burst
{
int t1, t2, t3, d_ncc, d_bcc;
burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response
double signal_pwr = 0;
input = (gr_complex *)input_items[input_nr];
detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits
send_burst(d_burst_nr, output_binary, b_type);
if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //and decode SCH data
for(int ii=GUARD_PERIOD;ii<TS_BITS;ii++)
{
// d_burst_nr.set(t1, t2, t3, 0); //but only to check if burst_start value is correct
d_failed_sch = 0;
DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
offset = burst_start - floor((GUARD_PERIOD) * d_OSR); //compute offset from burst_start - burst should start after a guard period
DCOUT("offset: "<<offset);
to_consume += offset; //adjust with offset number of samples to be consumed
signal_pwr += abs(input[ii])*abs(input[ii]);
}
else
signal_pwr = signal_pwr/(TS_BITS);
d_signal_dbm = round(10*log10(signal_pwr/50));
if(input_nr==0){
d_c0_signal_dbm = d_signal_dbm;
}
if(input_nr==0) //for c0 channel burst type is controlled by channel configuration
{
d_failed_sch++;
if (d_failed_sch >= MAX_SCH_ERRORS)
b_type = d_channel_conf.get_burst_type(d_burst_nr); //get burst type for given burst number
}
else
{
b_type = normal_or_noise; //for the rest it can be only normal burst or noise (at least at this moment of development)
}
switch (b_type)
{
case fcch_burst: //if it's FCCH burst
{
const unsigned first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1;
const unsigned last_sample = first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR;
double freq_offset_tmp = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it
send_burst(d_burst_nr, fc_fb, b_type);
pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("synchronized"));
message_port_pub(pmt::mp("measurements"), msg);
break;
}
case sch_burst: //if it's SCH burst
{
int t1, t2, t3, d_ncc, d_bcc;
d_c0_burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response
detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); //MLSE detection of bits
send_burst(d_burst_nr, output_binary, b_type);
if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //and decode SCH data
{
d_state = fcch_search;
pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(0.0),pmt::mp("sync_loss"));
message_port_pub(pmt::mp("measurements"), msg);
COUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
// d_burst_nr.set(t1, t2, t3, 0); //but only to check if burst_start value is correct
d_failed_sch = 0;
offset = d_c0_burst_start - floor((GUARD_PERIOD) * d_OSR); //compute offset from burst_start - burst should start after a guard period
to_consume += offset; //adjust with offset number of samples to be consumed
}
else
{
d_failed_sch++;
if (d_failed_sch >= MAX_SCH_ERRORS)
{
d_state = fcch_search;
pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(0.0),pmt::mp("sync_loss"));
message_port_pub(pmt::mp("measurements"), msg);
DCOUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
}
break;
}
}
break;
case normal_burst:
{
float normal_corr_max; //if it's normal burst
d_c0_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); //get channel impulse response for given training sequence number - d_bcc
detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); //MLSE detection of bits
send_burst(d_burst_nr, output_binary, b_type);
break;
}
case dummy_or_normal:
{
unsigned int normal_burst_start, dummy_burst_start;
float dummy_corr_max, normal_corr_max;
case normal_burst:
{
float normal_corr_max; //if it's normal burst
burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); //get channel impulse response for given training sequence number - d_bcc
detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits
send_burst(d_burst_nr, output_binary, b_type);
break;
}
case dummy_or_normal:
{
unsigned int normal_burst_start;
float dummy_corr_max, normal_corr_max;
get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc);
DCOUT("normal_corr_max: " << normal_corr_max << " dummy_corr_max:" << dummy_corr_max);
if (normal_corr_max > dummy_corr_max)
{
detect_burst(input, &channel_imp_resp[0], normal_burst_start, output_binary);
send_burst(d_burst_nr, output_binary, b_type);
dummy_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc);
if (normal_corr_max > dummy_corr_max)
{
d_c0_burst_start = normal_burst_start;
detect_burst(input, &channel_imp_resp[0], normal_burst_start, output_binary);
send_burst(d_burst_nr, output_binary, b_type);
}
else
{
d_c0_burst_start = dummy_burst_start;
send_burst(d_burst_nr, dummy_burst, b_type);
}
break;
}
else
{
case rach_burst:
break;
case dummy:
send_burst(d_burst_nr, dummy_burst, b_type);
}
}
case rach_burst:
break;
case dummy:
send_burst(d_burst_nr, dummy_burst, b_type);
break;
case empty: //if it's empty burst
break; //do nothing
}
break;
case normal_or_noise:
{
unsigned int burst_start;
float normal_corr_max_tmp;
float normal_corr_max=-1e6;
int max_tn;
std::vector<gr_complex> v(input, input + noutput_items);
if(d_signal_dbm>=d_c0_signal_dbm-13)
{
plot(v);
d_burst_nr++; //go to next burst
to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); //consume samples of the burst up to next guard period
//and add offset which is introduced by
//0.25 fractional part of a guard period
consume_each(to_consume);
burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, 7);
// if(abs(d_c0_burst_start-burst_start)<=2){
if((normal_corr_max/sqrt(signal_pwr))>=0.9){
std::cout << static_cast<int>(d_signal_dbm) << std::endl;
COUT("d_c0_burst_start: " << d_c0_burst_start);
COUT("burst_start: " << burst_start);
std::cout << "corr max to signal ratio: " << (normal_corr_max/sqrt(signal_pwr)) << std::endl;
usleep(4e6);
}
detect_burst(input, &channel_imp_resp[0], burst_start, output_binary);
send_burst(d_burst_nr, output_binary, b_type);
}
break;
}
case empty: //if it's empty burst
break; //do nothing
}
if(input_nr==0)
{
d_burst_nr++; //go to next burst
to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); //consume samples of the burst up to next guard period
}
if(input_nr==input_items.size()-1)
{
consume_each(to_consume);
}
//and add offset which is introduced by
//0.25 fractional part of a guard period
}
}
break;
}
return 0;
}
@ -432,7 +478,6 @@ bool receiver_impl::find_fcch_burst(const gr_complex *input, const int nitems, d
case fcch_found:
{
DCOUT("fcch found on position: " << d_counter + start_pos);
to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1; //consume one FCCH burst
d_fcch_start_pos = d_counter + start_pos;
@ -531,7 +576,6 @@ int receiver_impl::get_sch_chan_imp_resp(const gr_complex *input, gr_complex * c
correlation_buffer.push_back(correlation);
power_buffer.push_back(std::pow(abs(correlation), 2));
}
//plot(power_buffer);
//compute window energies
vector_float::iterator iter = power_buffer.begin();
bool loop_end = false;
@ -693,14 +737,13 @@ int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex *
// int search_start_pos = search_center - d_chan_imp_length * d_OSR;
int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 5 * d_OSR;
for (int ii = search_start_pos; ii < search_stop_pos; ii++)
for(int ii = search_start_pos; ii < search_stop_pos; ii++)
{
gr_complex correlation = correlate_sequence(&d_norm_training_seq[bcc][TRAIN_BEGINNING], N_TRAIN_BITS - 10, &input[ii]);
correlation_buffer.push_back(correlation);
power_buffer.push_back(std::pow(abs(correlation), 2));
}
//plot(power_buffer);
//compute window energies
vector_float::iterator iter = power_buffer.begin();
bool loop_end = false;
@ -748,10 +791,10 @@ int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex *
*corr_max = max_correlation;
DCOUT("strongest_window_nr_new: " << strongest_window_nr);
//DCOUT("strongest_window_nr_new: " << strongest_window_nr);
burst_start = search_start_pos + strongest_window_nr - TRAIN_POS * d_OSR; //compute first sample posiiton which corresponds to the first sample of the impulse response
DCOUT("burst_start: " << burst_start);
//DCOUT("burst_start: " << burst_start);
return burst_start;
}
@ -785,21 +828,6 @@ void receiver_impl::configure_receiver()
d_channel_conf.set_burst_types(TIMESLOT0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
d_channel_conf.set_burst_types(TIMESLOT0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst);
// d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT1, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
// d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT2, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
// d_channel_conf.set_multiframe_type(TIMESLOT3, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT3, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
// d_channel_conf.set_multiframe_type(TIMESLOT4, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT4, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
// d_channel_conf.set_multiframe_type(TIMESLOT5, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT5, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
// d_channel_conf.set_multiframe_type(TIMESLOT6, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT6, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
// d_channel_conf.set_multiframe_type(TIMESLOT7, multiframe_26);
// d_channel_conf.set_burst_types(TIMESLOT7, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_51);
d_channel_conf.set_burst_types(TIMESLOT1, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_51);

View File

@ -34,16 +34,18 @@ namespace gr {
class receiver_impl : public receiver
{
private:
unsigned int d_c0_burst_start;
float d_c0_signal_dbm;
/**@name Configuration of the receiver */
//@{
const int d_OSR; ///< oversampling ratio
const int d_chan_imp_length; ///< channel impulse length
uint16_t d_arfcn;
int8_t d_signal_dbm;
float d_signal_dbm;
//@}
gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a SCH burst
gr_complex d_norm_training_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS]; ///<encoded training sequences of a normal bursts and dummy bursts
gr_complex d_norm_training_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS]; ///<encoded training sequences of a normal and dummy burst
/** Counts samples consumed by the receiver
*