Support for SNR calculation and LoRaTAP headers (Wireshark)

pull/61/head
Pieter Robyns 2017-10-06 18:05:07 +02:00
rodzic 2f28b1ba9e
commit 01fde5be3d
14 zmienionych plików z 86 dodań i 62 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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>

Wyświetl plik

@ -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

Wyświetl plik

@ -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))

Wyświetl plik

@ -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

Wyświetl plik

@ -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.
*

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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