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

@@ -23,8 +23,8 @@
include(GrPlatform) #define LIB_SUFFIX
add_library(air_modes SHARED
air_modes_preamble.cc
air_modes_slicer.cc
preamble_impl.cc
slicer_impl.cc
modes_crc.cc
)
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
#include <stdio.h>
#include <air_modes_types.h>
#include <modes_crc.h>
#include <gr_air_modes/types.h>
#include <gr_air_modes/modes_crc.h>
#include <math.h>
#include <stdlib.h>

View File

@@ -26,38 +26,55 @@
#endif
#include <ciso646>
#include <air_modes_preamble.h>
#include "preamble_impl.h"
#include <gnuradio/io_signature.h>
#include <string.h>
#include <iostream>
#include <gnuradio/tags.h>
air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshold_db)
{
return air_modes_preamble_sptr (new air_modes_preamble(channel_rate, threshold_db));
namespace gr {
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) :
gr::block ("modes_preamble",
air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) :
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::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_samples_per_chip = channel_rate / d_chip_rate; //must be integer number of samples per chip to work
d_samples_per_symbol = d_samples_per_chip * 2;
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);
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("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);
}
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) {
for(int i=0; i<chips; i++) {
float acc = 0;
@@ -90,13 +107,13 @@ static double tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, double
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;
}
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_const_void_star &input_items,
gr_vector_void_star &output_items)
@@ -109,7 +126,7 @@ int air_modes_preamble::general_work(int noutput_items,
//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_chip) - d_samples_per_chip, 0);
if (ninputs <= 0) { consume_each(0); return 0; }
float *out = (float *) output_items[0];
if(0) std::cout << "Preamble called with " << ninputs << " samples" << std::endl;
@@ -206,3 +223,5 @@ int air_modes_preamble::general_work(int noutput_items,
consume_each(ninputs);
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
#include <ciso646>
#include <air_modes_slicer.h>
#include "slicer_impl.h"
#include <gnuradio/io_signature.h>
#include <air_modes_types.h>
#include <gr_air_modes/types.h>
#include <sstream>
#include <iomanip>
#include <modes_crc.h>
#include <gr_air_modes/modes_crc.h>
#include <iostream>
#include <gnuradio/tags.h>
@@ -41,14 +41,15 @@ extern "C"
#include <string.h>
}
air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr::msg_queue::sptr queue)
{
return air_modes_slicer_sptr (new air_modes_slicer(channel_rate, queue));
namespace gr {
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) :
gr::sync_block ("modes_slicer",
gr::io_signature::make (1, 1, sizeof(float)), //stream 0 is received data, stream 1 is binary preamble detector output
air_modes::slicer_impl::slicer_impl(gr::msg_queue::sptr queue) :
gr::sync_block ("slicer",
gr::io_signature::make (1, 1, sizeof(float)),
gr::io_signature::make (0, 0, 0) )
{
//initialize private data here
@@ -63,13 +64,13 @@ 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.
//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;
//3dB limits for bit slicing and confidence measurement
float highlimit=ref*1.414;
float lowlimit=ref*0.707;
bool firstchip_inref = ((bit0 > lowlimit) && (bit0 < highlimit));
bool secondchip_inref = ((bit1 > lowlimit) && (bit1 < highlimit));
@@ -98,7 +99,7 @@ static slice_result_t slicer(const float bit0, const float bit1, const float ref
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_void_star &output_items)
{
@@ -106,7 +107,7 @@ int air_modes_slicer::work(int noutput_items,
int size = noutput_items - d_check_width; //since it's a sync block, i assume that it runs with ninput_items = noutput_items
if(0) std::cout << "Slicer called with " << size << " samples" << std::endl;
std::vector<gr::tag_t> tags;
uint64_t abs_sample_cnt = nitems_read(0);
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::string_to_symbol("preamble_found"));
@@ -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
unsigned char pkt_hdr = 0;
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(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!
//TODO: don't repeat your work here, you already have the first 5 bits
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
if(slice_result.decision) {
@@ -156,12 +157,8 @@ int air_modes_slicer::work(int noutput_items,
if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j;
}
}
/******************** BEGIN TIMESTAMP BS ******************/
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.
bool zeroes = 1;
@@ -174,7 +171,7 @@ int air_modes_slicer::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);
//crc for packets that aren't type 11 or type 17 is encoded with the transponder ID, which we don't know
@@ -195,3 +192,5 @@ int air_modes_slicer::work(int noutput_items,
if(0) std::cout << "Slicer consumed " << size << ", returned " << size << std::endl;
return size;
}
} //namespace gr

55
lib/slicer_impl.h Normal file
View File

@@ -0,0 +1,55 @@
/*
# 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_IMPL_H
#define INCLUDED_AIR_MODES_SLICER_IMPL_H
#include <gnuradio/sync_block.h>
#include <gnuradio/msg_queue.h>
#include <gr_air_modes/api.h>
#include <gr_air_modes/slicer.h>
namespace gr {
namespace air_modes {
class AIR_MODES_API slicer_impl : public slicer
{
private:
int d_check_width;
int d_chip_rate;
int d_samples_per_chip;
int d_samples_per_symbol;
gr::msg_queue::sptr d_queue;
std::ostringstream d_payload;
public:
slicer_impl(gr::msg_queue::sptr queue);
int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} //namespace air_modes
} //namespace gr
#endif /* INCLUDED_AIR_MODES_SLICER_IMPL_H */