kopia lustrzana https://github.com/rpp0/gr-lora
Support for SNR calculation and LoRaTAP headers (Wireshark)
rodzic
2f28b1ba9e
commit
01fde5be3d
|
@ -1,6 +1,6 @@
|
|||
# Test suite: 'decode_long_hackrf'
|
||||
|
||||
*Results on 2017-09-20 07:54:45.563359*
|
||||
*Results on 2017-10-06 15:51:09.045468*
|
||||
|
||||
### 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-20 07:53:29.656650*
|
||||
*Results on 2017-10-06 15:49:53.109400*
|
||||
|
||||
### 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-20 07:54:06.220649*
|
||||
*Results on 2017-10-06 15:50:29.701072*
|
||||
|
||||
### 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-20 08:04:02.415820*
|
||||
*Results on 2017-10-06 16:00:25.768653*
|
||||
|
||||
### 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-20 07:55:22.913194*
|
||||
*Results on 2017-10-06 15:51:46.369561*
|
||||
|
||||
### 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-20 07:59:26.311889*
|
||||
*Results on 2017-10-06 15:55:49.743840*
|
||||
|
||||
### 868.1 MHz, SF 7, CR 4/8, BW 125 kHz, prlen 8, crc on, implicit off
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<key>lora_message_socket_sink</key>
|
||||
<category>[LoRa]</category>
|
||||
<import>import lora</import>
|
||||
<make>lora.message_socket_sink($ip, $port, $loratap, $loraphy)</make>
|
||||
<make>lora.message_socket_sink($ip, $port, $layer)</make>
|
||||
|
||||
<param>
|
||||
<name>IP</name>
|
||||
|
@ -21,17 +21,21 @@
|
|||
</param>
|
||||
|
||||
<param>
|
||||
<name>Append LoRaTap</name>
|
||||
<key>loratap</key>
|
||||
<value>False</value>
|
||||
<type>bool</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Append LoRaPHY</name>
|
||||
<key>loraphy</key>
|
||||
<value>False</value>
|
||||
<type>bool</type>
|
||||
<name>Layer</name>
|
||||
<key>layer</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>LoRa TAP</name>
|
||||
<key>0</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>LoRa PHY</name>
|
||||
<key>1</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>LoRa MAC</name>
|
||||
<key>2</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<sink>
|
||||
|
|
|
@ -692,6 +692,7 @@ namespace gr {
|
|||
class LORA_API message_socket_sink : virtual public gr::block {
|
||||
public:
|
||||
typedef boost::shared_ptr<message_socket_sink> sptr;
|
||||
enum lora_layer { LORATAP = 0, LORAPHY, LORAMAC };
|
||||
|
||||
/*!
|
||||
* \brief Return a shared_ptr to a new instance of lora::message_socket_sink.
|
||||
|
@ -701,7 +702,7 @@ namespace gr {
|
|||
* class. lora::message_socket_sink::make is the public interface for
|
||||
* creating new instances.
|
||||
*/
|
||||
static sptr make(std::string ip, int port, bool loratap, bool loraphy);
|
||||
static sptr make(std::string ip, int port, enum lora_layer layer);
|
||||
};
|
||||
|
||||
} // namespace lora
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#define REV_BITS
|
||||
#define MAC_CRC_SIZE 2u
|
||||
#define MAX_PWR_QUEUE_SIZE 4
|
||||
#define SM(value, shift, mask) (((value) << (shift)) & (mask))
|
||||
#define MS(value, mask, shift) (((value) & (mask)) >> (shift))
|
||||
|
||||
|
|
|
@ -48,7 +48,8 @@ namespace gr {
|
|||
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)) {
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_pwr_queue(MAX_PWR_QUEUE_SIZE) {
|
||||
// Radio config
|
||||
d_state = gr::lora::DecoderState::DETECT;
|
||||
|
||||
|
@ -330,8 +331,14 @@ namespace gr {
|
|||
volk_32f_accumulator_s32f(&energy_chirp1, magsq_chirp1, window);
|
||||
volk_32f_accumulator_s32f(&energy_chirp2, magsq_chirp2, window);
|
||||
|
||||
// When using implicit mode, stop when energy is halved.
|
||||
d_energy_threshold = energy_chirp2 / 2.0f;
|
||||
|
||||
// For calculating the SNR later on
|
||||
d_pwr_queue.push_back(energy_chirp1 / d_samples_per_symbol);
|
||||
|
||||
// Autocorr value
|
||||
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;
|
||||
}
|
||||
|
@ -345,6 +352,14 @@ namespace gr {
|
|||
return energy_chirp;
|
||||
}
|
||||
|
||||
void decoder_impl::determine_snr() {
|
||||
if(d_pwr_queue.size() >= 2) {
|
||||
float pwr_noise = d_pwr_queue[0];
|
||||
float pwr_signal = d_pwr_queue[d_pwr_queue.size()-1];
|
||||
d_snr = pwr_signal / pwr_noise;
|
||||
}
|
||||
}
|
||||
|
||||
float decoder_impl::detect_downchirp(const gr_complex *samples, const uint32_t window) {
|
||||
float samples_ifreq[window];
|
||||
instantaneous_frequency(samples, samples_ifreq, window);
|
||||
|
@ -554,6 +569,8 @@ namespace gr {
|
|||
memset(buffer, 0, sizeof(uint8_t) * len);
|
||||
memset(&loratap_header, 0, sizeof(loratap_header));
|
||||
|
||||
loratap_header.rssi.snr = (uint8_t)(10.0f * log10(d_snr) + 0.5);
|
||||
|
||||
offset = gr::lora::build_packet(buffer, offset, &loratap_header, sizeof(loratap_header_t));
|
||||
offset = gr::lora::build_packet(buffer, offset, &d_phdr, sizeof(loraphy_header_t));
|
||||
offset = gr::lora::build_packet(buffer, offset, &d_decoded[0], d_payload_length);
|
||||
|
@ -717,6 +734,7 @@ namespace gr {
|
|||
float correlation = detect_preamble_autocorr(input, d_samples_per_symbol);
|
||||
|
||||
if (correlation >= 0.90f) {
|
||||
determine_snr();
|
||||
#ifdef DEBUG
|
||||
d_debug << "Ca: " << correlation << std::endl;
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <lora/debugger.h>
|
||||
#include <volk/volk.h>
|
||||
#include <lora/loraphy.h>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
|
||||
namespace gr {
|
||||
namespace lora {
|
||||
|
@ -99,6 +100,8 @@ namespace gr {
|
|||
uint32_t d_corr_fails; ///< Indicates how many times the correlation failed. After some tries, the state will revert to `DecoderState::DETECT`.
|
||||
float d_energy_threshold; ///< The absolute threshold to distinguish signal from noise.
|
||||
const uint8_t* d_whitening_sequence; ///< A pointer to the whitening sequence to be used in decoding. Determined by the SF in the ctor.
|
||||
float d_snr; ///< Signal to noise ratio
|
||||
boost::circular_buffer<float> d_pwr_queue; ///< Queue holding symbol power values
|
||||
|
||||
std::vector<uint32_t> d_words; ///< Vector containing the demodulated words.
|
||||
std::vector<uint8_t> d_demodulated; ///< Vector containing the words after deinterleaving.
|
||||
|
@ -271,6 +274,11 @@ namespace gr {
|
|||
*/
|
||||
float determine_energy(const gr_complex *samples);
|
||||
|
||||
/**
|
||||
* \brief Determine the SNR
|
||||
*/
|
||||
void determine_snr();
|
||||
|
||||
/**
|
||||
* \brief Returns the index of the bin containing the frequency change.
|
||||
*
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
namespace gr {
|
||||
namespace lora {
|
||||
|
||||
message_socket_sink::sptr message_socket_sink::make(std::string ip, int port, bool loratap, bool loraphy) {
|
||||
return gnuradio::get_initial_sptr(new message_socket_sink_impl(ip, port, loratap, loraphy));
|
||||
message_socket_sink::sptr message_socket_sink::make(std::string ip, int port, enum lora_layer layer) {
|
||||
return gnuradio::get_initial_sptr(new message_socket_sink_impl(ip, port, layer));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,12 +40,11 @@ namespace gr {
|
|||
*
|
||||
* Create a UDP socket connection to send the data through.
|
||||
*/
|
||||
message_socket_sink_impl::message_socket_sink_impl(std::string ip, int port, bool loratap, bool loraphy)
|
||||
message_socket_sink_impl::message_socket_sink_impl(std::string ip, int port, enum lora_layer layer)
|
||||
: gr::block("message_socket_sink", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)),
|
||||
d_ip(ip),
|
||||
d_port(port),
|
||||
d_loratap(loratap),
|
||||
d_loraphy(loraphy) {
|
||||
d_layer(layer) {
|
||||
|
||||
message_port_register_in(pmt::mp("in"));
|
||||
set_msg_handler(pmt::mp("in"), boost::bind(&message_socket_sink_impl::handle, this, _1));
|
||||
|
@ -85,44 +84,38 @@ namespace gr {
|
|||
*/
|
||||
void message_socket_sink_impl::handle(pmt::pmt_t msg) {
|
||||
uint8_t* data = (uint8_t*)pmt::blob_data(msg);
|
||||
uint32_t offset = 0;
|
||||
size_t size = pmt::blob_length(msg);
|
||||
loratap_header_t *loratap_header;
|
||||
loraphy_header_t *loraphy_header;
|
||||
uint8_t *payload;
|
||||
|
||||
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 = 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;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(d_loratap == false) {
|
||||
msg_send_udp(loraphy_header, payload, payload_length); // Send message over UDP socket
|
||||
} else {
|
||||
//msg_send_loratap(); // Send message over raw LoRa socket
|
||||
std::cerr << "message_socket_sink_impl::handle: LoRaTap is not supported yet." << std::endl;
|
||||
return;
|
||||
}
|
||||
//offset = gr::lora::dissect_packet((const void **)&loratap_header, sizeof(loratap_header_t), data, offset);
|
||||
msg_send_udp(data, size); // Send message over UDP socket
|
||||
}
|
||||
|
||||
void message_socket_sink_impl::msg_send_udp(const loraphy_header_t* loraphy_header, const uint8_t* payload, const uint32_t payload_length) {
|
||||
bool error = false;
|
||||
void message_socket_sink_impl::msg_send_udp(const uint8_t* data, const uint32_t length) {
|
||||
int32_t msg_len;
|
||||
const uint8_t* msg;
|
||||
|
||||
if(d_loraphy) {
|
||||
int32_t msg_len = sizeof(loraphy_header_t) + payload_length;
|
||||
if (sendto(d_socket, loraphy_header, msg_len, 0, (const struct sockaddr*)d_sock_addr, sizeof(*d_sock_addr)) != msg_len)
|
||||
error = true;
|
||||
} else {
|
||||
int32_t msg_len = payload_length-(MAC_CRC_SIZE * loraphy_header->has_mac_crc); // User did not request PHY header
|
||||
if (sendto(d_socket, payload, msg_len, 0, (const struct sockaddr*)d_sock_addr, sizeof(*d_sock_addr)) != msg_len)
|
||||
error = true;
|
||||
switch(d_layer) {
|
||||
case LORATAP:
|
||||
msg_len = length;
|
||||
msg = data;
|
||||
break;
|
||||
case LORAPHY:
|
||||
msg_len = length - sizeof(loratap_header_t);
|
||||
msg = data + sizeof(loratap_header_t);
|
||||
break;
|
||||
case LORAMAC:
|
||||
loraphy_header_t* loraphy_header;
|
||||
gr::lora::dissect_packet((const void **)&loraphy_header, sizeof(loraphy_header_t), data, sizeof(loratap_header_t));
|
||||
msg_len = length - sizeof(loratap_header_t) - sizeof(loraphy_header_t) - (MAC_CRC_SIZE * loraphy_header->has_mac_crc);
|
||||
msg = data + sizeof(loratap_header_t) + sizeof(loraphy_header_t);
|
||||
break;
|
||||
default:
|
||||
msg_len = length;
|
||||
msg = data;
|
||||
break;
|
||||
}
|
||||
|
||||
if(error) {
|
||||
if (sendto(d_socket, msg, msg_len, 0, (const struct sockaddr*)d_sock_addr, sizeof(*d_sock_addr)) != msg_len) {
|
||||
perror("message_socket_sink_impl::handle: mismatch in number of bytes sent");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@ namespace gr {
|
|||
private:
|
||||
std::string d_ip = "127.0.0.1";
|
||||
int d_port = 40868;
|
||||
bool d_loratap;
|
||||
bool d_loraphy;
|
||||
enum lora_layer d_layer;
|
||||
|
||||
// socket
|
||||
struct sockaddr_in *d_sock_addr;
|
||||
|
@ -43,11 +42,11 @@ namespace gr {
|
|||
void handle(pmt::pmt_t msg);
|
||||
|
||||
public:
|
||||
message_socket_sink_impl(std::string ip, int port, bool loratap, bool loraphy);
|
||||
message_socket_sink_impl(std::string ip, int port, enum lora_layer layer);
|
||||
~message_socket_sink_impl();
|
||||
|
||||
private:
|
||||
void msg_send_udp(const loraphy_header_t* loraphy_header, const uint8_t* payload, const uint32_t payload_length);
|
||||
void msg_send_udp(const uint8_t* data, const uint32_t length);
|
||||
};
|
||||
|
||||
} // namespace lora
|
||||
|
|
|
@ -253,7 +253,7 @@ class qa_testsuite():
|
|||
file_source = blocks.file_source(gr.sizeof_gr_complex, data_file, False)
|
||||
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)
|
||||
message_socket_sink = lora.message_socket_sink("127.0.0.1", 40868, 2)
|
||||
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)
|
||||
|
||||
# Make connections
|
||||
|
|
Ładowanie…
Reference in New Issue