Huge messy reorg to move things into the GR3.7 paradigm. Mostly in effort to get

SWIG magic to work on member functions. Can change sample rate on the fly now.
This commit is contained in:
Nick Foster 2013-08-05 16:26:22 -07:00
parent 1630e67c3b
commit a528f375f7
24 changed files with 360 additions and 320 deletions

View File

@ -108,7 +108,7 @@ add_custom_target(uninstall
######################################################################## ########################################################################
# Add subdirectories # Add subdirectories
######################################################################## ########################################################################
add_subdirectory(include) add_subdirectory(include/gr_air_modes)
add_subdirectory(lib) add_subdirectory(lib)
add_subdirectory(swig) add_subdirectory(swig)
add_subdirectory(python) add_subdirectory(python)

View File

@ -137,6 +137,10 @@ class mainwindow(QtGui.QMainWindow):
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_map_highlight) self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_map_highlight)
self.datamodel.dataChanged.connect(self.unmapped_widgets_dataChanged) self.datamodel.dataChanged.connect(self.unmapped_widgets_dataChanged)
#hook up parameter-changed signals so we can change gain, rate, etc. while running
self.ui.combo_rate.currentIndexChanged['QString'].connect(self.update_sample_rate)
# self.ui.
#hook up live data text box update signal #hook up live data text box update signal
self.live_data_changed_signal.connect(self.on_append_live_data) self.live_data_changed_signal.connect(self.on_append_live_data)
@ -145,6 +149,10 @@ class mainwindow(QtGui.QMainWindow):
self.prefs = None self.prefs = None
def update_sample_rate(self, rate):
if self.running:
self._radio.set_rate(int(float(rate)*1e6))
############ widget update functions for non-mapped widgets ############ ############ widget update functions for non-mapped widgets ############
def update_heading_widget(self, index): def update_heading_widget(self, index):
if index.model() is not None: if index.model() is not None:

View File

@ -86,8 +86,9 @@ def main():
sbs1port = air_modes.output_sbs1(cpr_dec, 30003, publisher) sbs1port = air_modes.output_sbs1(cpr_dec, 30003, publisher)
tb.run() tb.run()
time.sleep(0.2)
tb.close() tb.close()
time.sleep(0.2)
relay.close() relay.close()
if options.kml is not None: if options.kml is not None:

View File

@ -1,54 +0,0 @@
/*
# Copyright 2010 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifndef INCLUDED_AIR_MODES_int_and_dump_H
#define INCLUDED_AIR_MODES_int_and_dump_H
#include <gr_block.h>
class air_modes_int_and_dump;
typedef boost::shared_ptr<air_modes_int_and_dump> air_modes_int_and_dump_sptr;
air_modes_int_and_dump_sptr air_make_modes_int_and_dump(int samples_per_chip);
/*!
* \brief mode select int_and_dump filter
* \ingroup block
*/
class air_modes_int_and_dump : public gr_block
{
private:
friend air_modes_int_and_dump_sptr air_make_modes_int_and_dump(int samples_per_chip);
air_modes_int_and_dump(int samples_per_chip);
int d_samples_per_chip;
float d_acc;
float d_pos;
public:
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif /* INCLUDED_AIR_MODES_int_and_dump_H */

View File

@ -1,66 +0,0 @@
/*
# Copyright 2010 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifndef INCLUDED_AIR_MODES_PREAMBLE_H
#define INCLUDED_AIR_MODES_PREAMBLE_H
#include <gnuradio/block.h>
#include <air_modes_api.h>
class air_modes_preamble;
typedef boost::shared_ptr<air_modes_preamble> air_modes_preamble_sptr;
AIR_MODES_API air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshold_db);
/*!
* \brief mode select preamble detection
* \ingroup block
*/
class AIR_MODES_API air_modes_preamble : public gr::block
{
private:
friend air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshold_db);
air_modes_preamble(int channel_rate, float threshold_db);
int d_check_width;
int d_chip_rate;
float d_preamble_length_us;
int d_samples_per_chip;
int d_samples_per_symbol;
float d_threshold_db;
float d_threshold;
pmt::pmt_t d_me, d_key;
gr::tag_t d_timestamp;
double d_secs_per_sample;
public:
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
void set_rate(int channel_rate);
void set_threshold(float threshold_db);
float get_threshold(void);
};
#endif /* INCLUDED_AIR_MODES_PREAMBLE_H */

View File

@ -21,9 +21,9 @@
# Install public header files # Install public header files
######################################################################## ########################################################################
install(FILES install(FILES
air_modes_preamble.h preamble.h
air_modes_slicer.h slicer.h
air_modes_types.h types.h
air_modes_api.h api.h
DESTINATION include/gr-air-modes DESTINATION include/gr_air_modes
) )

View File

@ -0,0 +1,51 @@
/*
# Copyright 2013 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifndef INCLUDED_AIR_MODES_PREAMBLE_H
#define INCLUDED_AIR_MODES_PREAMBLE_H
#include <gnuradio/block.h>
#include <gr_air_modes/api.h>
namespace gr {
namespace air_modes {
/*!
* \brief mode select preamble detection
* \ingroup block
*/
class AIR_MODES_API preamble : virtual public gr::block
{
public:
typedef boost::shared_ptr<preamble> sptr;
static sptr make(int channel_rate, float threshold_db);
virtual void set_rate(int channel_rate) = 0;
virtual void set_threshold(float threshold_db) = 0;
virtual int get_rate(void) = 0;
virtual float get_threshold(void) = 0;
};
} // namespace air_modes
} // namespace gr
#endif /* INCLUDED_AIR_MODES_PREAMBLE_H */

View File

@ -0,0 +1,47 @@
/*
# Copyright 2013 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifndef INCLUDED_AIR_MODES_SLICER_H
#define INCLUDED_AIR_MODES_SLICER_H
#include <gnuradio/block.h>
#include <gr_air_modes/api.h>
#include <gnuradio/msg_queue.h>
namespace gr {
namespace air_modes {
/*!
* \brief mode select slicer
* \ingroup block
*/
class AIR_MODES_API slicer : virtual public gr::sync_block
{
public:
typedef boost::shared_ptr<slicer> sptr;
static sptr make(gr::msg_queue::sptr queue);
};
} //namespace air_modes
} //namespace gr
#endif /* INCLUDED_AIR_MODES_SLICER_H */

View File

@ -23,8 +23,8 @@
include(GrPlatform) #define LIB_SUFFIX include(GrPlatform) #define LIB_SUFFIX
add_library(air_modes SHARED add_library(air_modes SHARED
air_modes_preamble.cc preamble_impl.cc
air_modes_slicer.cc slicer_impl.cc
modes_crc.cc modes_crc.cc
) )
target_link_libraries(air_modes ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES}) target_link_libraries(air_modes ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES})

View File

@ -1,89 +0,0 @@
/*
# Copyright 2010 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <air_modes_int_and_dump.h>
#include <gr_io_signature.h>
#include <string.h>
#include <iostream>
air_modes_int_and_dump_sptr air_make_modes_int_and_dump(int samples_per_symbol)
{
return air_modes_int_and_dump_sptr (new air_modes_int_and_dump(samples_per_symbol));
}
air_modes_int_and_dump::air_modes_int_and_dump(int samps_per_chip) :
gr_block ("modes_int_and_dump",
gr_make_io_signature (1, 1, sizeof(float)),
gr_make_io_signature (1, 1, sizeof(float)))
{
d_samples_per_symbol = samples_per_symbol;
set_output_multiple(d_samples_per_symbol);
set_history(d_samples_per_symbol);
d_acc = 0;
d_pos = 0;
}
int air_modes_int_and_dump::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
int input_items = std::min(ninput_items[0], ninput_items[1]); //just in case
//ok first of all we look for "preamble_found" tags in our input range.
//get a vector of these tags, then every time we hit one
//reset the integrator position and accumulator
std::vector<pmt::pmt_t> tags;
uint64_t abs_sample_cnt = nitems_read(0);
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + ninput_items, pmt::pmt_string_to_symbol("preamble_found"));
int out_items = 0;
int offset = gr_tags::get_nitems(&tags[0]) - abs_sample_cnt;
for(int i=0; i<120*2; i++) { //for each symbol in a potential long packet
out[out_items] = 0;
for(int j=0; j<d_samples_per_symbol; j++) { //for each sample in the symbol
out[out_items] += in[offset+i+j]; //integrate
}
out_items++;
}
//insert tag here
add_item_tag(0, //stream ID
nitems_written(0), //sample number
pmt::pmt_string_to_symbol("preamble_found");
pmt::PMT_T,
pmt::pmt_string_to_symbol(unique_id());
);
consume_each(wat);
return out_items;
}

View File

@ -26,8 +26,8 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <air_modes_types.h> #include <gr_air_modes/types.h>
#include <modes_crc.h> #include <gr_air_modes/modes_crc.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -26,38 +26,55 @@
#endif #endif
#include <ciso646> #include <ciso646>
#include <air_modes_preamble.h> #include "preamble_impl.h"
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include <string.h> #include <string.h>
#include <iostream> #include <iostream>
#include <gnuradio/tags.h> #include <gnuradio/tags.h>
air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshold_db) namespace gr {
{
return air_modes_preamble_sptr (new air_modes_preamble(channel_rate, threshold_db)); air_modes::preamble::sptr air_modes::preamble::make(int channel_rate, float threshold_db) {
return gnuradio::get_initial_sptr(new air_modes::preamble_impl(channel_rate, threshold_db));
} }
air_modes_preamble::air_modes_preamble(int channel_rate, float threshold_db) : air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) :
gr::block ("modes_preamble", gr::block ("preamble",
gr::io_signature::make2 (2, 2, sizeof(float), sizeof(float)), //stream 0 is received data, stream 1 is moving average for reference gr::io_signature::make2 (2, 2, sizeof(float), sizeof(float)), //stream 0 is received data, stream 1 is moving average for reference
gr::io_signature::make (1, 1, sizeof(float))) //the output packets gr::io_signature::make (1, 1, sizeof(float))) //the output soft symbols
{ {
d_chip_rate = 2000000; //2Mchips per second d_chip_rate = 2000000; //2Mchips per second
d_samples_per_chip = channel_rate / d_chip_rate; //must be integer number of samples per chip to work set_rate(channel_rate);
d_samples_per_symbol = d_samples_per_chip * 2; set_threshold(threshold_db);
d_check_width = 120 * d_samples_per_symbol; //only search to this far from the end of the stream buffer
d_threshold_db = threshold_db;
d_threshold = powf(10., threshold_db/20.); //the level that the sample must be above the moving average in order to qualify as a pulse
d_secs_per_sample = 1.0 / channel_rate;
set_output_multiple(1+d_check_width*2);
std::stringstream str; std::stringstream str;
str << name() << unique_id(); str << name() << unique_id();
d_me = pmt::string_to_symbol(str.str()); d_me = pmt::string_to_symbol(str.str());
d_key = pmt::string_to_symbol("preamble_found"); d_key = pmt::string_to_symbol("preamble_found");
}
void air_modes::preamble_impl::set_rate(int channel_rate) {
d_samples_per_chip = channel_rate / d_chip_rate;
d_samples_per_symbol = d_samples_per_chip * 2;
d_check_width = 120 * d_samples_per_symbol;
d_secs_per_sample = 1.0/channel_rate;
set_output_multiple(1+d_check_width*2);
set_history(d_samples_per_symbol); set_history(d_samples_per_symbol);
} }
void air_modes::preamble_impl::set_threshold(float threshold_db) {
d_threshold_db = threshold_db;
d_threshold = powf(10., threshold_db/20.); //the level that the sample must be above the moving average in order to qualify as a pulse
}
float air_modes::preamble_impl::get_threshold(void) {
return d_threshold_db;
}
int air_modes::preamble_impl::get_rate(void) {
return d_samples_per_chip * d_chip_rate;
}
static void integrate_and_dump(float *out, const float *in, int chips, int samps_per_chip) { static void integrate_and_dump(float *out, const float *in, int chips, int samps_per_chip) {
for(int i=0; i<chips; i++) { for(int i=0; i<chips; i++) {
float acc = 0; float acc = 0;
@ -96,7 +113,7 @@ static double tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, double
return tstime; return tstime;
} }
int air_modes_preamble::general_work(int noutput_items, int air_modes::preamble_impl::general_work(int noutput_items,
gr_vector_int &ninput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) gr_vector_void_star &output_items)
@ -206,3 +223,5 @@ int air_modes_preamble::general_work(int noutput_items,
consume_each(ninputs); consume_each(ninputs);
return 0; return 0;
} }
} //namespace gr

43
lib/preamble_impl.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef _AIR_MODES_PREAMBLE_IMPL_H_
#define _AIR_MODES_PREAMBLE_IMPL_H_
#include <gnuradio/block.h>
#include <gr_air_modes/api.h>
#include <gr_air_modes/preamble.h>
namespace gr {
namespace air_modes {
class AIR_MODES_API preamble_impl : public preamble
{
private:
int d_check_width;
int d_chip_rate;
float d_preamble_length_us;
int d_samples_per_chip;
int d_samples_per_symbol;
float d_threshold_db;
float d_threshold;
pmt::pmt_t d_me, d_key;
gr::tag_t d_timestamp;
double d_secs_per_sample;
public:
preamble_impl(int channel_rate, float threshold_db);
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
void set_rate(int channel_rate);
void set_threshold(float threshold_db);
float get_threshold(void);
int get_rate(void);
};
} //namespace air_modes
} //namespace gr
#endif //_AIR_MODES_PREAMBLE_IMPL_H_

View File

@ -26,12 +26,12 @@
#endif #endif
#include <ciso646> #include <ciso646>
#include <air_modes_slicer.h> #include "slicer_impl.h"
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include <air_modes_types.h> #include <gr_air_modes/types.h>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <modes_crc.h> #include <gr_air_modes/modes_crc.h>
#include <iostream> #include <iostream>
#include <gnuradio/tags.h> #include <gnuradio/tags.h>
@ -41,14 +41,15 @@ extern "C"
#include <string.h> #include <string.h>
} }
air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr::msg_queue::sptr queue) namespace gr {
{
return air_modes_slicer_sptr (new air_modes_slicer(channel_rate, queue)); air_modes::slicer::sptr air_modes::slicer::make(gr::msg_queue::sptr queue) {
return gnuradio::get_initial_sptr(new air_modes::slicer_impl(queue));
} }
air_modes_slicer::air_modes_slicer(int channel_rate, gr::msg_queue::sptr queue) : air_modes::slicer_impl::slicer_impl(gr::msg_queue::sptr queue) :
gr::sync_block ("modes_slicer", gr::sync_block ("slicer",
gr::io_signature::make (1, 1, sizeof(float)), //stream 0 is received data, stream 1 is binary preamble detector output gr::io_signature::make (1, 1, sizeof(float)),
gr::io_signature::make (0, 0, 0) ) gr::io_signature::make (0, 0, 0) )
{ {
//initialize private data here //initialize private data here
@ -63,7 +64,7 @@ air_modes_slicer::air_modes_slicer(int channel_rate, gr::msg_queue::sptr queue)
//this slicer is courtesy of Lincoln Labs. supposedly it is more resistant to mode A/C FRUIT. //this slicer is courtesy of Lincoln Labs. supposedly it is more resistant to mode A/C FRUIT.
//see http://adsb.tc.faa.gov/WG3_Meetings/Meeting8/Squitter-Lon.pdf //see http://adsb.tc.faa.gov/WG3_Meetings/Meeting8/Squitter-Lon.pdf
static slice_result_t slicer(const float bit0, const float bit1, const float ref) { static slice_result_t llslicer(const float bit0, const float bit1, const float ref) {
slice_result_t result; slice_result_t result;
//3dB limits for bit slicing and confidence measurement //3dB limits for bit slicing and confidence measurement
@ -98,7 +99,7 @@ static slice_result_t slicer(const float bit0, const float bit1, const float ref
return result; return result;
} }
int air_modes_slicer::work(int noutput_items, int air_modes::slicer_impl::work(int noutput_items,
gr_vector_const_void_star &input_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) gr_vector_void_star &output_items)
{ {
@ -133,7 +134,7 @@ int air_modes_slicer::work(int noutput_items,
//now let's slice the header so we can determine if it's a short pkt or a long pkt //now let's slice the header so we can determine if it's a short pkt or a long pkt
unsigned char pkt_hdr = 0; unsigned char pkt_hdr = 0;
for(int j=0; j < 5; j++) { for(int j=0; j < 5; j++) {
slice_result_t slice_result = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level); slice_result_t slice_result = llslicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
if(slice_result.decision) pkt_hdr += 1 << (4-j); if(slice_result.decision) pkt_hdr += 1 << (4-j);
} }
if(pkt_hdr == 16 or pkt_hdr == 17 or pkt_hdr == 20 or pkt_hdr == 21) rx_packet.type = Long_Packet; if(pkt_hdr == 16 or pkt_hdr == 17 or pkt_hdr == 20 or pkt_hdr == 21) rx_packet.type = Long_Packet;
@ -143,7 +144,7 @@ int air_modes_slicer::work(int noutput_items,
//it's slice time! //it's slice time!
//TODO: don't repeat your work here, you already have the first 5 bits //TODO: don't repeat your work here, you already have the first 5 bits
for(int j = 0; j < packet_length; j++) { for(int j = 0; j < packet_length; j++) {
slice_result_t slice_result = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level); slice_result_t slice_result = llslicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
//put the data into the packet //put the data into the packet
if(slice_result.decision) { if(slice_result.decision) {
@ -157,11 +158,7 @@ int air_modes_slicer::work(int noutput_items,
} }
} }
/******************** BEGIN TIMESTAMP BS ******************/
rx_packet.timestamp = pmt::to_double(tag_iter->value); rx_packet.timestamp = pmt::to_double(tag_iter->value);
/******************* END TIMESTAMP BS *********************/
//increment for the next round
//here you might want to traverse the whole packet and if you find all 0's, just toss it. don't know why these packets turn up, but they pass ECC. //here you might want to traverse the whole packet and if you find all 0's, just toss it. don't know why these packets turn up, but they pass ECC.
bool zeroes = 1; bool zeroes = 1;
@ -195,3 +192,5 @@ int air_modes_slicer::work(int noutput_items,
if(0) std::cout << "Slicer consumed " << size << ", returned " << size << std::endl; if(0) std::cout << "Slicer consumed " << size << ", returned " << size << std::endl;
return size; return size;
} }
} //namespace gr

View File

@ -1,5 +1,5 @@
/* /*
# Copyright 2010 Nick Foster # Copyright 2013 Nick Foster
# #
# This file is part of gr-air-modes # This file is part of gr-air-modes
# #
@ -20,28 +20,20 @@
# #
*/ */
#ifndef INCLUDED_AIR_MODES_slicer_H #ifndef INCLUDED_AIR_MODES_SLICER_IMPL_H
#define INCLUDED_AIR_MODES_slicer_H #define INCLUDED_AIR_MODES_SLICER_IMPL_H
#include <gnuradio/sync_block.h> #include <gnuradio/sync_block.h>
#include <gnuradio/msg_queue.h> #include <gnuradio/msg_queue.h>
#include <air_modes_api.h> #include <gr_air_modes/api.h>
#include <gr_air_modes/slicer.h>
class air_modes_slicer; namespace gr {
typedef boost::shared_ptr<air_modes_slicer> air_modes_slicer_sptr; namespace air_modes {
AIR_MODES_API air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr::msg_queue::sptr queue); class AIR_MODES_API slicer_impl : public slicer
/*!
* \brief mode select slicer detection
* \ingroup block
*/
class AIR_MODES_API air_modes_slicer : public gr::sync_block
{ {
private: private:
friend air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr::msg_queue::sptr queue);
air_modes_slicer(int channel_rate, gr::msg_queue::sptr queue);
int d_check_width; int d_check_width;
int d_chip_rate; int d_chip_rate;
int d_samples_per_chip; int d_samples_per_chip;
@ -50,9 +42,14 @@ private:
std::ostringstream d_payload; std::ostringstream d_payload;
public: public:
slicer_impl(gr::msg_queue::sptr queue);
int work (int noutput_items, int work (int noutput_items,
gr_vector_const_void_star &input_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items); gr_vector_void_star &output_items);
}; };
#endif /* INCLUDED_AIR_MODES_slicer_H */ } //namespace air_modes
} //namespace gr
#endif /* INCLUDED_AIR_MODES_SLICER_IMPL_H */

21
python/get_uniq.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
import sys, re
if __name__== '__main__':
data = sys.stdin.readlines()
icaos = []
num_icaos = 0
for line in data:
match = re.match(".*from (\w+)", line)
if match is not None:
icao = int(match.group(1), 16)
icaos.append(icao)
#get dupes
dupes = sorted([icao for icao in set(icaos) if icaos.count(icao) > 1])
for icao in dupes:
print "%x" % icao
print "Found non-unique replies from %i aircraft" % len(dupes)

87
python/mlat_client.py Normal file
View File

@ -0,0 +1,87 @@
#!/usr/bin/env python
#
# Copyright 2012 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
#multilateration client
#outputs stamps to server, receives multilaterated outputs back
import socket, pickle, time, sys
import air_modes
from gnuradio import gr
pickle_prot = 0
#pickle_prot = pickle.HIGHEST_PROTOCOL
class client_info:
def __init__(self):
self.name = ""
self.position = []
self.offset_secs = 0
self.offset_frac_secs = 0.0
self.time_source = None
class mlat_client:
def __init__(self, queue, position, server_addr, time_source):
self._queue = queue
self._pos = position
self._name = socket.gethostname()
#connect to server
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._sock.setblocking(1)
self._sock.connect((server_addr, 19005))
info = client_info()
info.name = self._name
info.position = self._pos
info.time_source = time_source #"gpsdo" or None
self._sock.send(pickle.dumps(info))
reply = self._sock.recv(1024)
if reply != "HELO": #i know, shut up
raise Exception("Invalid reply from server: %s" % reply)
self._sock.setblocking(0)
self._remnant = None
def __del__(self):
self._sock.close()
#send a stamped report to the server
def output(self, message):
self._sock.send(message+"\n")
#this is called from the update() method list of the main app thread
def get_mlat_positions(self):
msg = None
try:
msg = self._sock.recv(1024)
except socket.error:
pass
if msg:
for line in msg.splitlines(True):
if line.endswith("\n"):
if self._remnant:
line = self._remnant + line
self._remnant = None
self._queue.insert_tail(gr.message_from_string(line))
else:
if self._remnant is not None:
raise Exception("Malformed data: " + line)
else:
self._remnant = line

1
python/mlat_types.py Normal file
View File

@ -0,0 +1 @@

View File

@ -113,13 +113,17 @@ class modes_radio (gr.top_block, pubsub):
return self._options.source is 'uhd' or self._options.source is 'osmocom' return self._options.source is 'uhd' or self._options.source is 'osmocom'
def set_freq(self, freq): def set_freq(self, freq):
return self._u.set_center_freq(freq, 0) if live_source() else 0 return self._u.set_center_freq(freq, 0) if self.live_source() else 0
def set_gain(self, gain): def set_gain(self, gain):
return self._u.set_gain(gain) if live_source() else 0 return self._u.set_gain(gain) if self.live_source() else 0
def set_rate(self, rate): def set_rate(self, rate):
return self._u.set_rate(rate) if live_source() else 0 self._rx_path.set_rate(rate)
return self._u.set_rate(rate) if self.live_source() else 0
def set_threshold(self, threshold):
self._rx_path.set_threshold(threshold)
def get_freq(self, freq): def get_freq(self, freq):
return self._u.get_center_freq(freq, 0) if live_source() else 1090e6 return self._u.get_center_freq(freq, 0) if live_source() else 1090e6

View File

@ -48,10 +48,10 @@ class rx_path(gr.hier_block2):
self._avg = blocks.moving_average_ff(48*self._spc, 1.0/(48*self._spc))#, self._rate) # 3 preambles self._avg = blocks.moving_average_ff(48*self._spc, 1.0/(48*self._spc))#, self._rate) # 3 preambles
# Synchronize to Mode-S preamble # Synchronize to Mode-S preamble
self._sync = air_modes_swig.modes_preamble(self._rate, self._threshold) self._sync = air_modes_swig.preamble(self._rate, self._threshold)
# Slice Mode-S bits and send to message queue # Slice Mode-S bits and send to message queue
self._slicer = air_modes_swig.modes_slicer(self._rate, self._queue) self._slicer = air_modes_swig.slicer(self._queue)
# Wire up the flowgraph # Wire up the flowgraph
self.connect(self, self._demod) self.connect(self, self._demod)
@ -61,7 +61,6 @@ class rx_path(gr.hier_block2):
def set_rate(self, rate): def set_rate(self, rate):
self._sync.set_rate(rate) self._sync.set_rate(rate)
self._slicer.set_rate(rate)
self._spc = int(rate/2e6) self._spc = int(rate/2e6)
self._avg.set_length_and_scale(48*self._spc, 1.0/(48*self._spc)) self._avg.set_length_and_scale(48*self._spc, 1.0/(48*self._spc))
if self._bb != self._demod: if self._bb != self._demod:

View File

@ -1,45 +1,17 @@
/* -*- c++ -*- */ /* -*- c++ -*- */
%include "gnuradio.i" // the common stuff #define AIR_MODES_API
%include "gnuradio.i"
%{ %{
#include "air_modes_preamble.h" #include "gr_air_modes/preamble.h"
#include "air_modes_slicer.h" #include "gr_air_modes/slicer.h"
#include <gnuradio/msg_queue.h>
%} %}
// ---------------------------------------------------------------- %include "gr_air_modes/preamble.h"
%include "gr_air_modes/slicer.h"
/* GR_SWIG_BLOCK_MAGIC2(air_modes,preamble);
* First arg is the package prefix. GR_SWIG_BLOCK_MAGIC2(air_modes,slicer);
* Second arg is the name of the class minus the prefix.
*
* This does some behind-the-scenes magic so we can
* access howto_square_ff from python as howto.square_ff
*/
GR_SWIG_BLOCK_MAGIC(air,modes_preamble);
air_modes_preamble_sptr air_make_modes_preamble (int channel_rate, float threshold_db);
class air_modes_preamble : public gr::sync_block
{
set_rate(int channel_rate);
set_threshold(float threshold_db);
int get_threshold(void);
private:
air_modes_preamble (int channel_rate, float threshold_db);
};
GR_SWIG_BLOCK_MAGIC(air,modes_slicer);
air_modes_slicer_sptr air_make_modes_slicer (int channel_rate, gr::msg_queue::sptr queue);
class air_modes_slicer : public gr::block
{
set_rate(int channel_rate);
private:
air_modes_slicer (int channel_rate, gr::msg_queue::sptr queue);
};
// ----------------------------------------------------------------