diff --git a/include/air_modes_slicer.h b/include/air_modes_slicer.h index eb9e6a6..eb3f72b 100644 --- a/include/air_modes_slicer.h +++ b/include/air_modes_slicer.h @@ -47,7 +47,8 @@ private: int d_samples_per_chip; int d_samples_per_symbol; gr_msg_queue_sptr d_queue; - std::ostringstream d_payload; + unsigned char d_lowconfbits[24]; + unsigned char d_data[14]; public: int work (int noutput_items, diff --git a/include/air_modes_types.h b/include/air_modes_types.h index 9a80ffd..faee932 100644 --- a/include/air_modes_types.h +++ b/include/air_modes_types.h @@ -24,20 +24,6 @@ #define AIR_MODES_TYPES_H typedef enum { No_Packet = 0, Short_Packet = 1, Fruited_Packet = 2, Long_Packet = 3 } framer_packet_type; -typedef enum { No_Error = 0, Solution_Found, Too_Many_LCBs, No_Solution, Multiple_Solutions } bruteResultTypeDef; - -struct modes_packet { - unsigned char data[14]; -// unsigned char confidence[14]; //112 bits of boolean high/low confidence data for each bit - unsigned char lowconfbits[24]; //positions of low confidence bits within the packet - - unsigned long crc; - unsigned int numlowconf; - framer_packet_type type; //what length packet are we - unsigned int message_type; - float reference_level; - double timestamp; -}; struct slice_result_t { bool decision; diff --git a/include/modes_crc.h b/include/modes_crc.h index 1d6a230..555c770 100644 --- a/include/modes_crc.h +++ b/include/modes_crc.h @@ -24,7 +24,4 @@ #define INCLUDED_MODES_CRC_H extern const unsigned int modes_crc_table[112]; 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); - #endif diff --git a/lib/air_modes_preamble.cc b/lib/air_modes_preamble.cc index deab73b..533bc90 100644 --- a/lib/air_modes_preamble.cc +++ b/lib/air_modes_preamble.cc @@ -78,20 +78,31 @@ 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) { +//takes an rx tag and issues a tag offset appropriately for the preamble +static const pmt::pmt_t offset_stamp(const gr_tag_t &tstamp, const uint64_t abs_sample_cnt, const double secs_per_sample) { uint64_t ts_sample, last_whole_stamp; double last_frac_stamp; - if(tstamp.key == NULL || pmt::pmt_symbol_to_string(tstamp.key) != "rx_time") return 0; - - last_whole_stamp = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(tstamp.value, 0)); - last_frac_stamp = pmt::pmt_to_double(pmt::pmt_tuple_ref(tstamp.value, 1)); - ts_sample = tstamp.offset; + if(tstamp.key == NULL || pmt::pmt_symbol_to_string(tstamp.key) != "rx_time") { + last_whole_stamp = 0; + last_frac_stamp = 0; + ts_sample = 0; + } else { + last_whole_stamp = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(tstamp.value, 0)); + last_frac_stamp = pmt::pmt_to_double(pmt::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; + double fractime = double(abs_sample_cnt * secs_per_sample) + last_frac_stamp; + last_whole_stamp += int(fractime); + fractime -= int(fractime); + + const pmt::pmt_t newval = pmt::pmt_make_tuple( + pmt::pmt_from_uint64(last_whole_stamp), + pmt::pmt_from_double(fractime) + ); + + return newval; } int air_modes_preamble::general_work(int noutput_items, @@ -186,16 +197,14 @@ int air_modes_preamble::general_work(int noutput_items, integrate_and_dump(out, &in[i], 240, d_samples_per_chip); } - //get the timestamp of the preamble - double tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_secs_per_sample); - + const pmt::pmt_t new_pmt = offset_stamp(d_timestamp, abs_sample_cnt + i, d_secs_per_sample); //now tag the preamble add_item_tag(0, //stream ID - nitems_written(0), //sample - d_key, //frame_info - pmt::pmt_from_double(tstamp), - d_me //block src id - ); + nitems_written(0), //sample + d_key, //frame_info + new_pmt, + d_me //block src id + ); //std::cout << "PREAMBLE" << std::endl; diff --git a/lib/air_modes_slicer.cc b/lib/air_modes_slicer.cc index 9c0bb7f..2b95e98 100644 --- a/lib/air_modes_slicer.cc +++ b/lib/air_modes_slicer.cc @@ -112,84 +112,80 @@ int air_modes_slicer::work(int noutput_items, for(tag_iter = tags.begin(); tag_iter != tags.end(); tag_iter++) { uint64_t i = tag_iter->offset - abs_sample_cnt; - modes_packet rx_packet; - memset(&rx_packet.data, 0x00, 14 * sizeof(unsigned char)); - memset(&rx_packet.lowconfbits, 0x00, 24 * sizeof(unsigned char)); - rx_packet.numlowconf = 0; + memset(&d_data, 0x00, 14 * sizeof(unsigned char)); + memset(&d_lowconfbits, 0x00, 24 * sizeof(unsigned char)); + unsigned int numlowconf = 0; //let's use the preamble to get a reference level for the packet //fixme: a better thing to do is create a bi-level avg 1 and avg 0 //through simple statistics, then take the median for your slice level //this won't improve decoding but will improve confidence - rx_packet.reference_level = (in[i] - + in[i+2] - + in[i+7] - + in[i+9]) / 4.0; + double reference_level = (in[i] + + in[i+2] + + in[i+7] + + in[i+9]) / 4.0; i += 16; //move on up to the first bit of the packet data //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 = slicer(in[i+j*2], in[i+j*2+1], 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; - else rx_packet.type = Short_Packet; - int packet_length = (rx_packet.type == framer_packet_type(Short_Packet)) ? 56 : 112; + framer_packet_type type; + if(pkt_hdr == 16 or pkt_hdr == 17 or pkt_hdr == 20 or pkt_hdr == 21) type = Long_Packet; + else type = Short_Packet; + int packet_length = (type == Short_Packet) ? 56 : 112; //it's slice time! //TODO: don't repeat your work here, you already have the first 5 bits + slice_result_t slice_result; 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 = slicer(in[i+j*2], in[i+j*2+1], reference_level); //put the data into the packet if(slice_result.decision) { - rx_packet.data[j/8] += 1 << (7-(j%8)); + d_data[j/8] += 1 << (7-(j%8)); } //put the confidence decision into the packet if(slice_result.confidence) { - //rx_packet.confidence[j/8] += 1 << (7-(j%8)); + //d_confidence[j/8] += 1 << (7-(j%8)); } else { - if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j; + if(numlowconf < 24) d_lowconfbits[numlowconf++] = j; } } - - /******************** BEGIN TIMESTAMP BS ******************/ - rx_packet.timestamp = pmt_to_double(tag_iter->value); - /******************* END TIMESTAMP BS *********************/ - - //increment for the next round + + uint64_t timestamp_secs = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(tag_iter->value, 0)); + double timestamp_frac = pmt::pmt_to_double(pmt::pmt_tuple_ref(tag_iter->value, 1)); //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; for(int m = 0; m < 14; m++) { - if(rx_packet.data[m]) zeroes = 0; + if(d_data[m]) zeroes = 0; } if(zeroes) {continue;} //toss it - rx_packet.message_type = (rx_packet.data[0] >> 3) & 0x1F; //get the message type to make decisions on ECC methods + unsigned int message_type = (d_data[0] >> 3) & 0x1F; //get the message type to make decisions on ECC methods - 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;} + if(type == Short_Packet && message_type != 11 && numlowconf > 0) {continue;} + if(message_type == 11 && numlowconf >= 10) {continue;} - rx_packet.crc = modes_check_crc(rx_packet.data, packet_length); + unsigned long crc = modes_check_crc(d_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 //crc for the other short packets is usually nonzero, so they can't really be trusted that far - if(rx_packet.crc && (rx_packet.message_type == 11 || rx_packet.message_type == 17)) {continue;} - - d_payload.str(""); + if(crc && (message_type == 11 || message_type == 17)) {continue;} + std::ostringstream payload; for(int m = 0; m < packet_length/8; m++) { - d_payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]); + payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(d_data[m]); } - d_payload << " " << std::setw(6) << rx_packet.crc << " " << std::dec << rx_packet.reference_level - << " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp; - gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str())); + payload << " " << std::setw(6) << crc << " " << std::dec << reference_level + << " " << timestamp_secs << " " << std::setprecision(20) << timestamp_frac; + gr_message_sptr msg = gr_make_message_from_string(std::string(payload.str())); d_queue->handle(msg); } - if(0) std::cout << "Slicer consumed " << size << ", returned " << size << std::endl; return size; } diff --git a/python/flightgear.py b/python/flightgear.py index b28c3c6..548e76e 100755 --- a/python/flightgear.py +++ b/python/flightgear.py @@ -28,7 +28,8 @@ class output_flightgear(air_modes.parse): self.sock.connect((self.hostname, self.port)) def output(self, message): - [data, ecc, reference, timestamp] = message.split() + [data, ecc, reference, timestamp_int, timestamp_frac] = message.split() + timestamp = int(timestamp_int) + float(timestamp_frac) data = air_modes.modes_reply(long(data, 16)) try: diff --git a/python/msprint.py b/python/msprint.py index bf54217..d43f8f2 100644 --- a/python/msprint.py +++ b/python/msprint.py @@ -30,11 +30,11 @@ class output_print(air_modes.parse): air_modes.parse.__init__(self, mypos) def parse(self, message): - [data, ecc, reference, timestamp] = message.split() + [data, ecc, reference, timestamp_int, timestamp_frac] = message.split() + timestamp = int(timestamp_int) + float(timestamp_frac) ecc = long(ecc, 16) reference = float(reference) - timestamp = float(timestamp) if reference == 0.0: refdb = -150.0 diff --git a/python/sbs1.py b/python/sbs1.py index cfdd89d..0015970 100644 --- a/python/sbs1.py +++ b/python/sbs1.py @@ -103,7 +103,8 @@ class output_sbs1(air_modes.parse): def parse(self, message): #assembles a SBS-1-style output string from the received message - [data, ecc, reference, timestamp] = message.split() + [data, ecc, reference, timestamp_int, timestamp_frac] = message.split() + timestamp = int(timestamp_int) + float(timestamp_frac) data = air_modes.modes_reply(long(data, 16)) ecc = long(ecc, 16) diff --git a/python/sql.py b/python/sql.py index 585e35d..6b0aeb2 100644 --- a/python/sql.py +++ b/python/sql.py @@ -89,7 +89,8 @@ class output_sql(air_modes.parse): def make_insert_query(self, message): #assembles a SQL query tailored to our database #this version ignores anything that isn't Type 17 for now, because we just don't care - [data, ecc, reference, timestamp] = message.split() + [data, ecc, reference, timestamp_int, timestamp_frac] = message.split() + timestamp = int(timestamp_int) + float(timestamp_frac) data = air_modes.modes_reply(long(data, 16)) ecc = long(ecc, 16)