|
|
|
@ -34,11 +34,11 @@
|
|
|
|
|
|
|
|
|
|
namespace gr {
|
|
|
|
|
|
|
|
|
|
air_modes::preamble::sptr air_modes::preamble::make(int channel_rate, float threshold_db) {
|
|
|
|
|
air_modes::preamble::sptr air_modes::preamble::make(float channel_rate, float threshold_db) {
|
|
|
|
|
return gnuradio::get_initial_sptr(new air_modes::preamble_impl(channel_rate, threshold_db));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) :
|
|
|
|
|
air_modes::preamble_impl::preamble_impl(float 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 soft symbols
|
|
|
|
@ -53,11 +53,11 @@ air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) :
|
|
|
|
|
d_key = pmt::string_to_symbol("preamble_found");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void air_modes::preamble_impl::set_rate(int channel_rate) {
|
|
|
|
|
void air_modes::preamble_impl::set_rate(float 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;
|
|
|
|
|
d_sample_rate = channel_rate;
|
|
|
|
|
set_output_multiple(1+d_check_width*2);
|
|
|
|
|
set_history(d_samples_per_symbol);
|
|
|
|
|
}
|
|
|
|
@ -71,8 +71,8 @@ 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;
|
|
|
|
|
float air_modes::preamble_impl::get_rate(void) {
|
|
|
|
|
return d_sample_rate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void integrate_and_dump(float *out, const float *in, int chips, int samps_per_chip) {
|
|
|
|
@ -97,19 +97,34 @@ static double correlate_preamble(const float *in, int samples_per_chip) {
|
|
|
|
|
return corr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//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;
|
|
|
|
|
|
|
|
|
|
static pmt::pmt_t tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, int rate) {
|
|
|
|
|
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;
|
|
|
|
|
//the timestamp tag has tstamp.offset, the sample index of the timestamp tag
|
|
|
|
|
//also tstamp.value, a pmt pair with (uint64, double) representing int and
|
|
|
|
|
//fractional timestamp, respectively.
|
|
|
|
|
//this function also gets an abs_sample_cnt which represents the sample count to
|
|
|
|
|
//find a timestamp for. sps is obviously samples per second.
|
|
|
|
|
//
|
|
|
|
|
//so (abs_sample_cnt - tstamp.offset) is the delay we apply to the tag
|
|
|
|
|
// int((abs_sample_cnt - tstamp.offset)/sps) is the integer offset
|
|
|
|
|
// (abs_sample_cnt - tstamp.offset)/sps is the fractional offset
|
|
|
|
|
|
|
|
|
|
uint64_t last_whole_stamp = pmt::to_uint64(pmt::tuple_ref(tstamp.value, 0));
|
|
|
|
|
double last_frac_stamp = pmt::to_double(pmt::tuple_ref(tstamp.value, 1));
|
|
|
|
|
std::cout << "Rate: " << rate << std::endl;
|
|
|
|
|
uint64_t int_offset = int(abs_sample_cnt - tstamp.offset)/rate;
|
|
|
|
|
double frac_offset = ((abs_sample_cnt - tstamp.offset) % rate) / double(rate);
|
|
|
|
|
|
|
|
|
|
uint64_t abs_whole = last_whole_stamp + int_offset;
|
|
|
|
|
double abs_frac = last_frac_stamp + frac_offset;
|
|
|
|
|
if(abs_frac > 1.0f) {
|
|
|
|
|
abs_frac -= 1.0f;
|
|
|
|
|
abs_whole += 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pmt::pmt_t tstime = pmt::make_tuple(pmt::from_uint64(abs_whole), pmt::from_double(abs_frac));
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -124,7 +139,7 @@ int air_modes::preamble_impl::general_work(int noutput_items,
|
|
|
|
|
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_chip) - d_samples_per_chip, 0);
|
|
|
|
|
const int ninputs = std::max(mininputs - (mininputs % int(d_samples_per_chip)) - int(d_samples_per_chip), 0);
|
|
|
|
|
if (ninputs <= 0) { consume_each(0); return 0; }
|
|
|
|
|
|
|
|
|
|
float *out = (float *) output_items[0];
|
|
|
|
@ -194,22 +209,20 @@ int air_modes::preamble_impl::general_work(int noutput_items,
|
|
|
|
|
|
|
|
|
|
//all right i'm prepared to call this a preamble
|
|
|
|
|
for(int j=0; j<240; j++) {
|
|
|
|
|
out[j] = in[i+j*d_samples_per_chip] - inavg[i];
|
|
|
|
|
out[j] = in[i+int(j*d_samples_per_chip)] - inavg[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//get the timestamp of the preamble
|
|
|
|
|
double tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_secs_per_sample);
|
|
|
|
|
pmt::pmt_t tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_sample_rate);
|
|
|
|
|
|
|
|
|
|
//now tag the preamble
|
|
|
|
|
add_item_tag(0, //stream ID
|
|
|
|
|
nitems_written(0), //sample
|
|
|
|
|
d_key, //frame_info
|
|
|
|
|
pmt::from_double(tstamp),
|
|
|
|
|
tstamp,
|
|
|
|
|
d_me //block src id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//std::cout << "PREAMBLE" << std::endl;
|
|
|
|
|
|
|
|
|
|
//produce only one output per work call -- TODO this should probably change
|
|
|
|
|
if(0) std::cout << "Preamble consumed " << i+240*d_samples_per_chip << "with i=" << i << ", returned 240" << std::endl;
|
|
|
|
|
|
|
|
|
|