Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0101017e3 | ||
|
|
adbb7ec64b | ||
|
|
77d695f2ef |
@@ -464,7 +464,7 @@ class mainwindow(QtGui.QMainWindow):
|
||||
prefs.read(os.path.expanduser(self.opt_file))
|
||||
for item in prefs.items("GUI"):
|
||||
defaults[item[0]] = item[1]
|
||||
except (IOError, ConfigParser.NoSectionError):
|
||||
except IOError:
|
||||
print "No preferences file %s found, creating..." % os.path.expanduser(self.opt_file)
|
||||
self.write_defaults(defaults)
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ def main():
|
||||
|
||||
if options.kml is not None:
|
||||
kmlgen.close()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -25,5 +25,6 @@ install(FILES
|
||||
slicer.h
|
||||
types.h
|
||||
api.h
|
||||
uplink.h
|
||||
DESTINATION include/gr_air_modes
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#ifndef INCLUDED_MODES_CRC_H
|
||||
#define INCLUDED_MODES_CRC_H
|
||||
extern const unsigned int modes_crc_table[112];
|
||||
unsigned int modes_check_crc(unsigned char data[], int length);
|
||||
int modes_check_crc(unsigned char data[], int length);
|
||||
bruteResultTypeDef modes_ec_brute(modes_packet &err_packet);
|
||||
unsigned next_set_of_n_elements(unsigned x);
|
||||
|
||||
|
||||
52
include/gr_air_modes/uplink.h
Normal file
52
include/gr_air_modes/uplink.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
# 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_UPLINK_H
|
||||
#define INCLUDED_AIR_MODES_UPLINK_H
|
||||
|
||||
#include <gnuradio/block.h>
|
||||
#include <gr_air_modes/api.h>
|
||||
#include <gnuradio/msg_queue.h>
|
||||
|
||||
namespace gr {
|
||||
namespace air_modes {
|
||||
|
||||
/*!
|
||||
* \brief mode select preamble detection
|
||||
* \ingroup block
|
||||
*/
|
||||
class AIR_MODES_API uplink : virtual public gr::block
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<uplink> sptr;
|
||||
static sptr make(int channel_rate, float threshold_db, gr::msg_queue::sptr queue);
|
||||
|
||||
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_UPLINK_H */
|
||||
@@ -26,6 +26,7 @@ add_library(air_modes SHARED
|
||||
preamble_impl.cc
|
||||
slicer_impl.cc
|
||||
modes_crc.cc
|
||||
uplink_impl.cc
|
||||
)
|
||||
target_link_libraries(air_modes ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES})
|
||||
set_target_properties(air_modes PROPERTIES DEFINE_SYMBOL "AIR_MODES_EXPORTS")
|
||||
|
||||
166
lib/modes_crc.cc
166
lib/modes_crc.cc
@@ -1,24 +1,25 @@
|
||||
/*
|
||||
* Copyright 2013 Nick Foster
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of gr-air-modes
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* gr-air-modes is free software; you can redistribute it and/or modify
|
||||
* GNU Radio 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 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* gr-air-modes is distributed in the hope that it will be useful,
|
||||
* GNU Radio 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
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
//this is copied almost verbatim from Eric Cottrell's gr-air platform.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
@@ -30,34 +31,135 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned int crc_table[256];
|
||||
const unsigned int POLY=0xFFF409;
|
||||
|
||||
//generate a bytewise lookup CRC table
|
||||
|
||||
void generate_crc_table(void)
|
||||
/* Mode S Parity Table
|
||||
* Index is bit position with bit 0 being the first bit after preamble
|
||||
* On short frames an offset of 56 is used.
|
||||
*/
|
||||
const unsigned int modes_crc_table[112] =
|
||||
{
|
||||
unsigned int crc = 0;
|
||||
for(int n=0; n<256; n++) {
|
||||
crc = n<<16;
|
||||
for(int k=0; k<8; k++) {
|
||||
if(crc & 0x800000) {
|
||||
crc = ((crc<<1) ^ POLY) & 0xFFFFFF;
|
||||
} else {
|
||||
crc = (crc<<1) & 0xFFFFFF;
|
||||
}
|
||||
}
|
||||
crc_table[n] = crc & 0xFFFFFF;
|
||||
}
|
||||
}
|
||||
0x3935ea, // Start of Long Frame CRC
|
||||
0x1c9af5,
|
||||
0xf1b77e,
|
||||
0x78dbbf,
|
||||
0xc397db,
|
||||
0x9e31e9,
|
||||
0xb0e2f0,
|
||||
0x587178,
|
||||
0x2c38bc,
|
||||
0x161c5e,
|
||||
0x0b0e2f,
|
||||
0xfa7d13,
|
||||
0x82c48d,
|
||||
0xbe9842,
|
||||
0x5f4c21,
|
||||
0xd05c14,
|
||||
0x682e0a,
|
||||
0x341705,
|
||||
0xe5f186,
|
||||
0x72f8c3,
|
||||
0xc68665,
|
||||
0x9cb936,
|
||||
0x4e5c9b,
|
||||
0xd8d449,
|
||||
0x939020,
|
||||
0x49c810,
|
||||
0x24e408,
|
||||
0x127204,
|
||||
0x093902,
|
||||
0x049c81,
|
||||
0xfdb444,
|
||||
0x7eda22,
|
||||
0x3f6d11, // Extended 56 bit field
|
||||
0xe04c8c,
|
||||
0x702646,
|
||||
0x381323,
|
||||
0xe3f395,
|
||||
0x8e03ce,
|
||||
0x4701e7,
|
||||
0xdc7af7,
|
||||
0x91c77f,
|
||||
0xb719bb,
|
||||
0xa476d9,
|
||||
0xadc168,
|
||||
0x56e0b4,
|
||||
0x2b705a,
|
||||
0x15b82d,
|
||||
0xf52612,
|
||||
0x7a9309,
|
||||
0xc2b380,
|
||||
0x6159c0,
|
||||
0x30ace0,
|
||||
0x185670,
|
||||
0x0c2b38,
|
||||
0x06159c,
|
||||
0x030ace,
|
||||
0x018567,
|
||||
0xff38b7, // Start of Short Frame CRC
|
||||
0x80665f,
|
||||
0xbfc92b,
|
||||
0xa01e91,
|
||||
0xaff54c,
|
||||
0x57faa6,
|
||||
0x2bfd53,
|
||||
0xea04ad,
|
||||
0x8af852,
|
||||
0x457c29,
|
||||
0xdd4410,
|
||||
0x6ea208,
|
||||
0x375104,
|
||||
0x1ba882,
|
||||
0x0dd441,
|
||||
0xf91024,
|
||||
0x7c8812,
|
||||
0x3e4409,
|
||||
0xe0d800,
|
||||
0x706c00,
|
||||
0x383600,
|
||||
0x1c1b00,
|
||||
0x0e0d80,
|
||||
0x0706c0,
|
||||
0x038360,
|
||||
0x01c1b0,
|
||||
0x00e0d8,
|
||||
0x00706c,
|
||||
0x003836,
|
||||
0x001c1b,
|
||||
0xfff409,
|
||||
0x800000, // 24 PI or PA bits
|
||||
0x400000,
|
||||
0x200000,
|
||||
0x100000,
|
||||
0x080000,
|
||||
0x040000,
|
||||
0x020000,
|
||||
0x010000,
|
||||
0x008000,
|
||||
0x004000,
|
||||
0x002000,
|
||||
0x001000,
|
||||
0x000800,
|
||||
0x000400,
|
||||
0x000200,
|
||||
0x000100,
|
||||
0x000080,
|
||||
0x000040,
|
||||
0x000020,
|
||||
0x000010,
|
||||
0x000008,
|
||||
0x000004,
|
||||
0x000002,
|
||||
0x000001,
|
||||
};
|
||||
|
||||
//Perform a bytewise CRC check
|
||||
unsigned int modes_check_crc(unsigned char data[], int length)
|
||||
int modes_check_crc(unsigned char data[], int length)
|
||||
{
|
||||
if(crc_table[1] != POLY) generate_crc_table();
|
||||
unsigned int crc=0;
|
||||
for(int i=0; i<length; i++) {
|
||||
crc = crc_table[((crc>>16) ^ data[i]) & 0xff] ^ (crc << 8);
|
||||
}
|
||||
return crc & 0xFFFFFF;
|
||||
int crc=0, i;
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
if(data[i/8] & (1 << (7-(i%8))))
|
||||
{
|
||||
crc ^= modes_crc_table[i+(112-length)];
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
@@ -172,11 +172,7 @@ int air_modes::slicer_impl::work(int noutput_items,
|
||||
if(rx_packet.type == Short_Packet && rx_packet.message_type != 11 && rx_packet.numlowconf > 0) {continue;}
|
||||
if(rx_packet.message_type == 11 && rx_packet.numlowconf >= 10) {continue;}
|
||||
|
||||
rx_packet.crc = modes_check_crc(rx_packet.data, (packet_length/8)-3);
|
||||
unsigned int ap = rx_packet.data[packet_length/8-3] << 16
|
||||
| rx_packet.data[packet_length/8-2] << 8
|
||||
| rx_packet.data[packet_length/8-1] << 0;
|
||||
rx_packet.crc ^= ap;
|
||||
rx_packet.crc = modes_check_crc(rx_packet.data, packet_length);
|
||||
|
||||
//crc for packets that aren't type 11 or type 17 is encoded with the transponder ID, which we don't know
|
||||
//therefore we toss 'em if there's syndrome
|
||||
|
||||
210
lib/uplink_impl.cc
Normal file
210
lib/uplink_impl.cc
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
# 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.
|
||||
#
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <gnuradio/tags.h>
|
||||
#include "uplink_impl.h"
|
||||
|
||||
namespace gr {
|
||||
|
||||
air_modes::uplink::sptr air_modes::uplink::make(int channel_rate, float threshold_db, gr::msg_queue::sptr queue) {
|
||||
return gnuradio::get_initial_sptr(new air_modes::uplink_impl(channel_rate, threshold_db, queue));
|
||||
}
|
||||
|
||||
air_modes::uplink_impl::uplink_impl(int channel_rate, float threshold_db, gr::msg_queue::sptr queue) :
|
||||
gr::block ("uplink",
|
||||
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
|
||||
{
|
||||
d_chip_rate = 4000000;
|
||||
set_rate(channel_rate);
|
||||
set_threshold(threshold_db);
|
||||
|
||||
std::stringstream str;
|
||||
str << name() << unique_id();
|
||||
d_me = pmt::string_to_symbol(str.str());
|
||||
d_key = pmt::string_to_symbol("uplink_found");
|
||||
d_queue = queue;
|
||||
}
|
||||
|
||||
void air_modes::uplink_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);
|
||||
}
|
||||
|
||||
void air_modes::uplink_impl::set_threshold(float threshold_db) {
|
||||
d_threshold_db = threshold_db;
|
||||
d_threshold = powf(10., threshold_db/20.);
|
||||
}
|
||||
|
||||
float air_modes::uplink_impl::get_threshold(void) {
|
||||
return d_threshold_db;
|
||||
}
|
||||
|
||||
int air_modes::uplink_impl::get_rate(void) {
|
||||
return d_samples_per_chip * d_chip_rate;
|
||||
}
|
||||
|
||||
//todo: make it return a pair of some kind, otherwise you can lose precision
|
||||
static double tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, double secs_per_sample) {
|
||||
uint64_t ts_sample, last_whole_stamp;
|
||||
double last_frac_stamp;
|
||||
|
||||
if(tstamp.key == NULL || pmt::symbol_to_string(tstamp.key) != "rx_time") return 0;
|
||||
|
||||
last_whole_stamp = pmt::to_uint64(pmt::tuple_ref(tstamp.value, 0));
|
||||
last_frac_stamp = pmt::to_double(pmt::tuple_ref(tstamp.value, 1));
|
||||
ts_sample = tstamp.offset;
|
||||
|
||||
double tstime = double(abs_sample_cnt * secs_per_sample) + last_whole_stamp + last_frac_stamp;
|
||||
if(0) std::cout << "HEY WE GOT A STAMP AT " << tstime << " TICKS AT SAMPLE " << ts_sample << " ABS SAMPLE CNT IS " << abs_sample_cnt << std::endl;
|
||||
return tstime;
|
||||
}
|
||||
|
||||
//the preamble pattern in bits
|
||||
//fixme goes in .h
|
||||
//these are in 0.25us increments
|
||||
static const int preamble_bits[] = {1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, -1};
|
||||
static double correlate_preamble(const float *in, int samples_per_chip) {
|
||||
double corr = 0.0;
|
||||
for(int i=0; i<20; i++) {
|
||||
for(int j=0; j<samples_per_chip;j++)
|
||||
corr += preamble_bits[i]*in[i*samples_per_chip+j];
|
||||
}
|
||||
return corr/(20*samples_per_chip);
|
||||
}
|
||||
|
||||
int air_modes::uplink_impl::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];
|
||||
const float *inavg = (const float *) input_items[1];
|
||||
|
||||
int mininputs = std::min(ninput_items[0], ninput_items[1]); //they should be matched but let's be safe
|
||||
//round number of input samples down to nearest d_samples_per_chip
|
||||
//we also subtract off d_samples_per_chip to allow the bit center finder some leeway
|
||||
const int ninputs = std::max(mininputs - (mininputs % d_samples_per_symbol) - d_samples_per_symbol, 0);
|
||||
if (ninputs <= 0) { consume_each(0); return 0; }
|
||||
|
||||
float *out = (float *) output_items[0];
|
||||
|
||||
if(0) std::cout << "Uplink called with " << ninputs << " samples" << std::endl;
|
||||
|
||||
uint64_t abs_sample_cnt = nitems_read(0);
|
||||
std::vector<gr::tag_t> tstamp_tags;
|
||||
get_tags_in_range(tstamp_tags, 0, abs_sample_cnt, abs_sample_cnt + ninputs, pmt::string_to_symbol("rx_time"));
|
||||
//tags.back() is the most recent timestamp, then.
|
||||
if(tstamp_tags.size() > 0) {
|
||||
d_timestamp = tstamp_tags.back();
|
||||
}
|
||||
|
||||
for(int i=0; i < ninputs; i++) {
|
||||
float pulse_threshold = inavg[i] * d_threshold;
|
||||
//we're looking for negative pulses, since the sync
|
||||
//phase reversal bit will always be negative.
|
||||
if(in[i] < (0-fabs(pulse_threshold))) { //hey we got a candidate
|
||||
if(0) std::cout << "Pulse threshold " << (0-fabs(pulse_threshold)) << " exceeded by sample at " << in[i] << std::endl;
|
||||
|
||||
while(in[i+1] < in[i] and (ninputs-112*d_samples_per_symbol) > i) i++;
|
||||
bool ugly = false;
|
||||
for(int j=0; j<8*d_samples_per_symbol; j++) {
|
||||
if(in[i+j+d_samples_per_symbol] < fabs(pulse_threshold)) ugly=true;
|
||||
}
|
||||
if(ugly) continue;
|
||||
if(0) std::cout << "Phase reversal sync found at " << i << " with value " << in[i] << std::endl;
|
||||
//now we're at the phase reversal sync bit, and we can start pulling bits out
|
||||
//next bit starts 0.5us later (2 bit periods)
|
||||
float ref_level = 0;
|
||||
for(int j=0; j<d_samples_per_symbol*2; j++) {
|
||||
ref_level += in[i+j];
|
||||
}
|
||||
ref_level /= (d_samples_per_symbol*2);
|
||||
|
||||
i+=d_samples_per_symbol*2;
|
||||
|
||||
|
||||
//be sure we've got enough room in the input buffer to copy out a whole packet
|
||||
if(ninputs-i < 112*d_samples_per_symbol) {
|
||||
consume_each(std::max(i-1,0));
|
||||
if(0) std::cout << "Uplink consumed " << std::max(i-1,0) << ", returned 0 (no room)" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int j=0; j<ninputs; j++) {
|
||||
out[j] = in[j];
|
||||
}
|
||||
out[i] = 1;
|
||||
|
||||
unsigned char bits[14];
|
||||
memset((void *) bits, 0x00, 14);
|
||||
for(int j=0; j<56; j++) {
|
||||
if(in[i+j*d_samples_per_symbol] < 0) bits[j/8] += 1 << (7-(j%8));
|
||||
}
|
||||
if(0) {
|
||||
std::cout << "Data: ";
|
||||
for(int j=0; j<7; j++) {
|
||||
std::cout << std::setw(2) << std::setfill('0') << std::hex << int(bits[j]);
|
||||
}
|
||||
std::cout << std::dec << std::endl;
|
||||
}
|
||||
|
||||
//get the timestamp of the uplink tag
|
||||
double tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_secs_per_sample);
|
||||
|
||||
d_payload.str("");
|
||||
for(int m=0; m<7; m++) {
|
||||
d_payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(bits[m]);
|
||||
}
|
||||
|
||||
d_payload << " " << std::setw(6) << 0 << " " << std::dec << ref_level
|
||||
<< " " << std::setprecision(10) << std::setw(10) << tstamp;
|
||||
gr::message::sptr msg = gr::message::make_from_string(std::string(d_payload.str()));
|
||||
d_queue->handle(msg);
|
||||
|
||||
//produce only one output per work call -- TODO this should probably change
|
||||
if(0) std::cout << "Uplink consumed " << i+112*d_samples_per_symbol << " with i=" << i << ", returned 112" << std::endl;
|
||||
|
||||
consume_each(ninputs);
|
||||
return ninputs;
|
||||
}
|
||||
}
|
||||
|
||||
//didn't get anything this time
|
||||
//if(1) std::cout << "Uplink consumed " << ninputs << ", returned 0" << std::endl;
|
||||
consume_each(ninputs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} //namespace gr
|
||||
46
lib/uplink_impl.h
Normal file
46
lib/uplink_impl.h
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
#ifndef _AIR_MODES_UPLINK_IMPL_H_
|
||||
#define _AIR_MODES_UPLINK_IMPL_H_
|
||||
|
||||
#include <gnuradio/block.h>
|
||||
#include <gr_air_modes/api.h>
|
||||
#include <gr_air_modes/uplink.h>
|
||||
#include <gnuradio/msg_queue.h>
|
||||
|
||||
namespace gr {
|
||||
namespace air_modes {
|
||||
|
||||
class AIR_MODES_API uplink_impl : public uplink
|
||||
{
|
||||
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;
|
||||
gr::msg_queue::sptr d_queue;
|
||||
std::ostringstream d_payload;
|
||||
|
||||
public:
|
||||
uplink_impl(int channel_rate, float threshold_db, gr::msg_queue::sptr queue);
|
||||
|
||||
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_UPLINK_IMPL_H_
|
||||
@@ -51,7 +51,7 @@ from air_modes_swig import *
|
||||
|
||||
# import any pure python here
|
||||
#
|
||||
from rx_path import rx_path
|
||||
from rx_path import rx_path, uplink_rx_path
|
||||
from zmq_socket import zmq_pubsub_iface
|
||||
from parse import *
|
||||
from msprint import output_print
|
||||
|
||||
@@ -33,7 +33,6 @@ import zmq
|
||||
import threading
|
||||
import time
|
||||
import re
|
||||
import fractions
|
||||
|
||||
class modes_radio (gr.top_block, pubsub):
|
||||
def __init__(self, options, context):
|
||||
@@ -45,8 +44,6 @@ class modes_radio (gr.top_block, pubsub):
|
||||
|
||||
self._resample = None
|
||||
self._setup_source(options)
|
||||
if self._resample is not None:
|
||||
self._rate = 4.0e6 #fixed rate we resample to in RTL case
|
||||
|
||||
self._rx_path = air_modes.rx_path(self._rate, options.threshold,
|
||||
self._queue, options.pmf, options.dcblock)
|
||||
@@ -84,7 +81,7 @@ class modes_radio (gr.top_block, pubsub):
|
||||
@staticmethod
|
||||
def add_radio_options(parser):
|
||||
group = OptionGroup(parser, "Receiver setup options")
|
||||
|
||||
|
||||
#Choose source
|
||||
group.add_option("-s","--source", type="string", default="uhd",
|
||||
help="Choose source: uhd, osmocom, <filename>, or <ip:port> [default=%default]")
|
||||
@@ -175,14 +172,13 @@ class modes_radio (gr.top_block, pubsub):
|
||||
self._u.set_gain(options.gain)
|
||||
print "Gain is %i" % self._u.get_gain()
|
||||
|
||||
#TODO: detect if you're using an RTLSDR or Jawbreaker
|
||||
#and set up accordingly.
|
||||
elif options.source == "osmocom": #RTLSDR dongle or HackRF Jawbreaker
|
||||
import osmosdr
|
||||
self._u = osmosdr.source(options.args)
|
||||
rates = self._u.get_sample_rates()
|
||||
|
||||
# self._u.set_sample_rate(3.2e6) #fixed for RTL dongles
|
||||
self._u.set_sample_rate(options.rate)
|
||||
actual_rate = int(self._u.get_sample_rate())
|
||||
|
||||
if not self._u.set_center_freq(options.freq):
|
||||
print "Failed to set initial frequency"
|
||||
|
||||
@@ -192,14 +188,9 @@ class modes_radio (gr.top_block, pubsub):
|
||||
self._u.set_gain(options.gain)
|
||||
print "Gain is %i" % self._u.get_gain()
|
||||
|
||||
if actual_rate < 4.0e6:
|
||||
gcd = fractions.gcd(4.0e6, actual_rate)
|
||||
interp = 4.0e6 / gcd
|
||||
decim = actual_rate / gcd
|
||||
lpfiltcoeffs = filter.firdes.low_pass(1, interp*actual_rate, 1.6e6, 300e3)
|
||||
self._resample = filter.rational_resampler_ccf(interpolation=interp,
|
||||
decimation=decim,
|
||||
taps=lpfiltcoeffs)
|
||||
#Note: this should only come into play if using an RTLSDR.
|
||||
# lpfiltcoeffs = gr.firdes.low_pass(1, 5*3.2e6, 1.6e6, 300e3)
|
||||
# self._resample = filter.rational_resampler_ccf(interpolation=5, decimation=4, taps=lpfiltcoeffs)
|
||||
|
||||
else:
|
||||
#semantically detect whether it's ip.ip.ip.ip:port or filename
|
||||
@@ -214,7 +205,7 @@ class modes_radio (gr.top_block, pubsub):
|
||||
self._u = blocks.file_source(gr.sizeof_gr_complex, options.source)
|
||||
print "Using file source %s" % options.source
|
||||
|
||||
print "Rate is %i" % actual_rate
|
||||
print "Rate is %i" % (options.rate,)
|
||||
|
||||
def close(self):
|
||||
self._sender.close()
|
||||
|
||||
@@ -86,3 +86,46 @@ class rx_path(gr.hier_block2):
|
||||
def get_threshold(self, threshold):
|
||||
return self._sync.get_threshold()
|
||||
|
||||
class uplink_rx_path(gr.hier_block2):
|
||||
def __init__(self, rate, threshold, queue, use_pmf=False, use_dcblock=False):
|
||||
gr.hier_block2.__init__(self, "modes_uplink_rx_path",
|
||||
gr.io_signature(1, 1, gr.sizeof_gr_complex),
|
||||
gr.io_signature(0,0,0))
|
||||
|
||||
self._rate = int(rate)
|
||||
self._threshold = threshold
|
||||
self._queue = queue
|
||||
self._spc = int(rate/4e6)
|
||||
|
||||
#demodulate DPSK via delay
|
||||
self._delay = gr.delay(gr.sizeof_gr_complex, self._spc)
|
||||
self._mult = gr.multiply_cc()
|
||||
self._conj = gr.conjugate_cc()
|
||||
self._c2r = gr.complex_to_real()
|
||||
#self._bb = self._demod
|
||||
|
||||
self.filesink = gr.file_sink(gr.sizeof_float, "wat.dat")
|
||||
|
||||
# Pulse matched filter for 0.25us pulses
|
||||
# if use_pmf:
|
||||
# self._pmf = gr.moving_average_ff(self._spc, 1.0/self._spc, self._rate)
|
||||
# self.connect(self._demod, self._pmf)
|
||||
# self._bb = self._pmf
|
||||
|
||||
# Establish baseline amplitude (noise, interference)
|
||||
self._avg = gr.moving_average_ff(48*self._spc, 1.0/(48*self._spc), self._rate) # 3 preambles
|
||||
|
||||
# Synchronize to uplink preamble
|
||||
self._sync = air_modes_swig.modes_uplink(self._rate, self._threshold)
|
||||
|
||||
# Slice Mode-S bits and send to message queue
|
||||
# self._slicer = air_modes_swig.modes_slicer(self._rate, self._queue)
|
||||
|
||||
# Wire up the flowgraph
|
||||
self.connect(self, (self._mult, 0))
|
||||
self.connect(self, self._delay, self._conj, (self._mult, 1))
|
||||
self.connect(self._mult, self._c2r)
|
||||
self.connect(self._c2r, (self._sync, 0))
|
||||
self.connect(self._c2r, self._avg, (self._sync, 1))
|
||||
# self.connect(self._sync, self._slicer)
|
||||
self.connect(self._sync, self.filesink)
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
%{
|
||||
#include "gr_air_modes/preamble.h"
|
||||
#include "gr_air_modes/slicer.h"
|
||||
#include "gr_air_modes/uplink.h"
|
||||
%}
|
||||
|
||||
%include "gr_air_modes/preamble.h"
|
||||
%include "gr_air_modes/slicer.h"
|
||||
%include "gr_air_modes/uplink.h"
|
||||
|
||||
GR_SWIG_BLOCK_MAGIC2(air_modes,preamble);
|
||||
GR_SWIG_BLOCK_MAGIC2(air_modes,slicer);
|
||||
GR_SWIG_BLOCK_MAGIC2(air_modes,uplink);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user