kopia lustrzana https://github.com/rpp0/gr-lora
Support for implicit header mode
rodzic
8bf1953e6b
commit
025faa8c41
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
<key>lora_lora_receiver</key>
|
||||
<category>[LoRa]</category>
|
||||
<import>import lora</import>
|
||||
<make>lora.lora_receiver($in_samp_rate, $center_freq, $channel_list, $sf, $out_samp_rate, $threshold)</make>
|
||||
<make>lora.lora_receiver($in_samp_rate, $center_freq, $channel_list, $sf, $out_samp_rate, $implicit, $cr, $crc)</make>
|
||||
|
||||
<callback>set_center_freq($freq)</callback>
|
||||
<callback>set_sf($sf)</callback>
|
||||
<callback>set_out_samp_rate($out_samp_rate)</callback>
|
||||
<callback>set_threshold($threshold)</callback>
|
||||
|
||||
<param>
|
||||
<name>Sample rate</name>
|
||||
|
@ -39,10 +38,57 @@
|
|||
</param>
|
||||
|
||||
<param>
|
||||
<name>Detection threshold</name>
|
||||
<key>threshold</key>
|
||||
<value>0.01</value>
|
||||
<type>float</type>
|
||||
<name>Implicit header</name>
|
||||
<key>implicit</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>No</name>
|
||||
<key>False</key>
|
||||
<opt>hide_imp:all</opt>
|
||||
</option>
|
||||
<option>
|
||||
<name>Yes</name>
|
||||
<key>True</key>
|
||||
<opt>hide_imp:</opt>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Coding rate</name>
|
||||
<key>cr</key>
|
||||
<type>enum</type>
|
||||
<hide>$implicit.hide_imp</hide>
|
||||
<option>
|
||||
<name>4/8</name>
|
||||
<key>4</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>4/7</name>
|
||||
<key>3</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>4/6</name>
|
||||
<key>2</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>4/5</name>
|
||||
<key>1</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>CRC</name>
|
||||
<key>crc</key>
|
||||
<type>enum</type>
|
||||
<hide>$implicit.hide_imp</hide>
|
||||
<option>
|
||||
<name>Yes</name>
|
||||
<key>True</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>No</name>
|
||||
<key>False</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace gr {
|
|||
std::vector<gr_complex> d_mult_hf; ///< Vector containing the FFT decimation.
|
||||
std::vector<gr_complex> 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.
|
||||
* <br/>Should be around 0.01f (default) for normal environments,
|
||||
* <br/>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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_<type>
|
||||
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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue