diff --git a/apps/lora_receive_file.py b/apps/lora_receive_file.py index 810eb7b..bc54d1e 100755 --- a/apps/lora_receive_file.py +++ b/apps/lora_receive_file.py @@ -3,7 +3,7 @@ ################################################## # GNU Radio Python Flow Graph # Title: Lora Receive File -# Generated: Thu Sep 7 15:38:03 2017 +# Generated: Wed Sep 20 10:10:43 2017 ################################################## if __name__ == '__main__': @@ -66,7 +66,7 @@ class lora_receive_file(grc_wxgui.top_block_gui): peak_hold=False, ) self.Add(self.wxgui_fftsink2_1.win) - self.lora_lora_receiver_0 = lora.lora_receiver(samp_rate, capture_freq, ([target_freq]), 7, 1000000, 0.002) + self.lora_lora_receiver_0 = lora.lora_receiver(samp_rate, capture_freq, ([target_freq]), 7, 1000000, False, 4, True) self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True) self.blocks_file_source_0 = blocks.file_source(gr.sizeof_gr_complex*1, 'counting_cr4_sf7.cfile', True) diff --git a/apps/lora_receive_realtime.py b/apps/lora_receive_realtime.py index 3fefa8c..f9afba5 100755 --- a/apps/lora_receive_realtime.py +++ b/apps/lora_receive_realtime.py @@ -3,7 +3,7 @@ ################################################## # GNU Radio Python Flow Graph # Title: Lora Receive Realtime -# Generated: Thu Sep 14 16:24:32 2017 +# Generated: Wed Sep 20 10:11:08 2017 ################################################## if __name__ == '__main__': @@ -81,7 +81,7 @@ class lora_receive_realtime(grc_wxgui.top_block_gui): self.osmosdr_source_0.set_bandwidth(0, 0) self.lora_message_socket_sink_0 = lora.message_socket_sink('127.0.0.1', 40868, False, True) - self.lora_lora_receiver_0 = lora.lora_receiver(samp_rate, capture_freq, ([target_freq]), sf, internal_sampling_rate, 0.002) + self.lora_lora_receiver_0 = lora.lora_receiver(samp_rate, capture_freq, ([target_freq]), sf, internal_sampling_rate, False, 4, True) ################################################## # Connections diff --git a/docs/test-results/decode_long_hackrf.md b/docs/test-results/decode_long_hackrf.md index d2e6b97..cb7b8ca 100644 --- a/docs/test-results/decode_long_hackrf.md +++ b/docs/test-results/decode_long_hackrf.md @@ -1,6 +1,6 @@ # Test suite: 'decode_long_hackrf' -*Results on 2017-09-15 11:28:32.183183* +*Results on 2017-09-20 07:54:45.563359* ### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off diff --git a/docs/test-results/decode_long_rtl-sdr.md b/docs/test-results/decode_long_rtl-sdr.md index afce559..c15f775 100644 --- a/docs/test-results/decode_long_rtl-sdr.md +++ b/docs/test-results/decode_long_rtl-sdr.md @@ -1,6 +1,6 @@ # Test suite: 'decode_long_rtl-sdr' -*Results on 2017-09-15 11:27:16.260766* +*Results on 2017-09-20 07:53:29.656650* ### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off diff --git a/docs/test-results/decode_long_usrp.md b/docs/test-results/decode_long_usrp.md index 164c773..9776b4d 100644 --- a/docs/test-results/decode_long_usrp.md +++ b/docs/test-results/decode_long_usrp.md @@ -1,6 +1,6 @@ # Test suite: 'decode_long_usrp' -*Results on 2017-09-15 11:27:52.849819* +*Results on 2017-09-20 07:54:06.220649* ### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off diff --git a/docs/test-results/short_hackrf.md b/docs/test-results/short_hackrf.md index dc1e35e..00ce432 100644 --- a/docs/test-results/short_hackrf.md +++ b/docs/test-results/short_hackrf.md @@ -1,6 +1,6 @@ # Test suite: 'short_hackrf' -*Results on 2017-09-15 11:37:48.801373* +*Results on 2017-09-20 08:04:02.415820* ### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off diff --git a/docs/test-results/short_rtl-sdr.md b/docs/test-results/short_rtl-sdr.md index cd6be43..72dd9e0 100644 --- a/docs/test-results/short_rtl-sdr.md +++ b/docs/test-results/short_rtl-sdr.md @@ -1,6 +1,6 @@ # Test suite: 'short_rtl-sdr' -*Results on 2017-09-15 11:29:09.534517* +*Results on 2017-09-20 07:55:22.913194* ### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off diff --git a/docs/test-results/short_usrp.md b/docs/test-results/short_usrp.md index 4d4e893..680771c 100644 --- a/docs/test-results/short_usrp.md +++ b/docs/test-results/short_usrp.md @@ -1,6 +1,6 @@ # Test suite: 'short_usrp' -*Results on 2017-09-15 11:33:12.759248* +*Results on 2017-09-20 07:59:26.311889* ### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off diff --git a/grc/lora_receiver.xml b/grc/lora_receiver.xml index 0b98210..77c7ccd 100644 --- a/grc/lora_receiver.xml +++ b/grc/lora_receiver.xml @@ -4,12 +4,11 @@ lora_lora_receiver [LoRa] import lora - lora.lora_receiver($in_samp_rate, $center_freq, $channel_list, $sf, $out_samp_rate, $threshold) + lora.lora_receiver($in_samp_rate, $center_freq, $channel_list, $sf, $out_samp_rate, $implicit, $cr, $crc) set_center_freq($freq) set_sf($sf) set_out_samp_rate($out_samp_rate) - set_threshold($threshold) Sample rate @@ -39,10 +38,57 @@ - Detection threshold - threshold - 0.01 - float + Implicit header + implicit + enum + + + + + + Coding rate + cr + enum + $implicit.hide_imp + + + + + + + + CRC + crc + enum + $implicit.hide_imp + + diff --git a/include/lora/decoder.h b/include/lora/decoder.h index ef596c1..94fcb2e 100644 --- a/include/lora/decoder.h +++ b/include/lora/decoder.h @@ -702,11 +702,10 @@ namespace gr { * class. lora::decoder::make is the public interface for * creating new instances. */ - static sptr make(float samp_rate, int sf); + static sptr make(float samp_rate, int sf, bool implicit, uint8_t cr, bool crc); virtual void set_sf(uint8_t sf) = 0; virtual void set_samp_rate(float samp_rate) = 0; - virtual void set_abs_threshold(float threshold) = 0; }; } // namespace lora diff --git a/include/lora/utilities.h b/include/lora/utilities.h index d8e631b..bf96a88 100644 --- a/include/lora/utilities.h +++ b/include/lora/utilities.h @@ -338,6 +338,16 @@ namespace gr { out << std::flush; } + inline bool header_checksum(const uint8_t* header) { + (void) header; + /*Found valid order for bit #0: (1, 4, 8, 9, 10, 11) + Found valid order for bit #1: (0, 2, 5, 8, 9, 10) + Found valid order for bit #2: (0, 3, 6, 9, 11) + Found valid order for bit #3: (1, 2, 3, 7, 8) + Found valid order for bit #4: (4, 5, 6, 7)*/ + return true; + } + inline uint32_t dissect_packet(const void **header, uint32_t header_size, const uint8_t *buffer, uint32_t offset) { (*header) = buffer + offset; return offset + header_size; diff --git a/lib/decoder_impl.cc b/lib/decoder_impl.cc index 45798f3..597bb5d 100644 --- a/lib/decoder_impl.cc +++ b/lib/decoder_impl.cc @@ -37,15 +37,15 @@ namespace gr { namespace lora { - decoder::sptr decoder::make(float samp_rate, int sf) { + decoder::sptr decoder::make(float samp_rate, int sf, bool implicit, uint8_t cr, bool crc) { return gnuradio::get_initial_sptr - (new decoder_impl(samp_rate, sf)); + (new decoder_impl(samp_rate, sf, implicit, cr, crc)); } /** * The private constructor */ - decoder_impl::decoder_impl(float samp_rate, uint8_t sf) + decoder_impl::decoder_impl(float samp_rate, uint8_t sf, bool implicit, uint8_t cr, bool crc) : gr::sync_block("decoder", gr::io_signature::make(1, -1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0)) { @@ -65,7 +65,9 @@ namespace gr { #endif d_bw = 125000u; - d_phdr.cr = 4; + d_implicit = implicit; + d_phdr.cr = cr; + d_phdr.has_mac_crc = crc; d_samples_per_second = samp_rate; d_payload_symbols = 0; d_cfo_estimation = 0.0f; @@ -80,7 +82,7 @@ namespace gr { d_number_of_bins = (uint32_t)(1u << d_sf); d_number_of_bins_hdr = (uint32_t)(1u << (d_sf-2)); d_decim_factor = d_samples_per_symbol / d_number_of_bins; - d_energy_threshold = 0.01f; + d_energy_threshold = 0.0f; d_whitening_sequence = gr::lora::prng_payload; d_fine_sync = 0; set_output_multiple(2 * d_samples_per_symbol); @@ -89,6 +91,10 @@ namespace gr { std::cout << "Bins per symbol: \t" << d_number_of_bins << std::endl; std::cout << "Samples per symbol: \t" << d_samples_per_symbol << std::endl; std::cout << "Decimation: \t\t" << d_decim_factor << std::endl; + if(d_implicit) { + std::cout << "CR: \t\t" << (int)d_phdr.cr << std::endl; + std::cout << "CRC: \t\t" << (int)d_phdr.has_mac_crc << std::endl; + } // Locally generated chirps build_ideal_chirps(); @@ -325,10 +331,20 @@ namespace gr { volk_32f_accumulator_s32f(&energy_chirp2, magsq_chirp2, window); autocorr = abs(dot_product / gr_complex(sqrt(energy_chirp1 * energy_chirp2), 0)); + d_energy_threshold = energy_chirp2 / 2.0f; // When using implicit mode, stop when energy is halved. return autocorr; } + float decoder_impl::determine_energy(const gr_complex *samples) { + float magsq_chirp[d_samples_per_symbol]; + float energy_chirp = 0; + volk_32fc_magnitude_squared_32f(magsq_chirp, samples, d_samples_per_symbol); + volk_32f_accumulator_s32f(&energy_chirp, magsq_chirp, d_samples_per_symbol); + + return energy_chirp; + } + float decoder_impl::detect_downchirp(const gr_complex *samples, const uint32_t window) { float samples_ifreq[window]; instantaneous_frequency(samples, samples_ifreq, window); @@ -764,7 +780,12 @@ namespace gr { } case gr::lora::DecoderState::PAUSE: { - d_state = gr::lora::DecoderState::DECODE_HEADER; + if(d_implicit){ + d_state = gr::lora::DecoderState::DECODE_PAYLOAD; + d_payload_symbols = 1; + } else { + d_state = gr::lora::DecoderState::DECODE_HEADER; + } consume_each(d_samples_per_symbol + d_delay_after_sync); break; } @@ -801,26 +822,22 @@ namespace gr { } case gr::lora::DecoderState::DECODE_PAYLOAD: { - //************************************************************************** - // Failsafe if decoding length reaches end of actual data == noise reached? - // Could be replaced be rejecting packets with CRC mismatch... - if (std::abs(input[0]) < d_energy_threshold) { - //printf("\n*** Decode payload reached end of data! (payload length in HDR is wrong)\n"); + if (d_implicit && determine_energy(input) < d_energy_threshold) { d_payload_symbols = 0; + //d_demodulated.erase(d_demodulated.begin(), d_demodulated.begin() + 7u); // Test for SF 8 with header + d_payload_length = (int32_t)(d_demodulated.size() / 2); + } else if (demodulate(input, false)) { + if(!d_implicit) + d_payload_symbols -= (4u + d_phdr.cr); } - //************************************************************************** - if (demodulate(input, false)) { - d_payload_symbols -= (4u + d_phdr.cr); + if (d_payload_symbols <= 0) { + decode(false); + gr::lora::print_vector_hex(std::cout, &d_decoded[0], d_payload_length, true); + msg_lora_frame(); - if (d_payload_symbols <= 0) { - decode(false); - gr::lora::print_vector_hex(std::cout, &d_decoded[0], d_payload_length, true); - msg_lora_frame(); - - d_state = gr::lora::DecoderState::DETECT; - d_decoded.clear(); - } + d_state = gr::lora::DecoderState::DETECT; + d_decoded.clear(); } consume_each((int32_t)d_samples_per_symbol+d_fine_sync); @@ -856,10 +873,5 @@ namespace gr { std::cerr << "[LoRa Decoder] WARNING : Setting the sample rate during execution is currently not supported." << std::endl << "Nothing set, kept SR of " << d_samples_per_second << "." << std::endl; } - - void decoder_impl::set_abs_threshold(const float threshold) { - d_energy_threshold = gr::lora::clamp(threshold, 0.0f, 20.0f); - } - } /* namespace lora */ } /* namespace gr */ diff --git a/lib/decoder_impl.h b/lib/decoder_impl.h index c656b44..5d9dd9a 100644 --- a/lib/decoder_impl.h +++ b/lib/decoder_impl.h @@ -80,6 +80,7 @@ namespace gr { std::vector d_mult_hf; ///< Vector containing the FFT decimation. std::vector d_tmp; ///< Vector containing the FFT decimation. + bool d_implicit; ///< Implicit header mode. uint8_t d_sf; ///< The Spreading Factor. uint32_t d_bw; ///< The receiver bandwidth (fixed to `125kHz`). loraphy_header_t d_phdr; ///< LoRa PHY header. @@ -262,6 +263,14 @@ namespace gr { */ void determine_cfo(const gr_complex *samples); + /** + * \brief Determine the energy of a symbol. + * + * \param samples + * The complex symbol to analyse. + */ + float determine_energy(const gr_complex *samples); + /** * \brief Returns the index of the bin containing the frequency change. * @@ -407,7 +416,7 @@ namespace gr { * \param sf * The expected spreqding factor. */ - decoder_impl(float samp_rate, uint8_t sf); + decoder_impl(float samp_rate, uint8_t sf, bool implicit, uint8_t cr, bool crc); /** * Default destructor. @@ -445,16 +454,6 @@ namespace gr { * The new sample rate. */ virtual void set_samp_rate(const float samp_rate); - - /** - * \brief Set the absolute threshold to distinguish signal from noise. - *
Should be around 0.01f (default) for normal environments, - *
or as low as 0.001f for the very noise-resistant USRP. - * - * \param threshold - * The new threshold value. - */ - virtual void set_abs_threshold(const float threshold); }; } // namespace lora } // namespace gr diff --git a/lib/message_socket_sink_impl.cc b/lib/message_socket_sink_impl.cc index 9d23f35..9ad4c32 100644 --- a/lib/message_socket_sink_impl.cc +++ b/lib/message_socket_sink_impl.cc @@ -93,7 +93,7 @@ namespace gr { offset = gr::lora::dissect_packet((const void **)&loratap_header, sizeof(loratap_header_t), data, offset); offset = gr::lora::dissect_packet((const void **)&loraphy_header, sizeof(loraphy_header_t), data, offset); - uint32_t payload_length = loraphy_header->length + (MAC_CRC_SIZE * loraphy_header->has_mac_crc); + uint32_t payload_length = size - (sizeof(loratap_header_t) + sizeof(loraphy_header_t)); offset = gr::lora::dissect_packet((const void **)&payload, sizeof(uint8_t)*payload_length, data, offset); if(offset != size) { std::cerr << "message_socket_sink_impl::handle: invalid read: " << offset << " != " << size << std::endl; diff --git a/python/lora_receiver.py b/python/lora_receiver.py index b744f6e..28f585f 100644 --- a/python/lora_receiver.py +++ b/python/lora_receiver.py @@ -26,7 +26,7 @@ class lora_receiver(gr.hier_block2): """ docstring for block lora_receiver """ - def __init__(self, in_samp_rate, center_freq, channel_list, sf, out_samp_rate, threshold = 0.01): + def __init__(self, in_samp_rate, center_freq, channel_list, sf, out_samp_rate, implicit, cr, crc): gr.hier_block2.__init__(self, "lora_receiver", # Min, Max, gr.sizeof_ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature @@ -41,8 +41,7 @@ class lora_receiver(gr.hier_block2): # Define blocks self.channelizer = lora.channelizer(in_samp_rate, out_samp_rate, center_freq, channel_list) - self.decoder = lora.decoder(out_samp_rate, sf) - self.set_threshold(threshold) + self.decoder = lora.decoder(out_samp_rate, sf, implicit, cr, crc) # Messages self.message_port_register_hier_out('frames') @@ -66,10 +65,3 @@ class lora_receiver(gr.hier_block2): def set_center_freq(self, center_freq): self.center_freq = center_freq self.channelizer.set_center_freq(self.center_freq) - - def get_threshold(self): - return self.threshold - - def set_threshold(self, threshold): - self.threshold = threshold - self.decoder.set_abs_threshold(self.threshold) diff --git a/python/qa_testsuite.py b/python/qa_testsuite.py index 0204b0a..2243097 100755 --- a/python/qa_testsuite.py +++ b/python/qa_testsuite.py @@ -246,7 +246,7 @@ class qa_testsuite(): # Build flowgraph tb = gr.top_block() file_source = blocks.file_source(gr.sizeof_gr_complex, data_file, False) - lora_receiver = lora.lora_receiver(sample_rate, capture_freq, [868100000], sf, 1000000, 0.002) + lora_receiver = lora.lora_receiver(sample_rate, capture_freq, [868100000], sf, 1000000, False, 4, True) throttle = blocks.throttle(gr.sizeof_gr_complex, sample_rate, True) message_socket_sink = lora.message_socket_sink("127.0.0.1", 40868, False, False) freq_xlating_fir_filter = filter.freq_xlating_fir_filter_ccc(1, (firdes.low_pass(1, sample_rate, 200000, 100000, firdes.WIN_HAMMING, 6.67)), frequency_offset, sample_rate)