From dbadd1aacb199123500491b7b19c5b22f9773cbe Mon Sep 17 00:00:00 2001 From: Wosser1sProductions Date: Thu, 23 Feb 2017 21:12:40 +0100 Subject: [PATCH 1/3] Starting decoder rework ~ Changed indentation layout ~ Replaced some functions from utilities.h with more performant ones (tested in gr-lora-benchmarks) + Added message if spreading factor is set outside of compatible range + Added this keyword for class members + Added NDEBUG macro to be able to completely remove debugging (for performance improvement) ~ Extracted multiplications from loops to a precalculation instead ~ Reworked flow of most of the functions * TODO: Change find_preamble algorithm for better detection * TODO: Change detect_downchirp algorithm for better sync --- lib/decoder_impl.cc | 1436 ++++++++++++++++++++++--------------------- lib/decoder_impl.h | 194 +++--- lib/tables.h | 46 +- lib/utilities.h | 146 ++--- 4 files changed, 927 insertions(+), 895 deletions(-) diff --git a/lib/decoder_impl.cc b/lib/decoder_impl.cc index fe30526..3dd895d 100644 --- a/lib/decoder_impl.cc +++ b/lib/decoder_impl.cc @@ -19,7 +19,7 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include @@ -30,583 +30,552 @@ #include "tables.h" #include "utilities.h" -//#define NO_TMP_WRITES 1 -//#define CFO_CORRECT 1 +//#define NO_TMP_WRITES 1 /// Debug output file write +//#define CFO_CORRECT 1 /// Correct shift fft estimation + + +#undef NDEBUG /// Debug printing namespace gr { - namespace lora { + namespace lora { - decoder::sptr - decoder::make(float samp_rate, int sf) { - return gnuradio::get_initial_sptr - (new decoder_impl(samp_rate, sf)); - } - - /* - * The private constructor - */ - decoder_impl::decoder_impl(float samp_rate, int sf) : gr::sync_block("decoder", - gr::io_signature::make(1, -1, sizeof(gr_complex)), - gr::io_signature::make(0, 2, sizeof(float))) { - d_state = DETECT; - - d_debug_samples.open("/tmp/grlora_debug", std::ios::out | std::ios::binary); - d_debug.open("/tmp/grlora_debug_txt", std::ios::out); - d_sf = sf; // Only affects PHY send - d_bw = 125000; - d_cr = 4; - d_bits_per_second = (double)d_sf * (4.0f/4.0f+d_cr) / (pow(2.0f, d_sf) / d_bw); - d_samples_per_second = samp_rate; - d_symbols_per_second = (double)d_bw / pow(2.0f, d_sf); - d_bits_per_symbol = (uint32_t)(d_bits_per_second / d_symbols_per_second); - d_samples_per_symbol = (uint32_t)(d_samples_per_second / d_symbols_per_second); - d_delay_after_sync = d_samples_per_symbol / 4; - d_corr_decim_factor = 8; // samples_per_symbol / corr_decim_factor = correlation window. Also serves as preamble decimation factor - d_number_of_bins = (uint32_t)pow(2, d_sf); - d_number_of_bins_hdr = d_number_of_bins / 4; - d_payload_symbols = 0; - d_cfo_estimation = 0.0f; - d_dt = 1.0f / d_samples_per_second; - - // Some preparations - std::cout << "Bits per symbol: " << d_bits_per_symbol << std::endl; - std::cout << "Bins per symbol: " << d_number_of_bins << std::endl; - std::cout << "Header bins per symbol: " << d_number_of_bins_hdr << std::endl; - std::cout << "Samples per symbol: " << d_samples_per_symbol << std::endl; - std::cout << "Decimation: " << d_samples_per_symbol / d_number_of_bins << std::endl; - - build_ideal_chirps(); - - set_output_multiple(2*d_samples_per_symbol); - d_fft.resize(d_number_of_bins); - d_mult.resize(d_number_of_bins); - d_q = fft_create_plan(d_number_of_bins, &d_mult[0], &d_fft[0], LIQUID_FFT_FORWARD, 0); - - // Decimation filter - float g[DECIMATOR_FILTER_SIZE]; - liquid_firdes_rrcos(8, 1, 0.5f, 0.3f, g); // Filter for interpolating - for (uint32_t i = 0; i < DECIMATOR_FILTER_SIZE; i++) // Reverse it to get decimation filter - d_decim_h[i] = g[DECIMATOR_FILTER_SIZE-i-1]; - d_decim_factor = d_samples_per_symbol / d_number_of_bins; - - d_decim = firdecim_crcf_create(d_decim_factor, d_decim_h, DECIMATOR_FILTER_SIZE); - - // Register gnuradio ports - message_port_register_out(pmt::mp("frames")); - message_port_register_out(pmt::mp("debug")); - } - - /* - * Our virtual destructor. - */ - decoder_impl::~decoder_impl() { - if(d_debug_samples.is_open()) - d_debug_samples.close(); - if(d_debug.is_open()) - d_debug.close(); - - fft_destroy_plan(d_q); - firdecim_crcf_destroy(d_decim); - } - - void decoder_impl::build_ideal_chirps(void) { - d_downchirp.resize(d_samples_per_symbol); - d_upchirp.resize(d_samples_per_symbol); - d_downchirp_ifreq.resize(d_samples_per_symbol); - d_upchirp_ifreq.resize(d_samples_per_symbol); - - double dir; - double T = 1.0f / d_symbols_per_second; - double f0 = (d_bw / 2.0f); - double amplitude = 1.0f; - - // Store time domain signal - dir = 1.0f; - for(int i = 0; i < d_samples_per_symbol; i++) { // Width in number of samples = samples_per_symbol - // See https://en.wikipedia.org/wiki/Chirp#Linear - double t = d_dt * i; - d_downchirp[i] = gr_complex(amplitude, amplitude) * gr_expj(dir * 2.0f * M_PI * (f0 * t + (-1.0f * (0.5 * d_bw / T) * pow(t, 2)))); + decoder::sptr decoder::make(float samp_rate, int sf) { + return gnuradio::get_initial_sptr + (new decoder_impl(samp_rate, sf)); } - dir = -1.0f; - for(int i = 0; i < d_samples_per_symbol; i++) { - double t = d_dt * i; - d_upchirp[i] = gr_complex(amplitude, amplitude) * gr_expj(dir * 2.0f * M_PI * (f0 * t + (-1.0f * (0.5 * d_bw / T) * pow(t, 2)))); - } + /** + * The private constructor + */ + decoder_impl::decoder_impl(float samp_rate, uint8_t sf) + : gr::sync_block("decoder", + gr::io_signature::make(1, -1, sizeof(gr_complex)), + gr::io_signature::make(0, 2, sizeof(float))) { + this->d_state = gr::lora::DecoderState::DETECT; - // Store instant. frequency - instantaneous_frequency(&d_downchirp[0], &d_downchirp_ifreq[0], d_samples_per_symbol); - instantaneous_frequency(&d_upchirp[0], &d_upchirp_ifreq[0], d_samples_per_symbol); - - samples_to_file("/tmp/downchirp", &d_downchirp[0], d_downchirp.size(), sizeof(gr_complex)); - samples_to_file("/tmp/upchirp", &d_upchirp[0], d_upchirp.size(), sizeof(gr_complex)); - } - - void decoder_impl::samples_to_file(const std::string path, const gr_complex* v, int length, int elem_size) { - #ifndef NO_TMP_WRITES - std::ofstream out_file; - out_file.open(path.c_str(), std::ios::out | std::ios::binary); - //for(std::vector::const_iterator it = v.begin(); it != v.end(); ++it) { - for(uint32_t i = 0; i < length; i++) { - out_file.write(reinterpret_cast(&v[i]), elem_size); + if (sf < 6 || sf > 13) { + //throw std::invalid_argument("[LoRa Decoder] ERROR : Spreading factor should be between 6 and 12 (inclusive)!\n Other values are currently not supported."); + std::cerr << "[LoRa Decoder] ERROR : Spreading factor should be between 6 and 12 (inclusive)!\n Other values are currently not supported." << std::endl; + exit(1); } - out_file.close(); - #endif - } - void decoder_impl::samples_debug(const gr_complex* v, int length) { - gr_complex start_indicator(0.0f,32.0f); - d_debug_samples.write(reinterpret_cast(&start_indicator), sizeof(gr_complex)); - for(uint32_t i = 1; i < length; i++) { - d_debug_samples.write(reinterpret_cast(&v[i]), sizeof(gr_complex)); - } - } + #ifndef NDEBUG + this->d_debug_samples.open("/tmp/grlora_debug", std::ios::out | std::ios::binary); + this->d_debug.open("/tmp/grlora_debug_txt", std::ios::out); + #endif - bool decoder_impl::calc_energy_threshold(gr_complex* samples, int window_size, float threshold) { - float result = 0.0f; - for(int i = 0; i < window_size; i++) { - result += std::pow(abs(samples[i]), 2); - } - result /= (float)window_size; + this->d_bw = 125000; + this->d_cr = 4; + this->d_samples_per_second = samp_rate; + this->d_corr_decim_factor = 8; // samples_per_symbol / corr_decim_factor = correlation window. Also serves as preamble decimation factor + this->d_payload_symbols = 0; + this->d_cfo_estimation = 0.0f; + this->d_dt = 1.0f / this->d_samples_per_second; - //d_debug << "T: " << result << "\n"; + this->d_sf = sf; // Only affects PHY send + this->d_bits_per_second = (double)this->d_sf * (double)(1 + this->d_cr) / (1 << this->d_sf) * this->d_bw; + this->d_symbols_per_second = (double)this->d_bw / (1 << this->d_sf); + this->d_bits_per_symbol = (uint32_t)(this->d_bits_per_second / this->d_symbols_per_second); + this->d_samples_per_symbol = (uint32_t)(this->d_samples_per_second / this->d_symbols_per_second); + this->d_delay_after_sync = this->d_samples_per_symbol / 4; + this->d_number_of_bins = (uint32_t)(1 << this->d_sf); + this->d_number_of_bins_hdr = this->d_number_of_bins / 4; - if(result > threshold) { - return true; - } else { - return false; - } - } + // Some preparations + std::cout << "Bits per symbol: \t" << this->d_bits_per_symbol << std::endl; + std::cout << "Bins per symbol: \t" << this->d_number_of_bins << std::endl; + std::cout << "Header bins per symbol: " << this->d_number_of_bins_hdr << std::endl; + std::cout << "Samples per symbol: \t" << this->d_samples_per_symbol << std::endl; + std::cout << "Decimation: \t\t" << (this->d_samples_per_symbol / this->d_number_of_bins) << std::endl; - void decoder_impl::instantaneous_frequency(const gr_complex* in_samples, float* out_ifreq, uint32_t window) { - float iphase[window]; + this->build_ideal_chirps(); - if(window < 2) { - // TODO: throw warning here - return; + this->set_output_multiple(2 * this->d_samples_per_symbol); + this->d_fft.resize(this->d_number_of_bins); + this->d_mult.resize(this->d_number_of_bins); + this->d_q = fft_create_plan(this->d_number_of_bins, &this->d_mult[0], &this->d_fft[0], LIQUID_FFT_FORWARD, 0); + + // Decimation filter + float g[DECIMATOR_FILTER_SIZE]; + liquid_firdes_rrcos(8, 1, 0.5f, 0.3f, g); // Filter for interpolating + + for (uint32_t i = 0; i < DECIMATOR_FILTER_SIZE; i++) // Reverse it to get decimation filter + this->d_decim_h[i] = g[DECIMATOR_FILTER_SIZE - i - 1]; + + this->d_decim_factor = this->d_samples_per_symbol / this->d_number_of_bins; + + this->d_decim = firdecim_crcf_create(this->d_decim_factor, this->d_decim_h, DECIMATOR_FILTER_SIZE); + + // Register gnuradio ports + this->message_port_register_out(pmt::mp("frames")); + this->message_port_register_out(pmt::mp("debug")); } - instantaneous_phase(in_samples, iphase, window); + /** + * Our virtual destructor. + */ + decoder_impl::~decoder_impl() { + #ifndef NDEBUG + if (this->d_debug_samples.is_open()) + this->d_debug_samples.close(); - // Instant freq - for(uint32_t i = 1; i < window; i++) { - out_ifreq[i-1] = iphase[i] - iphase[i-1]; - } - out_ifreq[window-1] = out_ifreq[window-2]; // Make sure there is no strong gradient if this value is accessed by mistake - } + if (this->d_debug.is_open()) + this->d_debug.close(); + #endif - inline void decoder_impl::instantaneous_phase(const gr_complex* in_samples, float* out_iphase, uint32_t window) { - for(uint32_t i = 0; i < window; i++) { - out_iphase[i] = arg(in_samples[i]); // = the same as atan2(imag(in_samples[i]),real(in_samples[i])); + fft_destroy_plan(this->d_q); + firdecim_crcf_destroy(this->d_decim); } - liquid_unwrap_phase(out_iphase, window); - } + void decoder_impl::build_ideal_chirps(void) { + this->d_downchirp .resize(this->d_samples_per_symbol); + this->d_upchirp .resize(this->d_samples_per_symbol); + this->d_downchirp_ifreq .resize(this->d_samples_per_symbol); + this->d_upchirp_ifreq .resize(this->d_samples_per_symbol); - float decoder_impl::cross_correlate(const gr_complex *samples_1, const gr_complex *samples_2, int window) { - float result = 0.0f; + const double T = -0.5 * this->d_bw * this->d_symbols_per_second; + const double f0 = (this->d_bw / 2.0f); + const double pre_dir = 2.0f * M_PI; + double t; + gr_complex cmx = gr_complex(1.0f, 1.0f); - for (int i = 0; i < window; i++) { - result += real(samples_1[i] * conj(samples_2[i])); + for (uint32_t i = 0; i < this->d_samples_per_symbol; i++) { + // Width in number of samples = samples_per_symbol + // See https://en.wikipedia.org/wiki/Chirp#Linear + t = this->d_dt * i; + this->d_downchirp[i] = cmx * gr_expj(pre_dir * t * (f0 + T * t)); + this->d_upchirp[i] = cmx * gr_expj(pre_dir * t * (f0 + T * t) * -1.0f); + } + + // Store instant. frequency + instantaneous_frequency(&this->d_downchirp[0], &this->d_downchirp_ifreq[0], this->d_samples_per_symbol); + instantaneous_frequency(&this->d_upchirp[0], &this->d_upchirp_ifreq[0], this->d_samples_per_symbol); + + samples_to_file("/tmp/downchirp", &this->d_downchirp[0], this->d_downchirp.size(), sizeof(gr_complex)); + samples_to_file("/tmp/upchirp", &this->d_upchirp[0], this->d_upchirp.size(), sizeof(gr_complex)); } - result = result / window; - return result; - } + void decoder_impl::samples_to_file(const std::string path, const gr_complex *v, uint32_t length, uint32_t elem_size) { + #ifndef NO_TMP_WRITES + std::ofstream out_file; + out_file.open(path.c_str(), std::ios::out | std::ios::binary); - float decoder_impl::detect_downchirp(const gr_complex *samples, uint32_t window) { - float samples_ifreq[window]; + //for(std::vector::const_iterator it = v.begin(); it != v.end(); ++it) { + for (uint32_t i = 0; i < length; i++) { + out_file.write(reinterpret_cast(&v[i]), elem_size); + } - instantaneous_frequency(samples, samples_ifreq, window); - return norm_cross_correlate(samples_ifreq, &d_downchirp_ifreq[0], window); - } - - /** - * Calculate normalized cross correlation of real values. - * See https://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation. - */ - float decoder_impl::norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window) { - float result = 0.0f; - - double average_1 = std::accumulate(samples_1, samples_1 + window, 0.0) / window; - double average_2 = std::accumulate(samples_2, samples_2 + window, 0.0) / window; - double sd_1 = stddev(samples_1, window, average_1); - double sd_2 = stddev(samples_2, window, average_2); - - for (int i = 0; i < window-1; i++) { - result += (samples_1[i] - average_1) * (samples_2[i] - average_2) / (sd_1 * sd_2); - } - result = result / (window-1); - - return result; - } - - float decoder_impl::sliding_norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window, uint32_t slide, int32_t* index) { - float correlations[slide*2]; - float samples_1_padded[window+slide*2]; - - double average_1 = std::accumulate(samples_1, samples_1 + window, 0.0) / window; - double average_2 = std::accumulate(samples_2, samples_2 + window, 0.0) / window; - double sd_1 = stddev(samples_1, window, average_1); - double sd_2 = stddev(samples_2, window, average_2); - - // Create padding on both sides of the samples - for(uint32_t i = 0; i < window+slide*2; i++) { - samples_1_padded[i] = 0.0f; - } - for(uint32_t i = 0; i < window; i++) { - samples_1_padded[i+slide-1] = samples_1[i]; + out_file.close(); + #else + (void) path; + (void) v; + (void) length; + (void) elem_size; + #endif } - // Slide and correlate - for(uint32_t i = 0; i < 2*slide; i++) { + void decoder_impl::samples_debug(const gr_complex *v, uint32_t length) { + #ifndef NDEBUG + gr_complex start_indicator(0.0f, 32.0f); + this->d_debug_samples.write(reinterpret_cast(&start_indicator), sizeof(gr_complex)); + + for (uint32_t i = 1; i < length; i++) { + this->d_debug_samples.write(reinterpret_cast(&v[i]), sizeof(gr_complex)); + } + #else + (void) v; + (void) length; + #endif + } + + bool decoder_impl::calc_energy_threshold(gr_complex *samples, int window_size, float threshold) { float result = 0.0f; - for (uint32_t j = 0; j < window; j++) { - result += (samples_1_padded[i+j] - average_1) * (samples_2[j] - average_2) / (sd_1 * sd_2); - } - correlations[i] = result / window; - } - uint32_t argmax = (std::max_element(correlations,correlations+slide*2) - correlations); // Determine best correlation - *index = argmax - slide; // Determine how much we have to slide before the best correlation is reached - - return correlations[argmax]; - } - - float decoder_impl::stddev(const float *values, int len, float mean) { - double variance = 0.0f; - - for (unsigned int i = 0; i < len; i++) { - variance += std::pow(values[i] - mean, 2); - } - - variance /= len; - return std::sqrt(variance); - } - - float decoder_impl::detect_upchirp(const gr_complex *samples, uint32_t window, uint32_t slide, int32_t* index) { - float samples_ifreq[window]; - - instantaneous_frequency(samples, samples_ifreq, window); - return sliding_norm_cross_correlate(samples_ifreq, &d_upchirp_ifreq[0], window, slide, index); - } - - unsigned int decoder_impl::get_shift_fft(gr_complex* samples) { - float fft_mag[d_number_of_bins]; - gr_complex mult_hf[d_samples_per_symbol]; - - #ifdef CFO_CORRECT - determine_cfo(&samples[0]); - d_debug << "CFO: " << d_cfo_estimation << std::endl; - correct_cfo(&samples[0], d_samples_per_symbol); - #endif - - samples_to_file("/tmp/data", &samples[0], d_samples_per_symbol, sizeof(gr_complex)); - - // Multiply with ideal downchirp - for(uint32_t i = 0; i < d_samples_per_symbol; i++) { - mult_hf[i] = conj(samples[i] * d_downchirp[i]); - } - - samples_to_file("/tmp/mult", &mult_hf[0], d_samples_per_symbol, sizeof(gr_complex)); - - // Perform decimation - for (uint32_t i = 0; i < d_number_of_bins; i++) { - firdecim_crcf_execute(d_decim, &mult_hf[d_decim_factor*i], &d_mult[i]); - } - - samples_to_file("/tmp/resampled", &d_mult[0], d_number_of_bins, sizeof(gr_complex)); - - // Perform FFT - fft_execute(d_q); - - // Get magnitude - for(int i = 0; i < d_number_of_bins; i++) { - fft_mag[i] = abs(d_fft[i]); - } - - samples_to_file("/tmp/fft", &d_fft[0], d_number_of_bins, sizeof(gr_complex)); - - // Return argmax here - return (std::max_element(fft_mag,fft_mag+d_number_of_bins) - fft_mag); - } - - unsigned int decoder_impl::max_frequency_gradient_idx(gr_complex* samples) { - float instantaneous_phase[d_samples_per_symbol]; - float instantaneous_freq[d_samples_per_symbol]; - float bins[d_number_of_bins]; - - samples_to_file("/tmp/data", &samples[0], d_samples_per_symbol, sizeof(gr_complex)); - - // Determine instant phase - for(unsigned int i = 0; i < d_samples_per_symbol; i++) { - instantaneous_phase[i] = arg(samples[i]); - } - liquid_unwrap_phase(instantaneous_phase, d_samples_per_symbol); - - float max_if_diff = 2000.0f; - unsigned int max_if_diff_idx = 0; - - for(unsigned int i = 1; i < d_samples_per_symbol; i++) { - float ifreq = (instantaneous_phase[i] - instantaneous_phase[i-1]) / (2.0f * M_PI) * d_samples_per_second; // TODO: constant multiplication can be removed - instantaneous_freq[i-1] = ifreq; - } - - int osr = d_samples_per_symbol / d_number_of_bins; - float last_avg = instantaneous_freq[0]; - for(unsigned int i = 0; i < d_number_of_bins; i++) { - float avg = 0.0f; - for(unsigned int j = 0; j < osr; j++) { - avg += instantaneous_freq[(osr*i) + j]; - } - avg /= osr; - - float diff = abs(last_avg - avg); - - if(diff > max_if_diff) { - max_if_diff = diff; - max_if_diff_idx = i; + for (int i = 0; i < window_size; i++) { + float magn = abs(samples[i]); + result += magn * magn; } - last_avg = avg; - } - //std::cout << "!!!" << max_if_diff << std::endl; + result /= (float)window_size; - return max_if_diff_idx; - } + #ifndef NDEBUG + this->d_debug << "T: " << result << "\n"; + #endif - bool decoder_impl::demodulate(gr_complex* samples, bool is_header) { - unsigned int bin_idx = max_frequency_gradient_idx(samples); - //unsigned int bin_idx = get_shift_fft(samples); - //unsigned int bin_idx_test = get_shift_fft(samples); - unsigned int bin_idx_test = 0; - - // Header has additional redundancy - if(is_header) { - bin_idx /= 4; - bin_idx_test /= 4; + return result > threshold; } - // Decode (actually gray encode) the bin to get the symbol value - unsigned int word = gray_encode(bin_idx); - d_debug << to_bin(word, is_header ? d_sf-2 : d_sf) << " " << bin_idx << std::endl; - d_words.push_back(word); + void decoder_impl::instantaneous_frequency(const gr_complex *in_samples, float *out_ifreq, uint32_t window) { + float iphase[window]; - // Look for 4+cr symbols and stop - if(d_words.size() == (4 + d_cr)) { - // Deinterleave - if(is_header) { - deinterleave(d_sf - 2); + if (window < 2) { + // TODO: throw warning here + std::cerr << "LoRa Decoder Warning: window size < 2 !" << std::endl; + return; + } + + this->instantaneous_phase(in_samples, iphase, window); + + // Instant freq + for (uint32_t i = 1; i < window; i++) { + out_ifreq[i - 1] = iphase[i] - iphase[i - 1]; + } + + // Make sure there is no strong gradient if this value is accessed by mistake + out_ifreq[window - 1] = out_ifreq[window - 2]; + } + + inline void decoder_impl::instantaneous_phase(const gr_complex *in_samples, float *out_iphase, uint32_t window) { + for (uint32_t i = 0; i < window; i++) { + out_iphase[i] = arg(in_samples[i]); + // = the same as atan2(imag(in_samples[i]),real(in_samples[i])); + } + + liquid_unwrap_phase(out_iphase, window); + } + + float decoder_impl::cross_correlate(const gr_complex *samples_1, const gr_complex *samples_2, int window) { + float result = 0.0f; + + for (int i = 0; i < window; i++) { + result += real(samples_1[i] * conj(samples_2[i])); + } + + result /= (float)window; + + return result; + } + + float decoder_impl::detect_downchirp(const gr_complex *samples, uint32_t window) { + float samples_ifreq[window]; + + instantaneous_frequency(samples, samples_ifreq, window); + return norm_cross_correlate(samples_ifreq, &this->d_downchirp_ifreq[0], window); + } + + /** + * Calculate normalized cross correlation of real values. + * See https://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation. + */ + float decoder_impl::norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window) { + float result = 0.0f; + + float average_1 = std::accumulate(samples_1, samples_1 + window, 0.0f) / window; + float average_2 = std::accumulate(samples_2, samples_2 + window, 0.0f) / window; + float sd_1 = stddev(samples_1, window, average_1); + float sd_2 = stddev(samples_2, window, average_2); + + for (uint32_t i = 0; i < window - 1; i++) { + result += (samples_1[i] - average_1) * (samples_2[i] - average_2) + / (sd_1 * sd_2); + } + + result /= (float)(window - 1); + + return result; + } + + float decoder_impl::sliding_norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window, uint32_t slide, int32_t *index) { + float correlations[slide * 2]; + float samples_1_padded[window + slide * 2] = { 0.0f }; + + double average_1 = std::accumulate(samples_1, samples_1 + window, 0.0) / window; + double average_2 = std::accumulate(samples_2, samples_2 + window, 0.0) / window; + double sd_1 = stddev(samples_1, window, average_1); + double sd_2 = stddev(samples_2, window, average_2); + + uint32_t i, j; + float result; + + // Create padding on both sides of the samples + for (i = 0; i < window; i++) { + samples_1_padded[i + slide - 1] = samples_1[i]; + } + + // Slide and correlate + for (i = 0; i < 2 * slide; i++) { + result = 0.0f; + + for (j = 0; j < window; j++) { + result += (samples_1_padded[i + j] - average_1) * (samples_2[j] - average_2) + / (sd_1 * sd_2); + } + + correlations[i] = result / (float)window; + } + + // Determine best correlation + uint32_t argmax = (std::max_element(correlations, correlations + slide * 2) - correlations); + // Determine how much we have to slide before the best correlation is reached + *index = argmax - slide; + + return correlations[argmax]; + } + + float decoder_impl::stddev(const float *values, uint32_t len, float mean) { + float variance = 0.0f, temp; + + for (unsigned int i = 0; i < len; i++) { + temp = values[i] - mean; + variance += temp * temp; + } + + variance /= (float)len; + return std::sqrt(variance); + } + + float decoder_impl::detect_upchirp(const gr_complex *samples, uint32_t window, uint32_t slide, int32_t *index) { + float samples_ifreq[window]; + + instantaneous_frequency(samples, samples_ifreq, window); + return sliding_norm_cross_correlate(samples_ifreq, &this->d_upchirp_ifreq[0], window, slide, index); + } + + unsigned int decoder_impl::get_shift_fft(gr_complex *samples) { + float fft_mag[this->d_number_of_bins]; + gr_complex mult_hf[this->d_samples_per_symbol]; + + #ifdef CFO_CORRECT + determine_cfo(&samples[0]); + #ifndef NDEBUG + this->d_debug << "CFO: " << this->d_cfo_estimation << std::endl; + #endif + correct_cfo(&samples[0], this->d_samples_per_symbol); + #endif + + samples_to_file("/tmp/data", &samples[0], this->d_samples_per_symbol, sizeof(gr_complex)); + + // Multiply with ideal downchirp + for (uint32_t i = 0; i < this->d_samples_per_symbol; i++) { + mult_hf[i] = conj(samples[i] * this->d_downchirp[i]); + } + + samples_to_file("/tmp/mult", &mult_hf[0], this->d_samples_per_symbol, sizeof(gr_complex)); + + // Perform decimation + for (uint32_t i = 0; i < this->d_number_of_bins; i++) { + firdecim_crcf_execute(this->d_decim, &mult_hf[this->d_decim_factor * i], &d_mult[i]); + } + + samples_to_file("/tmp/resampled", &this->d_mult[0], this->d_number_of_bins, sizeof(gr_complex)); + + // Perform FFT + fft_execute(this->d_q); + + // Get magnitude + for (uint32_t i = 0; i < this->d_number_of_bins; i++) { + fft_mag[i] = abs(this->d_fft[i]); + } + + samples_to_file("/tmp/fft", &this->d_fft[0], this->d_number_of_bins, sizeof(gr_complex)); + + // Return argmax here + return (std::max_element(fft_mag, fft_mag + this->d_number_of_bins) - fft_mag); + } + + unsigned int decoder_impl::max_frequency_gradient_idx(gr_complex *samples) { + float instantaneous_phase[this->d_samples_per_symbol]; + float instantaneous_freq [this->d_samples_per_symbol]; + //float bins[this->d_number_of_bins]; + + samples_to_file("/tmp/data", &samples[0], this->d_samples_per_symbol, sizeof(gr_complex)); + + // Determine instant phase + for (unsigned int i = 0; i < this->d_samples_per_symbol; i++) { + instantaneous_phase[i] = arg(samples[i]); + } + + liquid_unwrap_phase(instantaneous_phase, this->d_samples_per_symbol); + + float max_if_diff = 2000.0f; + unsigned int max_if_diff_idx = 0; + const double div = (double)this->d_samples_per_second / (2.0f * M_PI); + + for (unsigned int i = 1; i < this->d_samples_per_symbol; i++) { + instantaneous_freq[i - 1] = (float)((instantaneous_phase[i] - instantaneous_phase[i - 1]) * div); + } + + uint32_t osr = this->d_samples_per_symbol / this->d_number_of_bins; + float last_avg = instantaneous_freq[0]; + + for (unsigned int i = 0; i < this->d_number_of_bins; i++) { + float avg = 0.0f; + + for (unsigned int j = 0; j < osr; j++) { + avg += instantaneous_freq[(osr * i) + j]; + } + + avg /= (float)osr; + + float diff = abs(last_avg - avg); + + if (diff > max_if_diff) { + max_if_diff = diff; + max_if_diff_idx = i; + } + + last_avg = avg; + } + + //std::cout << "!!!" << max_if_diff << std::endl; + + return max_if_diff_idx; + } + + bool decoder_impl::demodulate(gr_complex *samples, bool is_header) { + unsigned int bin_idx = this->max_frequency_gradient_idx(samples); + //unsigned int bin_idx = get_shift_fft(samples); + //unsigned int bin_idx_test = get_shift_fft(samples); + unsigned int bin_idx_test = 0; + + // Header has additional redundancy + if (is_header) { + bin_idx /= 4; + bin_idx_test /= 4; + } + + // Decode (actually gray encode) the bin to get the symbol value + unsigned int word = gray_encode(bin_idx); + #ifndef NDEBUG + this->d_debug << gr::lora::to_bin(word, is_header ? this->d_sf - 2 : this->d_sf) << " " << bin_idx << std::endl; + #endif + this->d_words.push_back(word); + + // Look for 4+cr symbols and stop + if (this->d_words.size() == (4u + this->d_cr)) { + // Deinterleave + this->deinterleave(is_header ? this->d_sf - 2 : this->d_sf); + + return true; // Signal that a block is ready for decoding + } + + return false; // We need more words in order to decode a block + } + + void decoder_impl::deinterleave(uint32_t ppm) { + unsigned int bits_per_word = this->d_words.size(); + + if (bits_per_word > 8) { + // Not sure if this can ever occur. It would imply coding rate high than 4/8 e.g. 4/9. + std::cerr << "More than 8 bits per word. uint8_t will not be sufficient! Bytes need to be stored in intermediate array and then packed into words_deinterleaved!" << std::endl; + } + + std::deque words_deinterleaved; + unsigned int offset_start = ppm - 1, offset_diag, i; + uint8_t d; + + for (i = 0; i < ppm; i++) { + d = 0; + offset_diag = offset_start; + + for (unsigned int j = 0; j < bits_per_word; j++) { + uint8_t power = 1 << j; + unsigned int power_check = 1 << offset_diag; + + if (this->d_words[j] & power_check) { // Mask triggers + d += power; + } + + if (offset_diag) offset_diag--; + else offset_diag = ppm - 1; + } + + offset_start--; + words_deinterleaved.push_front(d); + } + + #ifndef NDEBUG + std::vector wd(words_deinterleaved.begin(), words_deinterleaved.begin() + ppm-1); + print_vector(this->d_debug, wd, "D", sizeof(uint8_t) * 8); + #endif + + // Add to demodulated data + this->d_demodulated.insert(this->d_demodulated.end(), words_deinterleaved.begin(), words_deinterleaved.end()); + + // Cleanup + this->d_words.clear(); + } + + int decoder_impl::decode(uint8_t *out_data, bool is_header) { + const uint8_t *prng = NULL; + const uint8_t shuffle_pattern[] = {7, 6, 3, 4, 2, 1, 0, 5}; + + if (is_header) { + prng = gr::lora::prng_header; } else { - deinterleave(d_sf); - } - - return true; // Signal that a block is ready for decoding - } - - return false; // We need more words in order to decode a block - } - - void decoder_impl::deinterleave(int ppm) { - unsigned int bits_per_word = d_words.size(); - - if(bits_per_word > 8) { // Not sure if this can ever occur. It would imply coding rate high than 4/8 e.g. 4/9. - std::cout << "More than 8 bits per word. uint8_t will not be sufficient! Bytes need to be stored in intermediate array and then packed into words_deinterleaved!" << std::endl; - } - - unsigned int offset_start = ppm-1; - std::vector words_deinterleaved; - for(unsigned int i = 0; i < ppm; i++) { - uint8_t d = 0; - unsigned int offset_diag = offset_start; - - for(unsigned int j = 0; j < bits_per_word; j++) { - uint8_t power = pow(2, j); - unsigned int power_check = pow(2, offset_diag); - if((d_words[j] & power_check) > 0) { // Mask triggers - d += power; - } - - if(offset_diag == 0) - offset_diag = ppm-1; - else - offset_diag -= 1; - } - - offset_start -= 1; - words_deinterleaved.push_back(d); - } - - std::reverse(words_deinterleaved.begin(),words_deinterleaved.end()); - print_vector(d_debug, words_deinterleaved, "D", sizeof(uint8_t)*8); - - // Add to demodulated data - for(int i = 0; i < words_deinterleaved.size(); i++) { - d_demodulated.push_back(words_deinterleaved[i]); - } - - // Cleanup - d_words.clear(); - } - - int decoder_impl::decode(uint8_t* out_data, bool is_header) { - const uint8_t* prng = NULL; - const uint8_t shuffle_pattern[] = {7, 6, 3, 4, 2, 1, 0, 5}; - - if(is_header) { - prng = prng_header; - } else { - if(d_sf == 7) - prng = prng_payload_sf7; - else if(d_sf == 8) - prng = prng_payload_sf8; - else if(d_sf == 9) - prng = prng_payload_sf9; - else if(d_sf == 10) - prng = prng_payload_sf10; - else if(d_sf == 11) - prng = prng_payload_sf11; - else if(d_sf == 12) - prng = prng_payload_sf12; - else - prng = prng_payload_sf7; - } - - deshuffle(shuffle_pattern, is_header); - dewhiten(prng); - hamming_decode(out_data); - - // Nibbles are reversed TODO why is this? - nibble_reverse(out_data, d_payload_length); - - // Print result - std::stringstream result; - for (int i = 0; i < d_payload_length; i++) { - result << " " << std::hex << std::setw(2) << std::setfill('0') << (int)out_data[i]; - } - - if(!is_header) { - d_data.insert(d_data.end(), out_data, out_data + d_payload_length); - std::cout << result.str() << std::endl; - - pmt::pmt_t payload_blob = pmt::make_blob(&d_data[0], sizeof(uint8_t) * (d_payload_length + 3)); - message_port_pub(pmt::mp("frames"), payload_blob); - } else { - d_data.insert(d_data.end(), out_data, out_data + 3); - std::cout << result.str(); - } - - return 0; - } - - void decoder_impl::deshuffle(const uint8_t* shuffle_pattern, bool is_header) { - uint32_t to_decode = d_demodulated.size(); - - if(is_header) - to_decode = 5; - - for(uint32_t i = 0; i < to_decode; i++) { - uint8_t original = d_demodulated[i]; - uint8_t result = 0; - - for(int j = 0; j < sizeof(shuffle_pattern) / sizeof(uint8_t); j++) { - uint8_t mask = pow(2, shuffle_pattern[j]); - if((original & mask) > 0) { - result += pow(2, j); + switch(this->d_sf) { + case 7: prng = gr::lora::prng_payload_sf7; break; + case 8: prng = gr::lora::prng_payload_sf8; break; + case 9: prng = gr::lora::prng_payload_sf9; break; + case 10: prng = gr::lora::prng_payload_sf10; break; + case 11: prng = gr::lora::prng_payload_sf11; break; + case 12: prng = gr::lora::prng_payload_sf12; break; + default: prng = gr::lora::prng_payload_sf7; break; } } - d_words_deshuffled.push_back(result); + this->deshuffle(shuffle_pattern, is_header); + this->dewhiten(prng); + this->hamming_decode(out_data); + + // Nibbles are reversed TODO why is this? + this->nibble_reverse(out_data, this->d_payload_length); + + // Print result + std::stringstream result; + + for (uint32_t i = 0; i < this->d_payload_length; i++) { + result << " " << std::hex << std::setw(2) << std::setfill('0') << (int)out_data[i]; + } + + if (!is_header) { + this->d_data.insert(this->d_data.end(), out_data, out_data + this->d_payload_length); + std::cout << result.str() << std::endl; + + pmt::pmt_t payload_blob = pmt::make_blob(&this->d_data[0], + sizeof(uint8_t) * (this->d_payload_length + 3)); + this->message_port_pub(pmt::mp("frames"), payload_blob); + } else { + this->d_data.insert(this->d_data.end(), out_data, out_data + 3); + std::cout << result.str(); + } + + return 0; } - //print_vector(d_debug, d_words_deshuffled, "S", sizeof(uint8_t)*8); - print_vector_raw(d_debug, d_words_deshuffled, sizeof(uint8_t)*8); - d_debug << std::endl; + void decoder_impl::deshuffle(const uint8_t *shuffle_pattern, bool is_header) { + const uint32_t to_decode = is_header ? 5 : this->d_demodulated.size(); + const uint32_t len = sizeof(shuffle_pattern) / sizeof(uint8_t); + uint8_t original, result; - // We're done with these words - if(is_header) - d_demodulated.erase(d_demodulated.begin(), d_demodulated.begin()+5); - else - d_demodulated.clear(); - } + for (uint32_t i = 0; i < to_decode; i++) { + original = this->d_demodulated[i]; + result = 0; - void decoder_impl::dewhiten(const uint8_t* prng) { - for(int i = 0; i < d_words_deshuffled.size(); i++) { - uint8_t xor_b = d_words_deshuffled[i] ^ prng[i]; - xor_b = (xor_b & 0xF0) >> 4 | (xor_b & 0x0F) << 4; // TODO: reverse bit order is performed here, but is probably due to mistake in whitening or interleaving - xor_b = (xor_b & 0xCC) >> 2 | (xor_b & 0x33) << 2; - xor_b = (xor_b & 0xAA) >> 1 | (xor_b & 0x55) << 1; - d_words_dewhitened.push_back(xor_b); - } - - print_vector(d_debug, d_words_dewhitened, "W", sizeof(uint8_t)*8); - - d_words_deshuffled.clear(); - } - - void decoder_impl::hamming_decode(uint8_t* out_data) { - uint8_t data_indices[4] = {1, 2, 3, 5}; - unsigned int n = ceil(d_words_dewhitened.size() * 4.0f / (4.0f + d_cr)); - fec_scheme fs = LIQUID_FEC_HAMMING84; - - if(d_cr == 4) { - hamming_decode_soft(&d_words_dewhitened[0], d_words_dewhitened.size(), out_data); - d_words_dewhitened.clear(); - return; - } else if(d_cr == 3) { - hamming_decode_soft(&d_words_dewhitened[0], d_words_dewhitened.size(), out_data); - d_words_dewhitened.clear(); - return; - } else if(d_cr == 2) { - fec_extract_data_only(&d_words_dewhitened[0], d_words_dewhitened.size(), data_indices, 4, out_data); - d_words_dewhitened.clear(); - return; - } else if(d_cr == 1) { // TODO: Report parity error to the user - fec_extract_data_only(&d_words_dewhitened[0], d_words_dewhitened.size(), data_indices, 4, out_data); - d_words_dewhitened.clear(); - return; - } - - /*fs = LIQUID_FEC_HAMMING84; - - unsigned int k = fec_get_enc_msg_length(fs, n); - fec hamming = fec_create(fs, NULL); - - fec_decode(hamming, n, &d_words_dewhitened[0], out_data); - - d_words_dewhitened.clear(); - fec_destroy(hamming);*/ - } - - void decoder_impl::nibble_reverse(uint8_t* out_data, int len) { - for(int i = 0; i < len; i++) { - out_data[i] = ((out_data[i] & 0x0f) << 4) | ((out_data[i] & 0xf0) >> 4); - } - } - - void decoder_impl::determine_cfo(const gr_complex* samples) { - float instantaneous_phase[d_samples_per_symbol]; - float instantaneous_freq[d_samples_per_symbol]; - - // Determine instant phase - for(unsigned int i = 0; i < d_samples_per_symbol; i++) { - instantaneous_phase[i] = arg(samples[i]); - } - liquid_unwrap_phase(instantaneous_phase, d_samples_per_symbol); - - // Determine instant freq - for(unsigned int i = 1; i < d_samples_per_symbol; i++) { - float ifreq = (instantaneous_phase[i] - instantaneous_phase[i-1]) / (2.0f * M_PI) * d_samples_per_second; - instantaneous_freq[i-1] = ifreq; - } + for (uint32_t j = 0; j < len; j++) { + if (original & (1 << shuffle_pattern[j])) { + result |= 1 << j; + } + } float sum = 0.0f; for(int i = 0; i < d_samples_per_symbol-1; i++) { sum += instantaneous_freq[i]; - } - sum /= d_samples_per_symbol-1; + #ifndef NDEBUG + //print_vector(d_debug, d_words_deshuffled, "S", sizeof(uint8_t)*8); + print_vector_raw(this->d_debug, this->d_words_deshuffled, sizeof(uint8_t) * 8); + this->d_debug << std::endl; + #endif - d_cfo_estimation = sum; + // We're done with these words + if (is_header){ + this->d_demodulated.erase(this->d_demodulated.begin(), this->d_demodulated.begin() + 5); + this->d_demodulated.clear(); + } + } + + void decoder_impl::dewhiten(const uint8_t *prng) { + uint32_t i, len = this->d_words_deshuffled.size(); /*d_cfo_estimation = (*std::max_element(instantaneous_freq, instantaneous_freq+d_samples_per_symbol-1) + *std::min_element(instantaneous_freq, instantaneous_freq+d_samples_per_symbol-1)) / 2;*/ } @@ -614,81 +583,96 @@ namespace gr { void decoder_impl::correct_cfo(gr_complex* samples, int num_samples) { for(uint32_t i = 0; i < num_samples; i++) { samples[i] = samples[i] * gr_expj(2.0f * M_PI * -d_cfo_estimation * (d_dt * i)); - } - } - - int decoder_impl::find_preamble_start(gr_complex* samples) { - for(int i = 0; i < d_samples_per_symbol; i++) { - unsigned int c = get_shift_fft(&samples[i]); - if(c == 0) { - return i; - } - } - } - - int decoder_impl::find_preamble_start_fast(gr_complex* samples, uint32_t len) { - int decimation = d_corr_decim_factor; - int decim_size = d_samples_per_symbol / decimation; - float decim[decimation]; - float gradient[decimation]; - uint32_t rising = 0; - uint32_t rising_required = 2; - - gradient[0] = 0.0f; - - - for(int i = 0; i < decimation; i++) { - float s[2] = { - arg(samples[i*decim_size]), - arg(samples[(i+1)*decim_size]) - }; - liquid_unwrap_phase(s, 2); - - decim[i] = (s[1] - s[0]) / (2.0f * M_PI) * d_samples_per_second; + this->d_words_deshuffled.clear(); } - for(int i = 1; i < decimation; i++) { - gradient[i] = decim[i] - decim[i-1]; - if(gradient[i] > gradient[i-1]) - rising++; - if(rising >= rising_required && gradient[i] <= -20000) { // TODO: Make this a bit more logical, e.g. d_bw / decimation * 2 -> 2 steps down - return i*decim_size; + void decoder_impl::hamming_decode(uint8_t *out_data) { + uint8_t data_indices[4] = {1, 2, 3, 5}; + + switch(this->d_cr) { + case 4: case 3: + gr::lora::hamming_decode_soft(&this->d_words_dewhitened[0], this->d_words_dewhitened.size(), out_data); + break; + case 2: case 1: // TODO: Report parity error to the user + gr::lora::fec_extract_data_only(&this->d_words_dewhitened[0], this->d_words_dewhitened.size(), data_indices, 4, out_data); + break; } - //d_debug << "G:" << gradient[i] << std::endl; + + this->d_words_dewhitened.clear(); + + /* + fec_scheme fs = LIQUID_FEC_HAMMING84; + unsigned int n = ceil(this->d_words_dewhitened.size() * 4.0f / (4.0f + d_cr)); + + unsigned int k = fec_get_enc_msg_length(fs, n); + fec hamming = fec_create(fs, NULL); + + fec_decode(hamming, n, &d_words_dewhitened[0], out_data); + + d_words_dewhitened.clear(); + fec_destroy(hamming);*/ } - return -1; - } - - uint8_t decoder_impl::lookup_cr(uint8_t bytevalue) { - switch (bytevalue & 0x0f) { - case 0x01: { - return 4; - break; - } - case 0x0f: { - return 3; - break; - } - case 0x0d: { - return 2; - break; - } - case 0x0b: { - return 1; - break; - } - default: { - return 4; - break; + void decoder_impl::nibble_reverse(uint8_t *out_data, int len) { + for (int i = 0; i < len; i++) { + out_data[i] = ((out_data[i] & 0x0f) << 4) | ((out_data[i] & 0xf0) >> 4); } } - } - void decoder_impl::msg_raw_chirp_debug(const gr_complex* raw_samples, uint32_t num_samples) { - pmt::pmt_t chirp_blob = pmt::make_blob(raw_samples, sizeof(gr_complex) * num_samples); - message_port_pub(pmt::mp("debug"), chirp_blob); - } + void decoder_impl::determine_cfo(const gr_complex *samples) { + float instantaneous_phase[this->d_samples_per_symbol]; +// float instantaneous_freq [this->d_samples_per_symbol]; + double div = (double) this->d_samples_per_second / (2.0f * M_PI); + + // Determine instant phase + for (unsigned int i = 0; i < this->d_samples_per_symbol; i++) { + instantaneous_phase[i] = arg(samples[i]); + } + + liquid_unwrap_phase(instantaneous_phase, this->d_samples_per_symbol); + + // Determine instant freq +// for (unsigned int i = 1; i < this->d_samples_per_symbol; i++) { +// instantaneous_freq[i - 1] = (float)((instantaneous_phase[i] - instantaneous_phase[i - 1]) * div); +// } + + float sum = 0.0f; + + for (uint32_t i = 1; i < this->d_samples_per_symbol; i++) { + sum += (float)((instantaneous_phase[i] - instantaneous_phase[i - 1]) * div); + } + + this->d_cfo_estimation = sum / (float)(this->d_samples_per_symbol - 1); + + /*d_cfo_estimation = (*std::max_element(instantaneous_freq, instantaneous_freq+d_samples_per_symbol-1) + *std::min_element(instantaneous_freq, instantaneous_freq+d_samples_per_symbol-1)) / 2;*/ + } + + void decoder_impl::correct_cfo(gr_complex *samples, uint32_t num_samples) { + const float mul = 2.0f * M_PI * -this->d_cfo_estimation * this->d_dt; + + for (uint32_t i = 0; i < num_samples; i++) { + samples[i] *= gr_expj(mul * i); + } + } + + int decoder_impl::find_preamble_start(gr_complex *samples) { + for (uint32_t i = 0; i < this->d_samples_per_symbol; i++) { + if (!this->get_shift_fft(&samples[i])) + return i; + } + + return -1; + } + + int decoder_impl::find_preamble_start_fast(gr_complex *samples, uint32_t len) { + (void) len; + + const uint32_t decimation = this->d_corr_decim_factor; + const uint32_t decim_size = this->d_samples_per_symbol / decimation; + + const float mul = (float)this->d_samples_per_second / (2.0f * M_PI); + uint32_t rising = 0; + static const uint32_t rising_required = 2; void decoder_impl::msg_lora_frame(const uint8_t *frame_bytes, uint32_t frame_len) { @@ -716,107 +700,171 @@ namespace gr { d_state = SYNC; consume_each(i+index_correction); break; - } - } - consume_each(2*d_samples_per_symbol); - break; - } - case SYNC: { - double c = detect_downchirp(&input[0], d_samples_per_symbol); - d_debug << "Cd: " << c << std::endl; - - if(c > 0.98f) { - d_debug << "SYNC: " << c << std::endl; - // Debug stuff - samples_to_file("/tmp/sync", &input[0], d_samples_per_symbol, sizeof(gr_complex)); - - d_state = PAUSE; - consume_each(d_samples_per_symbol); - } else { - d_corr_fails++; - if(d_corr_fails > 32) { - d_state = DETECT; - d_debug << "Lost sync" << std::endl; - } - consume_each(d_samples_per_symbol); - } - break; - } - case PAUSE: { - d_state = DECODE_HEADER; - - //samples_debug(input, d_samples_per_symbol + d_delay_after_sync); - consume_each(d_samples_per_symbol + d_delay_after_sync); - break; - } - case DECODE_HEADER: { - d_cr = 4; - if(demodulate(input, true)) { - uint8_t decoded[3]; - d_payload_length = 3; // TODO: A bit messy. I think it's better to make an internal decoded std::vector - decode(decoded, true); - - nibble_reverse(decoded, 1); // TODO: Why? Endianess? - d_payload_length = decoded[0]; - d_cr = lookup_cr(decoded[1]); - - int symbols_per_block = d_cr + 4; - int bits_needed = ((d_payload_length * 8) + 16); - float symbols_needed = float(bits_needed) * (symbols_per_block / 4.0f) / float(d_sf); - int blocks_needed = ceil(symbols_needed / symbols_per_block); - d_payload_symbols = blocks_needed * symbols_per_block; - - d_debug << "LEN: " << d_payload_length << " (" << d_payload_symbols << " symbols)" << std::endl; - - d_state = DECODE_PAYLOAD; - } - - msg_raw_chirp_debug(raw_input, d_samples_per_symbol); - //samples_debug(input, d_samples_per_symbol); - consume_each(d_samples_per_symbol); - break; - } - case DECODE_PAYLOAD: { - if(demodulate(input, false)) { - d_payload_symbols -= (4 + d_cr); - - if(d_payload_symbols <= 0) { - uint8_t decoded[d_payload_length]; - memset(decoded, 0x00, d_payload_length); - decode(decoded, false); - - d_state = DETECT; - d_data.clear(); - } - } - - msg_raw_chirp_debug(raw_input, d_samples_per_symbol); - //samples_debug(input, d_samples_per_symbol); - consume_each(d_samples_per_symbol); - break; - } - case STOP: { - consume_each(d_samples_per_symbol); - break; - } - default: { - std::cout << "Shouldn't happen\n"; - break; - } + void decoder_impl::msg_raw_chirp_debug(const gr_complex *raw_samples, uint32_t num_samples) { + pmt::pmt_t chirp_blob = pmt::make_blob(raw_samples, sizeof(gr_complex) * num_samples); + message_port_pub(pmt::mp("debug"), chirp_blob); } - // Tell runtime system how many output items we produced. - return 0; - } + void decoder_impl::msg_lora_frame(const uint8_t *frame_bytes, uint32_t frame_len) { + // ?? No implementation + } - void decoder_impl::set_sf(uint8_t sf) { - if(sf >= 7 && sf <= 13) - d_sf = sf; - } + int decoder_impl::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) { + (void) noutput_items; + (void) output_items; - void decoder_impl::set_samp_rate(float samp_rate) { - d_samples_per_second = samp_rate; - } + gr_complex *input = (gr_complex *) input_items[0]; + gr_complex *raw_input = (gr_complex *) input_items[1]; +// float *out = (float *)output_items[0]; - } /* namespace lora */ + switch (this->d_state) { + case gr::lora::DecoderState::DETECT: { + int i = this->find_preamble_start_fast(&input[0], 2 * this->d_samples_per_symbol); + + if (i != -1) { + uint32_t c_window = std::min(2 * this->d_samples_per_symbol - i, + this->d_samples_per_symbol); + int32_t index_correction = 0; + float c = this->detect_upchirp(&input[i], + c_window, + this->d_samples_per_symbol / this->d_corr_decim_factor, + &index_correction); + + if (c > 0.8f) { + #ifndef NDEBUG + this->d_debug << "Cu: " << c << std::endl; + #endif + this->samples_to_file("/tmp/detectb", &input[i], this->d_samples_per_symbol, sizeof(gr_complex)); + this->samples_to_file("/tmp/detect", &input[i + index_correction], this->d_samples_per_symbol, sizeof(gr_complex)); + this->d_corr_fails = 0; + this->d_state = gr::lora::DecoderState::SYNC; + this->consume_each(i + index_correction); + break; + } + } + + this->consume_each(2 * this->d_samples_per_symbol); + break; + } + + case gr::lora::DecoderState::SYNC: { + double c = this->detect_downchirp(&input[0], this->d_samples_per_symbol); + #ifndef NDEBUG + this->d_debug << "Cd: " << c << std::endl; + #endif + + if (c > 0.98f) { + #ifndef NDEBUG + this->d_debug << "SYNC: " << c << std::endl; + #endif + // Debug stuff + this->samples_to_file("/tmp/sync", &input[0], this->d_samples_per_symbol, sizeof(gr_complex)); + + this->d_state = gr::lora::DecoderState::PAUSE; + } else { + this->d_corr_fails++; + + if (this->d_corr_fails > 32) { + this->d_state = gr::lora::DecoderState::DETECT; + #ifndef NDEBUG + this->d_debug << "Lost sync" << std::endl; + #endif + } + } + + this->consume_each(this->d_samples_per_symbol); + break; + } + + case gr::lora::DecoderState::PAUSE: { + this->d_state = gr::lora::DecoderState::DECODE_HEADER; + + //samples_debug(input, d_samples_per_symbol + d_delay_after_sync); + this->consume_each(this->d_samples_per_symbol + this->d_delay_after_sync); + break; + } + + case gr::lora::DecoderState::DECODE_HEADER: { + this->d_cr = 4; + + if (this->demodulate(input, true)) { + uint8_t decoded[3]; + // TODO: A bit messy. I think it's better to make an internal decoded std::vector + this->d_payload_length = 3; + + this->decode(decoded, true); + + this->nibble_reverse(decoded, 1); // TODO: Why? Endianess? + this->d_payload_length = decoded[0]; + this->d_cr = this->lookup_cr(decoded[1]); + + int symbols_per_block = this->d_cr + 4; + int bits_needed = this->d_payload_length * 8 + 16; + float symbols_needed = float(bits_needed) * (symbols_per_block / 4.0f) / float(this->d_sf); + int blocks_needed = ceil(symbols_needed / symbols_per_block); + this->d_payload_symbols = blocks_needed * symbols_per_block; + + #ifndef NDEBUG + this->d_debug << "LEN: " << this->d_payload_length << " (" << this->d_payload_symbols << " symbols)" << std::endl; + #endif + + this->d_state = gr::lora::DecoderState::DECODE_PAYLOAD; + } + + this->msg_raw_chirp_debug(raw_input, this->d_samples_per_symbol); + //samples_debug(input, d_samples_per_symbol); + this->consume_each(this->d_samples_per_symbol); + break; + } + + case gr::lora::DecoderState::DECODE_PAYLOAD: { + if (this->demodulate(input, false)) { + this->d_payload_symbols -= (4 + this->d_cr); + + if (this->d_payload_symbols <= 0) { + uint8_t decoded[this->d_payload_length] = { 0 }; + + this->decode(decoded, false); + + this->d_state = gr::lora::DecoderState::DETECT; + this->d_data.clear(); + } + } + + this->msg_raw_chirp_debug(raw_input, this->d_samples_per_symbol); + //samples_debug(input, d_samples_per_symbol); + this->consume_each(this->d_samples_per_symbol); + break; + } + + case gr::lora::DecoderState::STOP: { + this->consume_each(this->d_samples_per_symbol); + break; + } + + default: { + std::cerr << "LoRa Decoder: No state! Shouldn't happen\n"; + break; + } + } + + // Tell runtime system how many output items we produced. + return 0; + } + + void decoder_impl::set_sf(uint8_t sf) { + (void) sf; + std::cerr << "[LoRa Decoder] WARNING : Setting the spreading factor during execution is currently not supported." << std::endl + << "Nothing set, kept SF of " << this->d_sf << "." << std::endl; + } + + void decoder_impl::set_samp_rate(float samp_rate) { + (void) samp_rate; + std::cerr << "[LoRa Decoder] WARNING : Setting the sample rate during execution is currently not supported." << std::endl + << "Nothing set, kept SR of " << this->d_samples_per_second << "." << std::endl; + } + + } /* namespace lora */ } /* namespace gr */ diff --git a/lib/decoder_impl.h b/lib/decoder_impl.h index 8297205..f9be2c8 100644 --- a/lib/decoder_impl.h +++ b/lib/decoder_impl.h @@ -21,112 +21,124 @@ #ifndef INCLUDED_LORA_DECODER_IMPL_H #define INCLUDED_LORA_DECODER_IMPL_H -#include +#include +#include "lora/decoder.h" #include #include #include +#include #include -#define DECIMATOR_FILTER_SIZE 2*8*1+1 // 2*decim_factor*delay+1 +#define DECIMATOR_FILTER_SIZE (2*8*1 + 1) // 2*decim_factor*delay+1 namespace gr { - namespace lora { + namespace lora { - typedef enum decoder_state { - DETECT, - SYNC, - PAUSE, - DECODE_HEADER, - DECODE_PAYLOAD, - STOP - } decoder_state; + enum class DecoderState { + DETECT, + SYNC, + PAUSE, + DECODE_HEADER, + DECODE_PAYLOAD, + STOP + }; - class decoder_impl : public decoder - { - private: - decoder_state d_state; - std::vector d_downchirp; - std::vector d_upchirp; - std::vector d_downchirp_ifreq; - std::vector d_upchirp_ifreq; - std::vector d_fft; - std::vector d_mult; - uint8_t d_sf; - uint32_t d_bw; - uint8_t d_cr; - double d_bits_per_second; - uint32_t d_delay_after_sync; - uint32_t d_samples_per_second; - double d_symbols_per_second; - uint32_t d_bits_per_symbol; - uint32_t d_samples_per_symbol; - uint32_t d_number_of_bins; - uint32_t d_number_of_bins_hdr; - uint32_t d_compression; - uint32_t d_payload_symbols; - uint32_t d_payload_length; - uint32_t d_corr_fails; - std::vector d_words; - std::vector d_demodulated; - std::vector d_words_deshuffled; - std::vector d_words_dewhitened; - std::vector d_data; - std::ofstream d_debug_samples; - std::ofstream d_debug; - fftplan d_q; - float d_decim_h[DECIMATOR_FILTER_SIZE]; - uint32_t d_corr_decim_factor; - int d_decim_factor; - firdecim_crcf d_decim; - float d_cfo_estimation; - int d_cfo_step; - double d_dt; + class decoder_impl : public decoder { + private: + DecoderState d_state; - bool calc_energy_threshold(gr_complex* samples, int window_size, float threshold); - void build_ideal_chirps(void); - void samples_to_file(const std::string path, const gr_complex* v, int length, int elem_size); - void samples_debug(const gr_complex* v, int length); - float sliding_norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window, uint32_t slide, int32_t* index); - float norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window); - float detect_downchirp(const gr_complex *samples, uint32_t window); - float detect_upchirp(const gr_complex *samples_1, uint32_t window, uint32_t slide, int32_t* index); - float cross_correlate(const gr_complex *samples_1, const gr_complex *samples_2, int window); - unsigned int get_shift_fft(gr_complex* samples); - void determine_cfo(const gr_complex* samples); - void correct_cfo(gr_complex* samples, int num_samples); - int find_preamble_start(gr_complex* samples); - int find_preamble_start_fast(gr_complex* samples, uint32_t len); - unsigned int max_frequency_gradient_idx(gr_complex* samples); - bool demodulate(gr_complex* samples, bool is_header); - void deinterleave(int ppm); - int decode(uint8_t* out_data, bool is_header); - void deshuffle(const uint8_t* shuffle_pattern, bool is_header); - void dewhiten(const uint8_t* prng); - void hamming_decode(uint8_t* out_data); - void nibble_reverse(uint8_t* out_data, int len); - float stddev(const float *values, int len, float mean); - inline void instantaneous_phase(const gr_complex* in_samples, float* out_iphase, uint32_t window); - void instantaneous_frequency(const gr_complex* in_samples, float* out_ifreq, uint32_t window); - uint8_t lookup_cr(uint8_t bytevalue); - void msg_raw_chirp_debug(const gr_complex *raw_samples, uint32_t num_samples); - void msg_lora_frame(const uint8_t *frame_bytes, uint32_t frame_len); + /// using std::complex = gr_complex + std::vector d_downchirp; + std::vector d_upchirp; + std::vector d_downchirp_ifreq; + std::vector d_upchirp_ifreq; + std::vector d_fft; + std::vector d_mult; + uint8_t d_sf; + uint32_t d_bw; + uint8_t d_cr; + double d_bits_per_second; + uint32_t d_delay_after_sync; + uint32_t d_samples_per_second; + double d_symbols_per_second; + uint32_t d_bits_per_symbol; + uint32_t d_samples_per_symbol; + uint32_t d_number_of_bins; + uint32_t d_number_of_bins_hdr; + uint32_t d_compression; + uint32_t d_payload_symbols; + uint32_t d_payload_length; + uint32_t d_corr_fails; - public: - decoder_impl(float samp_rate, int sf); - ~decoder_impl(); + std::vector d_words; + std::vector d_demodulated; + std::vector d_words_deshuffled; + std::vector d_words_dewhitened; + std::vector d_data; - // Where all the action really happens - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + std::ofstream d_debug_samples; + std::ofstream d_debug; - // GRC interfaces - virtual void set_sf(uint8_t sf); - virtual void set_samp_rate(float samp_rate); - }; + fftplan d_q; - } // namespace lora + float d_decim_h[DECIMATOR_FILTER_SIZE]; + uint32_t d_corr_decim_factor; + int d_decim_factor; + firdecim_crcf d_decim = nullptr; + float d_cfo_estimation; + int d_cfo_step; + double d_dt; + + bool calc_energy_threshold(gr_complex *samples, int window_size, float threshold); + void build_ideal_chirps(void); + void samples_to_file(const std::string path, const gr_complex *v, uint32_t length, uint32_t elem_size); + void samples_debug(const gr_complex *v, uint32_t length); + float sliding_norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window, uint32_t slide, int32_t *index); + float norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window); + float detect_downchirp(const gr_complex *samples, uint32_t window); + float detect_upchirp(const gr_complex *samples_1, uint32_t window, uint32_t slide, int32_t *index); + float cross_correlate(const gr_complex *samples_1, const gr_complex *samples_2, int window); + + unsigned int get_shift_fft(gr_complex *samples); + + void determine_cfo(const gr_complex *samples); + void correct_cfo(gr_complex *samples, uint32_t num_samples); + int find_preamble_start(gr_complex *samples); + int find_preamble_start_fast(gr_complex *samples, uint32_t len); + + unsigned int max_frequency_gradient_idx(gr_complex *samples); + + bool demodulate(gr_complex *samples, bool is_header); + void deinterleave(uint32_t ppm); + int decode(uint8_t *out_data, bool is_header); + void deshuffle(const uint8_t *shuffle_pattern, bool is_header); + void dewhiten(const uint8_t *prng); + void hamming_decode(uint8_t *out_data); + void nibble_reverse(uint8_t *out_data, int len); + float stddev(const float *values, uint32_t len, float mean); + + inline void instantaneous_phase(const gr_complex *in_samples, float *out_iphase, uint32_t window); + void instantaneous_frequency(const gr_complex *in_samples, float *out_ifreq, uint32_t window); + + uint8_t lookup_cr(uint8_t bytevalue); + void msg_raw_chirp_debug(const gr_complex *raw_samples, uint32_t num_samples); + void msg_lora_frame(const uint8_t *frame_bytes, uint32_t frame_len); + + public: + decoder_impl(float samp_rate, uint8_t sf); + ~decoder_impl(); + + /// Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + + /// GRC interfaces + virtual void set_sf(uint8_t sf); + virtual void set_samp_rate(float samp_rate); + }; + } // namespace lora } // namespace gr #endif /* INCLUDED_LORA_DECODER_IMPL_H */ diff --git a/lib/tables.h b/lib/tables.h index 5648ea4..8f2a6ff 100644 --- a/lib/tables.h +++ b/lib/tables.h @@ -2,35 +2,35 @@ #define TABLES_H namespace gr { - namespace lora { - const uint8_t prng_header[] = { - 0x22, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + namespace lora { + const uint8_t prng_header[] = { + 0x22, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; - const uint8_t prng_payload_sf7[] = { // OK - 0xdc, 0xec, 0xb0, 0xf4, 0x9c, 0xfc, 0xc4, 0xdc, 0x10, 0xf8, 0x40, 0x34, 0xa8, 0x5c, 0xf0, 0x94, 0x60, 0x8, 0xf8, 0x48, 0xbc, 0x88, 0xa4, 0xd4, 0x14, 0xe4, 0x84, 0x38, 0x68, 0xec, 0xe4, 0xbc, 0xb0, 0x1c, 0x14, 0xa4, 0x3c, 0x4c, 0x90, 0x60, 0x84, 0x70, 0x20, 0x44, 0x4, 0x24, 0x80, 0x98, 0x40, 0xa4, 0x58, 0x4, 0xa0, 0x80, 0x98, 0x40, 0xa4, 0x10, 0x4c, 0x40, 0x60, 0xa8, 0x38, 0xb8, 0xa4, 0x80, 0x14, 0xc8, 0x84, 0xa0, 0x68, 0x68, 0xac, 0xbc, 0x18, 0x1c, 0x8c, 0xa4, 0xb8, 0x4c, 0xd8, 0x28, 0x64, 0xd8, 0x58, 0xdc, 0xb0, 0xa0, 0x9c, 0xd0, 0xc4, 0x44, 0x10, 0x7c, 0x8, 0xb4, 0x0, 0x5c, 0x68, 0x94, 0xe4, 0x8, 0xb0, 0x0, 0x5c, 0x20, 0xdc, 0x4c, 0xa0, 0x60, 0x98, 0x70, 0xec, 0xc, 0xac, 0xc4, 0x18, 0xa8, 0x8c, 0xb8, 0xf0, 0xc8, 0x38, 0x28, 0x54, 0xd8, 0x44, 0xdc, 0x7c, 0xe8, 0x34, 0x30, 0x5c, 0x74, 0xdc, 0x60, 0xa0, 0xf8, 0x98, 0xf4, 0xa4, 0x1c, 0x4, 0xc4, 0x80, 0xa8, 0x8, 0xb8, 0xb8, 0x80, 0xd8, 0x80, 0x2c, 0x40, 0xf0, 0x58, 0x60, 0xa0, 0xb0, 0xd0, 0x14, 0xc, 0x74, 0xd4, 0x38, 0xe4, 0x54, 0x70, 0xc, 0x44, 0xd4, 0x6c, 0xe4, 0x30, 0x70, 0x74, 0xc, 0x28, 0xc4, 0x50, 0xa8, 0x24, 0xf0, 0x20, 0x60, 0x14, 0xb0, 0xcc, 0x5c, 0x88, 0x94, 0xd4, 0x8, 0xe4, 0x48, 0x70, 0xc0, 0xc, 0x7c, 0x8c, 0x7c, 0x0, 0xbc, 0x68, 0xa4, 0xe4, 0x5c, 0xf8, 0x64, 0xbc, 0x10, 0xec, 0x50, 0xbc, 0xe4, 0x54, 0x38, 0x44, 0xec, 0x34, 0xbc, 0xd4, 0x54, 0x24, 0xc, 0x68, 0xd4, 0xf4, 0xe4, 0xb4, 0x38, 0x74, 0xa4, 0x28, 0x5c, 0x50, 0x2c, 0x24, 0xb8, 0x68, 0x80, 0xbc, 0xc8, 0x54, 0xe8, 0xc, 0x88, 0x9c, 0x8c, 0x4, 0x0, 0x8, 0x68, 0xb8, 0xe4, 0x90, 0xb0, 0x84, 0x14, 0x20, 0x74, 0x4c, 0x38, 0x60, 0x1c, 0x70, 0xa4, 0x44, 0x4c, 0x6c, 0x60, 0x30, 0x38, 0x3c, 0xec, 0x80, 0xbc, 0xc8, 0x1c, 0xa0, 0xec, 0x68, 0xe4, 0xf4, 0xf8, 0xb4, 0xf4, 0x3c, 0xc, 0xc8, 0xc4, 0x60, 0xe0, 0x38, 0x10, 0xa4, 0x18, 0x14, 0x4, 0xcc, 0x8, 0xc0, 0xb8, 0x34, 0xd8, 0x9c, 0x64, 0xc4, 0x10, 0x58, 0x50, 0xa0, 0xac, 0xd0, 0xd8, 0x44, 0xdc, 0x34, 0xa0, 0xd4, 0x98, 0x6c, 0xa4, 0x88, 0x4c, 0xc4, 0x28, 0xa8, 0x90, 0xb8, 0x3c, 0x80, 0x90, 0xc8, 0xcc, 0xe8, 0x88, 0xc0, 0xd4, 0x24, 0xac, 0x98, 0x90 - }; + const uint8_t prng_payload_sf7[] = { // OK + 0xdc, 0xec, 0xb0, 0xf4, 0x9c, 0xfc, 0xc4, 0xdc, 0x10, 0xf8, 0x40, 0x34, 0xa8, 0x5c, 0xf0, 0x94, 0x60, 0x8, 0xf8, 0x48, 0xbc, 0x88, 0xa4, 0xd4, 0x14, 0xe4, 0x84, 0x38, 0x68, 0xec, 0xe4, 0xbc, 0xb0, 0x1c, 0x14, 0xa4, 0x3c, 0x4c, 0x90, 0x60, 0x84, 0x70, 0x20, 0x44, 0x4, 0x24, 0x80, 0x98, 0x40, 0xa4, 0x58, 0x4, 0xa0, 0x80, 0x98, 0x40, 0xa4, 0x10, 0x4c, 0x40, 0x60, 0xa8, 0x38, 0xb8, 0xa4, 0x80, 0x14, 0xc8, 0x84, 0xa0, 0x68, 0x68, 0xac, 0xbc, 0x18, 0x1c, 0x8c, 0xa4, 0xb8, 0x4c, 0xd8, 0x28, 0x64, 0xd8, 0x58, 0xdc, 0xb0, 0xa0, 0x9c, 0xd0, 0xc4, 0x44, 0x10, 0x7c, 0x8, 0xb4, 0x0, 0x5c, 0x68, 0x94, 0xe4, 0x8, 0xb0, 0x0, 0x5c, 0x20, 0xdc, 0x4c, 0xa0, 0x60, 0x98, 0x70, 0xec, 0xc, 0xac, 0xc4, 0x18, 0xa8, 0x8c, 0xb8, 0xf0, 0xc8, 0x38, 0x28, 0x54, 0xd8, 0x44, 0xdc, 0x7c, 0xe8, 0x34, 0x30, 0x5c, 0x74, 0xdc, 0x60, 0xa0, 0xf8, 0x98, 0xf4, 0xa4, 0x1c, 0x4, 0xc4, 0x80, 0xa8, 0x8, 0xb8, 0xb8, 0x80, 0xd8, 0x80, 0x2c, 0x40, 0xf0, 0x58, 0x60, 0xa0, 0xb0, 0xd0, 0x14, 0xc, 0x74, 0xd4, 0x38, 0xe4, 0x54, 0x70, 0xc, 0x44, 0xd4, 0x6c, 0xe4, 0x30, 0x70, 0x74, 0xc, 0x28, 0xc4, 0x50, 0xa8, 0x24, 0xf0, 0x20, 0x60, 0x14, 0xb0, 0xcc, 0x5c, 0x88, 0x94, 0xd4, 0x8, 0xe4, 0x48, 0x70, 0xc0, 0xc, 0x7c, 0x8c, 0x7c, 0x0, 0xbc, 0x68, 0xa4, 0xe4, 0x5c, 0xf8, 0x64, 0xbc, 0x10, 0xec, 0x50, 0xbc, 0xe4, 0x54, 0x38, 0x44, 0xec, 0x34, 0xbc, 0xd4, 0x54, 0x24, 0xc, 0x68, 0xd4, 0xf4, 0xe4, 0xb4, 0x38, 0x74, 0xa4, 0x28, 0x5c, 0x50, 0x2c, 0x24, 0xb8, 0x68, 0x80, 0xbc, 0xc8, 0x54, 0xe8, 0xc, 0x88, 0x9c, 0x8c, 0x4, 0x0, 0x8, 0x68, 0xb8, 0xe4, 0x90, 0xb0, 0x84, 0x14, 0x20, 0x74, 0x4c, 0x38, 0x60, 0x1c, 0x70, 0xa4, 0x44, 0x4c, 0x6c, 0x60, 0x30, 0x38, 0x3c, 0xec, 0x80, 0xbc, 0xc8, 0x1c, 0xa0, 0xec, 0x68, 0xe4, 0xf4, 0xf8, 0xb4, 0xf4, 0x3c, 0xc, 0xc8, 0xc4, 0x60, 0xe0, 0x38, 0x10, 0xa4, 0x18, 0x14, 0x4, 0xcc, 0x8, 0xc0, 0xb8, 0x34, 0xd8, 0x9c, 0x64, 0xc4, 0x10, 0x58, 0x50, 0xa0, 0xac, 0xd0, 0xd8, 0x44, 0xdc, 0x34, 0xa0, 0xd4, 0x98, 0x6c, 0xa4, 0x88, 0x4c, 0xc4, 0x28, 0xa8, 0x90, 0xb8, 0x3c, 0x80, 0x90, 0xc8, 0xcc, 0xe8, 0x88, 0xc0, 0xd4, 0x24, 0xac, 0x98, 0x90 + }; - const uint8_t prng_payload_sf8[] = { - 0xbd, 0xdf, 0xa4, 0xfb, 0x16, 0x7f, 0x85, 0xfe, 0x40, 0xdf, 0x5b, 0xb0, 0xa2, 0x9e, 0xd0, 0x86, 0x26, 0x20, 0x68, 0x4f, 0xf7, 0x2a, 0xb6, 0xd3, 0x5e, 0x46, 0x97, 0x7c, 0x43, 0x7f, 0xe3, 0xb5, 0x73, 0x3e, 0x45, 0x83, 0x25, 0xcb, 0x9b, 0xe0, 0xc7, 0x13, 0x10, 0x51, 0x8, 0xad, 0x2, 0x98, 0x40, 0xa7, 0x5b, 0x4, 0xa2, 0x80, 0x9b, 0x1, 0xc7, 0x20, 0x5b, 0x4f, 0xe9, 0x2a, 0x7a, 0x98, 0xf4, 0xa7, 0xe, 0x4f, 0x8f, 0x61, 0x49, 0x79, 0xea, 0x94, 0x89, 0x1a, 0xc4, 0x7, 0xa8, 0x4a, 0x92, 0x8a, 0x76, 0x9d, 0x70, 0x4c, 0xb6, 0xab, 0x5e, 0xf2, 0x97, 0x62, 0x8, 0xf8, 0x2, 0xb5, 0x40, 0x3e, 0x5b, 0x83, 0xe9, 0x80, 0x31, 0x1, 0x5e, 0x20, 0xdc, 0x4f, 0xa2, 0x61, 0x9b, 0x32, 0x8c, 0x3e, 0x9a, 0xd8, 0x95, 0x22, 0x4e, 0x9a, 0xa0, 0xac, 0x23, 0x8e, 0x5d, 0x5, 0x64, 0xcf, 0xb9, 0xc1, 0xc4, 0x37, 0x2, 0xdd, 0xce, 0xe7, 0xe9, 0x58, 0xc9, 0xb1, 0xbf, 0x98, 0xa, 0xcd, 0xc0, 0x8b, 0x7b, 0xdd, 0xb2, 0xf, 0x54, 0x3, 0x6d, 0x60, 0xe2, 0x4f, 0x6e, 0x2e, 0xb9, 0xc3, 0x16, 0x5, 0x76, 0xb6, 0x2f, 0xe6, 0xd7, 0x30, 0x6c, 0x37, 0xc3, 0x62, 0x4a, 0xbb, 0xa1, 0x54, 0x5e, 0x4d, 0xfd, 0xc6, 0xa2, 0xee, 0xd4, 0xb2, 0x24, 0x3e, 0x23, 0xe9, 0x56, 0x3e, 0x8d, 0x53, 0x42, 0x6, 0x7b, 0x37, 0xf9, 0x9e, 0xf6, 0x86, 0xbc, 0x20, 0xcf, 0xe, 0xbc, 0x7d, 0xd7, 0x7b, 0x26, 0xdf, 0x61, 0xcb, 0x5d, 0x38, 0xe4, 0x54, 0x39, 0xe, 0xef, 0x87, 0xb8, 0xd5, 0x57, 0x67, 0x6e, 0xd8, 0x82, 0xeb, 0x4b, 0x3c, 0x7a, 0x56, 0xf4, 0xd, 0x45, 0x96, 0x31, 0xc6, 0x1b, 0x73, 0xc6, 0x95, 0x7b, 0x11, 0xb2, 0xa5, 0x1f, 0x9a, 0xc7, 0xe6, 0x30, 0x4f, 0x47, 0x2a, 0xeb, 0x1a, 0x63, 0xa7, 0x65, 0x54, 0x6e, 0xcf, 0x39, 0xe2, 0xdf, 0x5b, 0xb6, 0x51, 0x57, 0xe6, 0xe3, 0xb0, 0x38, 0x3e, 0xcf, 0xc2, 0xbc, 0xd7, 0x9c, 0xe2, 0x8c, 0x58, 0xb1, 0xca, 0x74, 0x3c, 0xb6, 0x9d, 0x5e, 0xae, 0xfc, 0xe5, 0xe9, 0xf8, 0xa9, 0xb5, 0x5b, 0x3e, 0xb7, 0xd9, 0x7, 0x61, 0x28, 0x3a, 0x90, 0x7e, 0x76, 0xb3, 0x3f, 0xcb, 0x5f, 0xab, 0xee, 0xf3, 0xeb, 0x72, 0xc0, 0xb3, 0x28, 0x5c, 0xd9, 0x4d, 0xb6, 0x9d, 0x57, 0x4c, 0xa0, 0x29, 0x92, 0xb9, 0x1d, 0x83, 0x95, 0xd3, 0x8e, 0x2b, 0xe9, 0xf3, 0xa2, 0x29, 0x25, 0x15, 0x40, 0xcf, 0x6d, 0xca, 0x89, 0xd6, 0xd4, 0xa1, 0xc3, 0x51, 0x39, 0x4d, 0x85, 0x8d, 0x49, 0x44, 0xe8, 0xe2, 0xbb, 0x1a, 0x84, 0x0, 0x49, 0x98, 0xec, 0x65, 0x72, 0x10, 0x6e, 0x80, 0x40, 0xdd, 0x76, 0x65, 0x3b, 0x51, 0x8e, 0x2, 0xb8, 0x70, 0xd7, 0xe2, 0xa7, 0x9a, 0x48, 0xab, 0xc2, 0x38, 0x7d, 0x5e, 0xbe, 0x6, 0x86, 0x4c, 0x9, 0x72, 0xaf, 0xf4, 0x58, 0x9e, 0x3c, 0x80, 0xed, 0xdd, 0xa5, 0x2e, 0x55, 0xf8, 0xbc, 0xd8, 0xed, 0x4d, 0xb9, 0xa0, 0x16, 0xfe, 0x5f, 0xf9, 0xde, 0x79, 0xa7, 0x34, 0xd8, 0x37, 0xf6, 0xb9, 0x77, 0x5a, 0x6b, 0x2e, 0x76, 0xf8, 0x36, 0xb5, 0x8b, 0xc3, 0xc2, 0xe2, 0xc1, 0x53, 0x38, 0xa, 0xfd, 0x2b, 0xf2, 0x83, 0xf5, 0x64, 0x25, 0x5e, 0x33, 0x49, 0x50, 0xfb, 0x64, 0xd5, 0xa2, 0x41, 0x21, 0x85, 0x5c, 0x41, 0x25, 0x4d, 0x9, 0xe6, 0xe3, 0xa5, 0x79, 0xd9, 0x77, 0x6, 0x6e, 0x4c, 0xc0, 0x77, 0x35, 0xfc, 0x11, 0xd5, 0x5d, 0xa, 0x97, 0x50, 0x5, 0xa9, 0xe9, 0xb3, 0x7b, 0x79, 0x96, 0x15, 0x13, 0x4, 0x8f, 0x62, 0x91, 0x5e, 0x74, 0x12, 0x75, 0x9e, 0x3e, 0xad, 0x4b, 0x97, 0xe3, 0xf0, 0x8a, 0x3, 0x41, 0x60, 0xd1, 0xd2, 0x4b, 0xbb, 0xda, 0x3f, 0x3d - }; + const uint8_t prng_payload_sf8[] = { + 0xbd, 0xdf, 0xa4, 0xfb, 0x16, 0x7f, 0x85, 0xfe, 0x40, 0xdf, 0x5b, 0xb0, 0xa2, 0x9e, 0xd0, 0x86, 0x26, 0x20, 0x68, 0x4f, 0xf7, 0x2a, 0xb6, 0xd3, 0x5e, 0x46, 0x97, 0x7c, 0x43, 0x7f, 0xe3, 0xb5, 0x73, 0x3e, 0x45, 0x83, 0x25, 0xcb, 0x9b, 0xe0, 0xc7, 0x13, 0x10, 0x51, 0x8, 0xad, 0x2, 0x98, 0x40, 0xa7, 0x5b, 0x4, 0xa2, 0x80, 0x9b, 0x1, 0xc7, 0x20, 0x5b, 0x4f, 0xe9, 0x2a, 0x7a, 0x98, 0xf4, 0xa7, 0xe, 0x4f, 0x8f, 0x61, 0x49, 0x79, 0xea, 0x94, 0x89, 0x1a, 0xc4, 0x7, 0xa8, 0x4a, 0x92, 0x8a, 0x76, 0x9d, 0x70, 0x4c, 0xb6, 0xab, 0x5e, 0xf2, 0x97, 0x62, 0x8, 0xf8, 0x2, 0xb5, 0x40, 0x3e, 0x5b, 0x83, 0xe9, 0x80, 0x31, 0x1, 0x5e, 0x20, 0xdc, 0x4f, 0xa2, 0x61, 0x9b, 0x32, 0x8c, 0x3e, 0x9a, 0xd8, 0x95, 0x22, 0x4e, 0x9a, 0xa0, 0xac, 0x23, 0x8e, 0x5d, 0x5, 0x64, 0xcf, 0xb9, 0xc1, 0xc4, 0x37, 0x2, 0xdd, 0xce, 0xe7, 0xe9, 0x58, 0xc9, 0xb1, 0xbf, 0x98, 0xa, 0xcd, 0xc0, 0x8b, 0x7b, 0xdd, 0xb2, 0xf, 0x54, 0x3, 0x6d, 0x60, 0xe2, 0x4f, 0x6e, 0x2e, 0xb9, 0xc3, 0x16, 0x5, 0x76, 0xb6, 0x2f, 0xe6, 0xd7, 0x30, 0x6c, 0x37, 0xc3, 0x62, 0x4a, 0xbb, 0xa1, 0x54, 0x5e, 0x4d, 0xfd, 0xc6, 0xa2, 0xee, 0xd4, 0xb2, 0x24, 0x3e, 0x23, 0xe9, 0x56, 0x3e, 0x8d, 0x53, 0x42, 0x6, 0x7b, 0x37, 0xf9, 0x9e, 0xf6, 0x86, 0xbc, 0x20, 0xcf, 0xe, 0xbc, 0x7d, 0xd7, 0x7b, 0x26, 0xdf, 0x61, 0xcb, 0x5d, 0x38, 0xe4, 0x54, 0x39, 0xe, 0xef, 0x87, 0xb8, 0xd5, 0x57, 0x67, 0x6e, 0xd8, 0x82, 0xeb, 0x4b, 0x3c, 0x7a, 0x56, 0xf4, 0xd, 0x45, 0x96, 0x31, 0xc6, 0x1b, 0x73, 0xc6, 0x95, 0x7b, 0x11, 0xb2, 0xa5, 0x1f, 0x9a, 0xc7, 0xe6, 0x30, 0x4f, 0x47, 0x2a, 0xeb, 0x1a, 0x63, 0xa7, 0x65, 0x54, 0x6e, 0xcf, 0x39, 0xe2, 0xdf, 0x5b, 0xb6, 0x51, 0x57, 0xe6, 0xe3, 0xb0, 0x38, 0x3e, 0xcf, 0xc2, 0xbc, 0xd7, 0x9c, 0xe2, 0x8c, 0x58, 0xb1, 0xca, 0x74, 0x3c, 0xb6, 0x9d, 0x5e, 0xae, 0xfc, 0xe5, 0xe9, 0xf8, 0xa9, 0xb5, 0x5b, 0x3e, 0xb7, 0xd9, 0x7, 0x61, 0x28, 0x3a, 0x90, 0x7e, 0x76, 0xb3, 0x3f, 0xcb, 0x5f, 0xab, 0xee, 0xf3, 0xeb, 0x72, 0xc0, 0xb3, 0x28, 0x5c, 0xd9, 0x4d, 0xb6, 0x9d, 0x57, 0x4c, 0xa0, 0x29, 0x92, 0xb9, 0x1d, 0x83, 0x95, 0xd3, 0x8e, 0x2b, 0xe9, 0xf3, 0xa2, 0x29, 0x25, 0x15, 0x40, 0xcf, 0x6d, 0xca, 0x89, 0xd6, 0xd4, 0xa1, 0xc3, 0x51, 0x39, 0x4d, 0x85, 0x8d, 0x49, 0x44, 0xe8, 0xe2, 0xbb, 0x1a, 0x84, 0x0, 0x49, 0x98, 0xec, 0x65, 0x72, 0x10, 0x6e, 0x80, 0x40, 0xdd, 0x76, 0x65, 0x3b, 0x51, 0x8e, 0x2, 0xb8, 0x70, 0xd7, 0xe2, 0xa7, 0x9a, 0x48, 0xab, 0xc2, 0x38, 0x7d, 0x5e, 0xbe, 0x6, 0x86, 0x4c, 0x9, 0x72, 0xaf, 0xf4, 0x58, 0x9e, 0x3c, 0x80, 0xed, 0xdd, 0xa5, 0x2e, 0x55, 0xf8, 0xbc, 0xd8, 0xed, 0x4d, 0xb9, 0xa0, 0x16, 0xfe, 0x5f, 0xf9, 0xde, 0x79, 0xa7, 0x34, 0xd8, 0x37, 0xf6, 0xb9, 0x77, 0x5a, 0x6b, 0x2e, 0x76, 0xf8, 0x36, 0xb5, 0x8b, 0xc3, 0xc2, 0xe2, 0xc1, 0x53, 0x38, 0xa, 0xfd, 0x2b, 0xf2, 0x83, 0xf5, 0x64, 0x25, 0x5e, 0x33, 0x49, 0x50, 0xfb, 0x64, 0xd5, 0xa2, 0x41, 0x21, 0x85, 0x5c, 0x41, 0x25, 0x4d, 0x9, 0xe6, 0xe3, 0xa5, 0x79, 0xd9, 0x77, 0x6, 0x6e, 0x4c, 0xc0, 0x77, 0x35, 0xfc, 0x11, 0xd5, 0x5d, 0xa, 0x97, 0x50, 0x5, 0xa9, 0xe9, 0xb3, 0x7b, 0x79, 0x96, 0x15, 0x13, 0x4, 0x8f, 0x62, 0x91, 0x5e, 0x74, 0x12, 0x75, 0x9e, 0x3e, 0xad, 0x4b, 0x97, 0xe3, 0xf0, 0x8a, 0x3, 0x41, 0x60, 0xd1, 0xd2, 0x4b, 0xbb, 0xda, 0x3f, 0x3d + }; - const uint8_t prng_payload_sf9[] = { - 0xfd, 0xbe, 0x94, 0xef, 0x1a, 0xf7, 0x7, 0xfd, 0x1, 0xff, 0xb, 0x94, 0xba, 0x1a, 0xda, 0x7, 0x64, 0x1, 0x78, 0xb, 0xdf, 0xba, 0xb0, 0xda, 0x9e, 0x64, 0x86, 0x78, 0xb, 0xdf, 0xf1, 0xb0, 0x3b, 0x9e, 0x57, 0x86, 0x2d, 0xb, 0xb9, 0xf1, 0x83, 0x3b, 0x80, 0x57, 0x1, 0x2d, 0x40, 0xb9, 0x10, 0x83, 0x47, 0x80, 0xa8, 0x3, 0x99, 0x41, 0xa3, 0x12, 0x5f, 0x3, 0x69, 0x8, 0x79, 0x98, 0xf4, 0xa7, 0xe, 0x5f, 0xcf, 0x6d, 0xe9, 0x79, 0xab, 0xf6, 0xb9, 0x2e, 0xd8, 0xcf, 0x2e, 0x41, 0xd1, 0x2b, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x7, 0x27, 0x60, 0x48, 0x14, 0xb8, 0x88, 0x9c, 0x48, 0x86, 0xa1, 0x60, 0x3, 0x4, 0x16, 0x94, 0x4e, 0x42, 0xa9, 0xa1, 0xf9, 0x3, 0xc8, 0x16, 0x3e, 0x46, 0x98, 0xab, 0x8e, 0xf9, 0xf1, 0xe8, 0x3b, 0x32, 0x57, 0x9e, 0xe7, 0x8c, 0x18, 0xf1, 0x80, 0x3f, 0x9e, 0x5f, 0xcd, 0xe7, 0xe8, 0x58, 0xe9, 0xb1, 0x9f, 0x92, 0x82, 0xcf, 0x0, 0xea, 0x2b, 0x88, 0xbe, 0xaf, 0x56, 0x82, 0x2e, 0x8, 0x92, 0x6b, 0x17, 0xae, 0x3b, 0x4a, 0xd7, 0x2a, 0x66, 0x92, 0x13, 0x76, 0x21, 0x3b, 0xa5, 0xd3, 0xd3, 0x65, 0x26, 0x13, 0x2, 0x41, 0x52, 0xad, 0x46, 0xd3, 0xa8, 0x26, 0xb2, 0x23, 0x52, 0x12, 0xb3, 0xce, 0x97, 0xa9, 0xc6, 0x33, 0x30, 0x72, 0x27, 0xbf, 0x7b, 0x1d, 0x7b, 0xc7, 0x9d, 0x30, 0xeb, 0x27, 0x38, 0x73, 0xd6, 0x79, 0x2f, 0x9f, 0x3, 0xeb, 0x39, 0x2c, 0xe8, 0xd6, 0x7b, 0x27, 0x9d, 0x43, 0x80, 0x59, 0xc9, 0xec, 0xae, 0x79, 0x93, 0x9f, 0x16, 0x80, 0x74, 0xc9, 0x3e, 0xae, 0x56, 0x93, 0x4d, 0x57, 0xcd, 0x64, 0x2b, 0x3e, 0xc8, 0x56, 0xea, 0x6d, 0xa8, 0x8d, 0x9b, 0xf, 0x86, 0xc8, 0x2, 0xe8, 0x80, 0xe9, 0x27, 0xbb, 0xdd, 0x86, 0xe5, 0x4a, 0x79, 0x80, 0x2e, 0x7, 0x9b, 0xd9, 0x89, 0xed, 0xe2, 0x73, 0x18, 0x2e, 0xe9, 0xeb, 0x38, 0xd9, 0x95, 0xe0, 0x8d, 0x98, 0xd1, 0x8a, 0x74, 0x2c, 0x32, 0x1d, 0x17, 0x8e, 0x2d, 0x91, 0xf5, 0x44, 0xbf, 0x36, 0x1d, 0x15, 0xc7, 0x2d, 0x7b, 0xb5, 0x96, 0xbb, 0x50, 0x1d, 0x6b, 0xc5, 0x53, 0x3b, 0x41, 0xb6, 0x85, 0x54, 0x1a, 0x6d, 0x8d, 0x53, 0xdb, 0x41, 0x85, 0xa5, 0x29, 0x9a, 0xca, 0x8e, 0x8a, 0xfa, 0xd6, 0x91, 0xb8, 0xa5, 0x98, 0xc1, 0x8c, 0xca, 0xda, 0xe6, 0xaa, 0xa1, 0x27, 0x18, 0xc8, 0x8d, 0x5, 0xfb, 0x8d, 0xca, 0x40, 0xa7, 0x40, 0x51, 0x29, 0x4d, 0xc5, 0xbd, 0x7d, 0x1c, 0xe0, 0x60, 0xfb, 0x31, 0x94, 0x44, 0x71, 0x7d, 0xfe, 0xe8, 0xb0, 0x7a, 0x55, 0xd7, 0xbc, 0x21, 0xfd, 0xda, 0xf6, 0xb8, 0xfc, 0xdf, 0xd4, 0x9c, 0x21, 0xfc, 0xf2, 0x76, 0xf9, 0xfc, 0xbe, 0x17, 0xaf, 0x41, 0xe3, 0xca, 0xbe, 0x6f, 0x5f, 0xbf, 0xc, 0x87, 0x2d, 0xc3, 0x48, 0x36, 0x74, 0x57, 0x73, 0x4d, 0x43, 0xad, 0xd0, 0x18, 0xe3, 0xe0, 0xb0, 0x72, 0x35, 0x6f, 0x49, 0xf4, 0x52, 0x6b, 0xac, 0xb4, 0xd8, 0x35, 0xf6, 0x59, 0x77, 0x5e, 0x7b, 0xae, 0xbc, 0xda, 0x3e, 0xf7, 0x32, 0x53, 0x84, 0xeb, 0x23, 0x30, 0x18, 0x7e, 0xb1, 0x52, 0x64, 0xb4, 0xbe, 0x5, 0x56, 0xa, 0xc, 0x91, 0x76, 0x50, 0xb1, 0x3e, 0x59, 0x57, 0x6e, 0xd, 0xa3, 0xb6, 0x7e, 0x89, 0x76, 0x4b, 0x7d, 0x6e, 0xde, 0x82, 0x90, 0x5e, 0xca, 0x72, 0x4d, 0x71, 0xe9, 0xdc, 0x82, 0xd0, 0x15, 0x9a, 0x83, 0x4d, 0x9, 0xeb, 0x20, 0x82, 0x6f, 0x74, 0x1e, 0x93, 0x18, 0x8d, 0xb, 0x20, 0xb1, 0x2e, 0x60, 0x1e, 0xf1, 0x10, 0xfd, 0xf, 0x5e, 0xb7, 0x9b, 0x40, 0x94, 0xa, 0x89, 0x2, 0xa0, 0xb7, 0x66, 0x43, 0x77, 0xb6, 0xc7, 0x3e, 0x3f, 0xdf - }; + const uint8_t prng_payload_sf9[] = { + 0xfd, 0xbe, 0x94, 0xef, 0x1a, 0xf7, 0x7, 0xfd, 0x1, 0xff, 0xb, 0x94, 0xba, 0x1a, 0xda, 0x7, 0x64, 0x1, 0x78, 0xb, 0xdf, 0xba, 0xb0, 0xda, 0x9e, 0x64, 0x86, 0x78, 0xb, 0xdf, 0xf1, 0xb0, 0x3b, 0x9e, 0x57, 0x86, 0x2d, 0xb, 0xb9, 0xf1, 0x83, 0x3b, 0x80, 0x57, 0x1, 0x2d, 0x40, 0xb9, 0x10, 0x83, 0x47, 0x80, 0xa8, 0x3, 0x99, 0x41, 0xa3, 0x12, 0x5f, 0x3, 0x69, 0x8, 0x79, 0x98, 0xf4, 0xa7, 0xe, 0x5f, 0xcf, 0x6d, 0xe9, 0x79, 0xab, 0xf6, 0xb9, 0x2e, 0xd8, 0xcf, 0x2e, 0x41, 0xd1, 0x2b, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x7, 0x27, 0x60, 0x48, 0x14, 0xb8, 0x88, 0x9c, 0x48, 0x86, 0xa1, 0x60, 0x3, 0x4, 0x16, 0x94, 0x4e, 0x42, 0xa9, 0xa1, 0xf9, 0x3, 0xc8, 0x16, 0x3e, 0x46, 0x98, 0xab, 0x8e, 0xf9, 0xf1, 0xe8, 0x3b, 0x32, 0x57, 0x9e, 0xe7, 0x8c, 0x18, 0xf1, 0x80, 0x3f, 0x9e, 0x5f, 0xcd, 0xe7, 0xe8, 0x58, 0xe9, 0xb1, 0x9f, 0x92, 0x82, 0xcf, 0x0, 0xea, 0x2b, 0x88, 0xbe, 0xaf, 0x56, 0x82, 0x2e, 0x8, 0x92, 0x6b, 0x17, 0xae, 0x3b, 0x4a, 0xd7, 0x2a, 0x66, 0x92, 0x13, 0x76, 0x21, 0x3b, 0xa5, 0xd3, 0xd3, 0x65, 0x26, 0x13, 0x2, 0x41, 0x52, 0xad, 0x46, 0xd3, 0xa8, 0x26, 0xb2, 0x23, 0x52, 0x12, 0xb3, 0xce, 0x97, 0xa9, 0xc6, 0x33, 0x30, 0x72, 0x27, 0xbf, 0x7b, 0x1d, 0x7b, 0xc7, 0x9d, 0x30, 0xeb, 0x27, 0x38, 0x73, 0xd6, 0x79, 0x2f, 0x9f, 0x3, 0xeb, 0x39, 0x2c, 0xe8, 0xd6, 0x7b, 0x27, 0x9d, 0x43, 0x80, 0x59, 0xc9, 0xec, 0xae, 0x79, 0x93, 0x9f, 0x16, 0x80, 0x74, 0xc9, 0x3e, 0xae, 0x56, 0x93, 0x4d, 0x57, 0xcd, 0x64, 0x2b, 0x3e, 0xc8, 0x56, 0xea, 0x6d, 0xa8, 0x8d, 0x9b, 0xf, 0x86, 0xc8, 0x2, 0xe8, 0x80, 0xe9, 0x27, 0xbb, 0xdd, 0x86, 0xe5, 0x4a, 0x79, 0x80, 0x2e, 0x7, 0x9b, 0xd9, 0x89, 0xed, 0xe2, 0x73, 0x18, 0x2e, 0xe9, 0xeb, 0x38, 0xd9, 0x95, 0xe0, 0x8d, 0x98, 0xd1, 0x8a, 0x74, 0x2c, 0x32, 0x1d, 0x17, 0x8e, 0x2d, 0x91, 0xf5, 0x44, 0xbf, 0x36, 0x1d, 0x15, 0xc7, 0x2d, 0x7b, 0xb5, 0x96, 0xbb, 0x50, 0x1d, 0x6b, 0xc5, 0x53, 0x3b, 0x41, 0xb6, 0x85, 0x54, 0x1a, 0x6d, 0x8d, 0x53, 0xdb, 0x41, 0x85, 0xa5, 0x29, 0x9a, 0xca, 0x8e, 0x8a, 0xfa, 0xd6, 0x91, 0xb8, 0xa5, 0x98, 0xc1, 0x8c, 0xca, 0xda, 0xe6, 0xaa, 0xa1, 0x27, 0x18, 0xc8, 0x8d, 0x5, 0xfb, 0x8d, 0xca, 0x40, 0xa7, 0x40, 0x51, 0x29, 0x4d, 0xc5, 0xbd, 0x7d, 0x1c, 0xe0, 0x60, 0xfb, 0x31, 0x94, 0x44, 0x71, 0x7d, 0xfe, 0xe8, 0xb0, 0x7a, 0x55, 0xd7, 0xbc, 0x21, 0xfd, 0xda, 0xf6, 0xb8, 0xfc, 0xdf, 0xd4, 0x9c, 0x21, 0xfc, 0xf2, 0x76, 0xf9, 0xfc, 0xbe, 0x17, 0xaf, 0x41, 0xe3, 0xca, 0xbe, 0x6f, 0x5f, 0xbf, 0xc, 0x87, 0x2d, 0xc3, 0x48, 0x36, 0x74, 0x57, 0x73, 0x4d, 0x43, 0xad, 0xd0, 0x18, 0xe3, 0xe0, 0xb0, 0x72, 0x35, 0x6f, 0x49, 0xf4, 0x52, 0x6b, 0xac, 0xb4, 0xd8, 0x35, 0xf6, 0x59, 0x77, 0x5e, 0x7b, 0xae, 0xbc, 0xda, 0x3e, 0xf7, 0x32, 0x53, 0x84, 0xeb, 0x23, 0x30, 0x18, 0x7e, 0xb1, 0x52, 0x64, 0xb4, 0xbe, 0x5, 0x56, 0xa, 0xc, 0x91, 0x76, 0x50, 0xb1, 0x3e, 0x59, 0x57, 0x6e, 0xd, 0xa3, 0xb6, 0x7e, 0x89, 0x76, 0x4b, 0x7d, 0x6e, 0xde, 0x82, 0x90, 0x5e, 0xca, 0x72, 0x4d, 0x71, 0xe9, 0xdc, 0x82, 0xd0, 0x15, 0x9a, 0x83, 0x4d, 0x9, 0xeb, 0x20, 0x82, 0x6f, 0x74, 0x1e, 0x93, 0x18, 0x8d, 0xb, 0x20, 0xb1, 0x2e, 0x60, 0x1e, 0xf1, 0x10, 0xfd, 0xf, 0x5e, 0xb7, 0x9b, 0x40, 0x94, 0xa, 0x89, 0x2, 0xa0, 0xb7, 0x66, 0x43, 0x77, 0xb6, 0xc7, 0x3e, 0x3f, 0xdf + }; - const uint8_t prng_payload_sf10[] = { - 0xfd, 0xfe, 0xf4, 0xdf, 0xe, 0xfb, 0x8f, 0x7f, 0x2, 0xfe, 0x4b, 0xb4, 0xea, 0x3e, 0xc2, 0x83, 0x6a, 0x88, 0xfa, 0x48, 0xfe, 0xaa, 0xf4, 0xf2, 0x4e, 0x62, 0xab, 0xf8, 0xd1, 0xfc, 0xe0, 0xb4, 0x73, 0x7e, 0x65, 0x83, 0x21, 0xcb, 0x93, 0x72, 0x87, 0x32, 0x40, 0x75, 0x50, 0x29, 0x2c, 0x19, 0x9a, 0x84, 0x4a, 0x0, 0xea, 0x30, 0xa9, 0x4, 0x8b, 0x88, 0x49, 0xa, 0xe2, 0x2a, 0x38, 0xb9, 0xa4, 0xa3, 0x16, 0xdf, 0xcd, 0x60, 0x4b, 0x7b, 0xea, 0x94, 0x89, 0x1a, 0xd0, 0x47, 0x28, 0x60, 0xd3, 0xaa, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x6, 0x65, 0x40, 0x18, 0x30, 0xa0, 0x3c, 0x92, 0xc9, 0x4c, 0xe2, 0x1, 0x73, 0x64, 0x2e, 0x34, 0xd0, 0x83, 0x20, 0xe2, 0x18, 0x32, 0x8e, 0x7c, 0x9a, 0xf8, 0xd5, 0x32, 0x46, 0x1e, 0xe0, 0xcd, 0x73, 0xca, 0x25, 0x8d, 0x7a, 0x64, 0xfe, 0x6a, 0xb5, 0x33, 0x5d, 0x35, 0xbd, 0x72, 0x96, 0xf0, 0x1b, 0xbf, 0x2, 0x1c, 0x40, 0xad, 0x30, 0x9e, 0x47, 0x55, 0x30, 0x4, 0xd3, 0x2, 0x6d, 0x62, 0xe2, 0x3f, 0x6a, 0x26, 0xb1, 0x41, 0x54, 0x2c, 0x2e, 0xb2, 0x3, 0x52, 0x1, 0xaf, 0xab, 0xd4, 0xd0, 0xe7, 0x26, 0x13, 0x62, 0x41, 0x6, 0xa5, 0x62, 0x53, 0xbb, 0xed, 0x92, 0x13, 0x17, 0x3a, 0x1b, 0x50, 0x94, 0x29, 0xd, 0xd2, 0x42, 0x6, 0x3b, 0x17, 0xc9, 0xda, 0xea, 0xe, 0x7e, 0x3, 0xbe, 0x2b, 0xe4, 0xa5, 0x69, 0xf4, 0xe8, 0x76, 0xb3, 0xfd, 0x14, 0x94, 0x36, 0x41, 0x64, 0xca, 0xf1, 0x28, 0xb6, 0xd6, 0x15, 0x46, 0x1f, 0x5c, 0x9a, 0x63, 0xcc, 0x3f, 0xfa, 0x54, 0xf4, 0xd, 0x5, 0xf6, 0x21, 0xe2, 0x93, 0xe9, 0x5, 0xb3, 0xa, 0x55, 0xfa, 0x29, 0x81, 0x1d, 0x9d, 0xa, 0x82, 0x4a, 0x48, 0x8b, 0x31, 0xfd, 0x2b, 0x23, 0x5f, 0x9d, 0x64, 0x48, 0x73, 0xc9, 0x4e, 0x57, 0xbf, 0xd1, 0x51, 0xe7, 0x67, 0x30, 0x39, 0x3e, 0xaf, 0xe3, 0xac, 0xef, 0x10, 0x70, 0x4e, 0x73, 0xa0, 0xde, 0x28, 0x90, 0xac, 0xba, 0x0, 0x4d, 0x86, 0x62, 0xa1, 0x58, 0x63, 0xd1, 0x26, 0x8a, 0x89, 0x45, 0xc9, 0xe2, 0xea, 0x13, 0x82, 0x7a, 0x5e, 0x3, 0x3d, 0xda, 0xdf, 0xa9, 0x6c, 0xf3, 0xc9, 0x12, 0xf0, 0x8f, 0xa0, 0x56, 0x1f, 0x27, 0xc7, 0xf8, 0x3b, 0xe8, 0xd6, 0x3e, 0xd4, 0x82, 0x2f, 0x85, 0x59, 0x29, 0x9d, 0xce, 0x96, 0x4e, 0x4c, 0xa4, 0xf, 0x9b, 0x12, 0xec, 0x1d, 0xce, 0xa1, 0x4e, 0x42, 0xaa, 0xeb, 0x50, 0x29, 0x8d, 0xc5, 0xfd, 0x5d, 0x4, 0xec, 0x46, 0x7a, 0x63, 0xf5, 0x94, 0x5, 0x21, 0x5e, 0x8e, 0xb9, 0xe1, 0x9d, 0xb3, 0x8f, 0x35, 0xb1, 0x32, 0x64, 0x97, 0xe1, 0x17, 0x35, 0xcf, 0x1c, 0x82, 0x16, 0x1c, 0x54, 0x7b, 0xed, 0xb3, 0xfe, 0xdd, 0xbf, 0x6, 0xc4, 0xc, 0x29, 0x46, 0xa7, 0x70, 0x8, 0xf5, 0xc, 0xd5, 0xd1, 0x61, 0x4f, 0x93, 0x80, 0x12, 0x4f, 0xc3, 0x20, 0x80, 0x43, 0x67, 0x49, 0xc2, 0xab, 0x6f, 0x5d, 0xf3, 0xef, 0x51, 0xe8, 0x81, 0xfb, 0xb5, 0xc9, 0x51, 0x72, 0x2e, 0x7e, 0xf8, 0x2e, 0xf7, 0xab, 0xd7, 0x86, 0x6a, 0xa3, 0xb1, 0x9, 0x7e, 0x91, 0x52, 0x4, 0x98, 0x2a, 0x8b, 0xd4, 0x48, 0x64, 0x0, 0xe2, 0x4c, 0x41, 0x28, 0x7c, 0xda, 0xac, 0x26, 0x93, 0xb3, 0x34, 0x49, 0x14, 0x52, 0x69, 0xa, 0x76, 0xd0, 0x75, 0xe, 0xc, 0x2c, 0xc4, 0x2b, 0x4, 0xf0, 0x42, 0x36, 0x6c, 0x3c, 0x89, 0x89, 0xab, 0x3a, 0x8e, 0xdd, 0xca, 0xa7, 0xeb, 0xbe, 0xa9, 0xd3, 0xe4, 0x94, 0xe7, 0xe0, 0xf9, 0xb8, 0x3e, 0xf9, 0xe7, 0xac, 0xd3, 0x9, 0x79, 0x61, 0x80, 0x82, 0x41, 0x31, 0x48, 0xa0, 0x50, 0x96, 0x2, 0x26, 0x64, 0x85, 0x16 - }; + const uint8_t prng_payload_sf10[] = { + 0xfd, 0xfe, 0xf4, 0xdf, 0xe, 0xfb, 0x8f, 0x7f, 0x2, 0xfe, 0x4b, 0xb4, 0xea, 0x3e, 0xc2, 0x83, 0x6a, 0x88, 0xfa, 0x48, 0xfe, 0xaa, 0xf4, 0xf2, 0x4e, 0x62, 0xab, 0xf8, 0xd1, 0xfc, 0xe0, 0xb4, 0x73, 0x7e, 0x65, 0x83, 0x21, 0xcb, 0x93, 0x72, 0x87, 0x32, 0x40, 0x75, 0x50, 0x29, 0x2c, 0x19, 0x9a, 0x84, 0x4a, 0x0, 0xea, 0x30, 0xa9, 0x4, 0x8b, 0x88, 0x49, 0xa, 0xe2, 0x2a, 0x38, 0xb9, 0xa4, 0xa3, 0x16, 0xdf, 0xcd, 0x60, 0x4b, 0x7b, 0xea, 0x94, 0x89, 0x1a, 0xd0, 0x47, 0x28, 0x60, 0xd3, 0xaa, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x6, 0x65, 0x40, 0x18, 0x30, 0xa0, 0x3c, 0x92, 0xc9, 0x4c, 0xe2, 0x1, 0x73, 0x64, 0x2e, 0x34, 0xd0, 0x83, 0x20, 0xe2, 0x18, 0x32, 0x8e, 0x7c, 0x9a, 0xf8, 0xd5, 0x32, 0x46, 0x1e, 0xe0, 0xcd, 0x73, 0xca, 0x25, 0x8d, 0x7a, 0x64, 0xfe, 0x6a, 0xb5, 0x33, 0x5d, 0x35, 0xbd, 0x72, 0x96, 0xf0, 0x1b, 0xbf, 0x2, 0x1c, 0x40, 0xad, 0x30, 0x9e, 0x47, 0x55, 0x30, 0x4, 0xd3, 0x2, 0x6d, 0x62, 0xe2, 0x3f, 0x6a, 0x26, 0xb1, 0x41, 0x54, 0x2c, 0x2e, 0xb2, 0x3, 0x52, 0x1, 0xaf, 0xab, 0xd4, 0xd0, 0xe7, 0x26, 0x13, 0x62, 0x41, 0x6, 0xa5, 0x62, 0x53, 0xbb, 0xed, 0x92, 0x13, 0x17, 0x3a, 0x1b, 0x50, 0x94, 0x29, 0xd, 0xd2, 0x42, 0x6, 0x3b, 0x17, 0xc9, 0xda, 0xea, 0xe, 0x7e, 0x3, 0xbe, 0x2b, 0xe4, 0xa5, 0x69, 0xf4, 0xe8, 0x76, 0xb3, 0xfd, 0x14, 0x94, 0x36, 0x41, 0x64, 0xca, 0xf1, 0x28, 0xb6, 0xd6, 0x15, 0x46, 0x1f, 0x5c, 0x9a, 0x63, 0xcc, 0x3f, 0xfa, 0x54, 0xf4, 0xd, 0x5, 0xf6, 0x21, 0xe2, 0x93, 0xe9, 0x5, 0xb3, 0xa, 0x55, 0xfa, 0x29, 0x81, 0x1d, 0x9d, 0xa, 0x82, 0x4a, 0x48, 0x8b, 0x31, 0xfd, 0x2b, 0x23, 0x5f, 0x9d, 0x64, 0x48, 0x73, 0xc9, 0x4e, 0x57, 0xbf, 0xd1, 0x51, 0xe7, 0x67, 0x30, 0x39, 0x3e, 0xaf, 0xe3, 0xac, 0xef, 0x10, 0x70, 0x4e, 0x73, 0xa0, 0xde, 0x28, 0x90, 0xac, 0xba, 0x0, 0x4d, 0x86, 0x62, 0xa1, 0x58, 0x63, 0xd1, 0x26, 0x8a, 0x89, 0x45, 0xc9, 0xe2, 0xea, 0x13, 0x82, 0x7a, 0x5e, 0x3, 0x3d, 0xda, 0xdf, 0xa9, 0x6c, 0xf3, 0xc9, 0x12, 0xf0, 0x8f, 0xa0, 0x56, 0x1f, 0x27, 0xc7, 0xf8, 0x3b, 0xe8, 0xd6, 0x3e, 0xd4, 0x82, 0x2f, 0x85, 0x59, 0x29, 0x9d, 0xce, 0x96, 0x4e, 0x4c, 0xa4, 0xf, 0x9b, 0x12, 0xec, 0x1d, 0xce, 0xa1, 0x4e, 0x42, 0xaa, 0xeb, 0x50, 0x29, 0x8d, 0xc5, 0xfd, 0x5d, 0x4, 0xec, 0x46, 0x7a, 0x63, 0xf5, 0x94, 0x5, 0x21, 0x5e, 0x8e, 0xb9, 0xe1, 0x9d, 0xb3, 0x8f, 0x35, 0xb1, 0x32, 0x64, 0x97, 0xe1, 0x17, 0x35, 0xcf, 0x1c, 0x82, 0x16, 0x1c, 0x54, 0x7b, 0xed, 0xb3, 0xfe, 0xdd, 0xbf, 0x6, 0xc4, 0xc, 0x29, 0x46, 0xa7, 0x70, 0x8, 0xf5, 0xc, 0xd5, 0xd1, 0x61, 0x4f, 0x93, 0x80, 0x12, 0x4f, 0xc3, 0x20, 0x80, 0x43, 0x67, 0x49, 0xc2, 0xab, 0x6f, 0x5d, 0xf3, 0xef, 0x51, 0xe8, 0x81, 0xfb, 0xb5, 0xc9, 0x51, 0x72, 0x2e, 0x7e, 0xf8, 0x2e, 0xf7, 0xab, 0xd7, 0x86, 0x6a, 0xa3, 0xb1, 0x9, 0x7e, 0x91, 0x52, 0x4, 0x98, 0x2a, 0x8b, 0xd4, 0x48, 0x64, 0x0, 0xe2, 0x4c, 0x41, 0x28, 0x7c, 0xda, 0xac, 0x26, 0x93, 0xb3, 0x34, 0x49, 0x14, 0x52, 0x69, 0xa, 0x76, 0xd0, 0x75, 0xe, 0xc, 0x2c, 0xc4, 0x2b, 0x4, 0xf0, 0x42, 0x36, 0x6c, 0x3c, 0x89, 0x89, 0xab, 0x3a, 0x8e, 0xdd, 0xca, 0xa7, 0xeb, 0xbe, 0xa9, 0xd3, 0xe4, 0x94, 0xe7, 0xe0, 0xf9, 0xb8, 0x3e, 0xf9, 0xe7, 0xac, 0xd3, 0x9, 0x79, 0x61, 0x80, 0x82, 0x41, 0x31, 0x48, 0xa0, 0x50, 0x96, 0x2, 0x26, 0x64, 0x85, 0x16 + }; - const uint8_t prng_payload_sf11[] = { - 0xfd, 0xfe, 0xb4, 0xbf, 0x3e, 0x8f, 0xa3, 0xd3, 0xd0, 0x75, 0x4, 0xfe, 0xc1, 0xb5, 0xea, 0x3e, 0xc2, 0xc3, 0x4a, 0x80, 0x6e, 0x2c, 0x7a, 0x59, 0xfe, 0x6a, 0x94, 0x82, 0x2a, 0x7a, 0x47, 0x62, 0x84, 0xf8, 0x42, 0xfd, 0xa0, 0x94, 0x43, 0x4a, 0x39, 0x27, 0xd3, 0x6, 0x2d, 0x43, 0x9a, 0x21, 0xe7, 0x61, 0x54, 0x3d, 0xbc, 0xd3, 0x3, 0x2d, 0x9, 0x98, 0xc0, 0xe7, 0x7b, 0x74, 0xf6, 0x98, 0xab, 0xb, 0x99, 0x80, 0x87, 0x47, 0x6b, 0x3b, 0xd5, 0x86, 0xec, 0x87, 0xfb, 0x3, 0xb7, 0x86, 0x5e, 0x6b, 0xb7, 0xd5, 0x57, 0xe8, 0xec, 0x7b, 0x31, 0xb6, 0x98, 0x5e, 0xec, 0xb7, 0xbe, 0x7, 0x3a, 0xec, 0xd3, 0xab, 0xee, 0x9a, 0x38, 0xe4, 0xe4, 0xfe, 0x76, 0xa, 0x99, 0x43, 0x5, 0x64, 0x1, 0x38, 0x63, 0xe4, 0x14, 0x6, 0x9b, 0x99, 0x4a, 0x4f, 0xe1, 0x0, 0x73, 0x22, 0xe, 0x44, 0xa0, 0x97, 0x44, 0xc4, 0xaa, 0x61, 0x99, 0x72, 0xac, 0x4e, 0xce, 0xe0, 0x35, 0x4c, 0x9d, 0xa0, 0x4e, 0x98, 0xa1, 0xad, 0x43, 0xce, 0x59, 0x25, 0x54, 0x5, 0xe4, 0xcf, 0x78, 0xa1, 0x94, 0x43, 0xa, 0x19, 0x10, 0x40, 0x85, 0x66, 0xaa, 0xfb, 0xd8, 0x85, 0xd7, 0x6a, 0x28, 0x4, 0x6, 0x45, 0xc6, 0x28, 0x60, 0xd9, 0x8a, 0xd7, 0xc7, 0x38, 0xe1, 0x56, 0xa1, 0x82, 0xd0, 0xc8, 0x2e, 0x8a, 0x3, 0xe6, 0x49, 0xe5, 0x58, 0x31, 0xec, 0x51, 0x32, 0x25, 0x35, 0x3, 0x29, 0x19, 0x12, 0xd0, 0xb, 0xef, 0xe1, 0x30, 0x72, 0x75, 0x2e, 0x39, 0xa4, 0x3a, 0xf8, 0x9b, 0x2b, 0xec, 0xd5, 0x72, 0x46, 0x2e, 0x17, 0xb5, 0x8a, 0xd8, 0xd6, 0x25, 0x5, 0xd3, 0x42, 0x46, 0x3b, 0x16, 0xfd, 0xce, 0xfe, 0x16, 0xf7, 0x4, 0xfc, 0x40, 0xdf, 0x3b, 0x90, 0xfd, 0xcd, 0xf6, 0x5b, 0xfb, 0x6c, 0xfe, 0xf0, 0xde, 0x65, 0xb0, 0x7e, 0xcd, 0xea, 0xdf, 0xe7, 0xe5, 0xfe, 0x71, 0xd4, 0x65, 0x51, 0x2e, 0xcd, 0xfa, 0x87, 0xfd, 0x58, 0xfc, 0x27, 0xd4, 0x68, 0x51, 0x8c, 0xed, 0xab, 0xa7, 0xd1, 0x50, 0x2e, 0x2f, 0xf9, 0x48, 0xc3, 0x9a, 0xb3, 0x23, 0xc5, 0xde, 0x28, 0x2c, 0xd8, 0xa8, 0xd7, 0xc5, 0x68, 0x93, 0xd, 0x41, 0xca, 0xa1, 0x40, 0xd9, 0x13, 0x97, 0x41, 0x28, 0xc2, 0x55, 0x6c, 0xec, 0x38, 0xe2, 0xdf, 0x13, 0xd6, 0x61, 0x73, 0xe2, 0x4f, 0x6c, 0x6c, 0xb0, 0x6b, 0x5d, 0x1f, 0x95, 0xa0, 0x43, 0xc6, 0x5b, 0x9, 0x60, 0x4f, 0x72, 0xa0, 0x9e, 0x48, 0xe0, 0xe8, 0xe6, 0x4, 0x15, 0x82, 0x4c, 0x47, 0xa0, 0x82, 0x8, 0x7, 0x98, 0x96, 0x3c, 0x2c, 0x9a, 0xe, 0x4d, 0x4a, 0x8a, 0x9a, 0x27, 0xea, 0xee, 0xe8, 0x1a, 0xf5, 0x5, 0xb1, 0xb, 0x74, 0xba, 0x39, 0xee, 0x79, 0xec, 0x8f, 0x67, 0x48, 0x38, 0xeb, 0x75, 0xe8, 0x79, 0x9f, 0x9, 0x99, 0x1f, 0xcd, 0x6, 0x29, 0xe9, 0xf2, 0xe9, 0x79, 0x9f, 0xd, 0x9d, 0x9b, 0x4b, 0x5, 0xac, 0xeb, 0x71, 0xa2, 0x19, 0x25, 0x1d, 0x98, 0x97, 0x4f, 0x7, 0x2e, 0xeb, 0xf8, 0xa2, 0x9a, 0x5, 0x6d, 0xb0, 0xe7, 0x5f, 0xfb, 0xae, 0xf5, 0xf9, 0x65, 0xf8, 0x3e, 0x39, 0xfe, 0x4b, 0x71, 0xe0, 0xb6, 0xf1, 0x75, 0x65, 0x12, 0x1e, 0xdb, 0xb6, 0xb3, 0xe3, 0x9c, 0xb2, 0xf, 0x75, 0xd0, 0x22, 0x10, 0xd7, 0x2d, 0x8d, 0x76, 0x91, 0x37, 0x8f, 0x35, 0xd1, 0x22, 0x0, 0xc4, 0x25, 0x5c, 0xfe, 0xf0, 0x36, 0xbc, 0x35, 0x8e, 0x42, 0xe8, 0xa4, 0x3, 0xfc, 0xd2, 0x7d, 0xa6, 0xbc, 0xba, 0xcf, 0xc8, 0xb8, 0x15, 0x23, 0x54, 0x58, 0xb3, 0x2f, 0x5f, 0xb2, 0x9c, 0xa8, 0x89, 0x65, 0x39, 0x54, 0x38, 0xb3, 0xd7, 0x5b, 0x8c, 0xdc, 0xa6, 0x99, 0xb1, 0x79, 0x18, 0x38, 0x10, 0x57, 0xc0 - }; + const uint8_t prng_payload_sf11[] = { + 0xfd, 0xfe, 0xb4, 0xbf, 0x3e, 0x8f, 0xa3, 0xd3, 0xd0, 0x75, 0x4, 0xfe, 0xc1, 0xb5, 0xea, 0x3e, 0xc2, 0xc3, 0x4a, 0x80, 0x6e, 0x2c, 0x7a, 0x59, 0xfe, 0x6a, 0x94, 0x82, 0x2a, 0x7a, 0x47, 0x62, 0x84, 0xf8, 0x42, 0xfd, 0xa0, 0x94, 0x43, 0x4a, 0x39, 0x27, 0xd3, 0x6, 0x2d, 0x43, 0x9a, 0x21, 0xe7, 0x61, 0x54, 0x3d, 0xbc, 0xd3, 0x3, 0x2d, 0x9, 0x98, 0xc0, 0xe7, 0x7b, 0x74, 0xf6, 0x98, 0xab, 0xb, 0x99, 0x80, 0x87, 0x47, 0x6b, 0x3b, 0xd5, 0x86, 0xec, 0x87, 0xfb, 0x3, 0xb7, 0x86, 0x5e, 0x6b, 0xb7, 0xd5, 0x57, 0xe8, 0xec, 0x7b, 0x31, 0xb6, 0x98, 0x5e, 0xec, 0xb7, 0xbe, 0x7, 0x3a, 0xec, 0xd3, 0xab, 0xee, 0x9a, 0x38, 0xe4, 0xe4, 0xfe, 0x76, 0xa, 0x99, 0x43, 0x5, 0x64, 0x1, 0x38, 0x63, 0xe4, 0x14, 0x6, 0x9b, 0x99, 0x4a, 0x4f, 0xe1, 0x0, 0x73, 0x22, 0xe, 0x44, 0xa0, 0x97, 0x44, 0xc4, 0xaa, 0x61, 0x99, 0x72, 0xac, 0x4e, 0xce, 0xe0, 0x35, 0x4c, 0x9d, 0xa0, 0x4e, 0x98, 0xa1, 0xad, 0x43, 0xce, 0x59, 0x25, 0x54, 0x5, 0xe4, 0xcf, 0x78, 0xa1, 0x94, 0x43, 0xa, 0x19, 0x10, 0x40, 0x85, 0x66, 0xaa, 0xfb, 0xd8, 0x85, 0xd7, 0x6a, 0x28, 0x4, 0x6, 0x45, 0xc6, 0x28, 0x60, 0xd9, 0x8a, 0xd7, 0xc7, 0x38, 0xe1, 0x56, 0xa1, 0x82, 0xd0, 0xc8, 0x2e, 0x8a, 0x3, 0xe6, 0x49, 0xe5, 0x58, 0x31, 0xec, 0x51, 0x32, 0x25, 0x35, 0x3, 0x29, 0x19, 0x12, 0xd0, 0xb, 0xef, 0xe1, 0x30, 0x72, 0x75, 0x2e, 0x39, 0xa4, 0x3a, 0xf8, 0x9b, 0x2b, 0xec, 0xd5, 0x72, 0x46, 0x2e, 0x17, 0xb5, 0x8a, 0xd8, 0xd6, 0x25, 0x5, 0xd3, 0x42, 0x46, 0x3b, 0x16, 0xfd, 0xce, 0xfe, 0x16, 0xf7, 0x4, 0xfc, 0x40, 0xdf, 0x3b, 0x90, 0xfd, 0xcd, 0xf6, 0x5b, 0xfb, 0x6c, 0xfe, 0xf0, 0xde, 0x65, 0xb0, 0x7e, 0xcd, 0xea, 0xdf, 0xe7, 0xe5, 0xfe, 0x71, 0xd4, 0x65, 0x51, 0x2e, 0xcd, 0xfa, 0x87, 0xfd, 0x58, 0xfc, 0x27, 0xd4, 0x68, 0x51, 0x8c, 0xed, 0xab, 0xa7, 0xd1, 0x50, 0x2e, 0x2f, 0xf9, 0x48, 0xc3, 0x9a, 0xb3, 0x23, 0xc5, 0xde, 0x28, 0x2c, 0xd8, 0xa8, 0xd7, 0xc5, 0x68, 0x93, 0xd, 0x41, 0xca, 0xa1, 0x40, 0xd9, 0x13, 0x97, 0x41, 0x28, 0xc2, 0x55, 0x6c, 0xec, 0x38, 0xe2, 0xdf, 0x13, 0xd6, 0x61, 0x73, 0xe2, 0x4f, 0x6c, 0x6c, 0xb0, 0x6b, 0x5d, 0x1f, 0x95, 0xa0, 0x43, 0xc6, 0x5b, 0x9, 0x60, 0x4f, 0x72, 0xa0, 0x9e, 0x48, 0xe0, 0xe8, 0xe6, 0x4, 0x15, 0x82, 0x4c, 0x47, 0xa0, 0x82, 0x8, 0x7, 0x98, 0x96, 0x3c, 0x2c, 0x9a, 0xe, 0x4d, 0x4a, 0x8a, 0x9a, 0x27, 0xea, 0xee, 0xe8, 0x1a, 0xf5, 0x5, 0xb1, 0xb, 0x74, 0xba, 0x39, 0xee, 0x79, 0xec, 0x8f, 0x67, 0x48, 0x38, 0xeb, 0x75, 0xe8, 0x79, 0x9f, 0x9, 0x99, 0x1f, 0xcd, 0x6, 0x29, 0xe9, 0xf2, 0xe9, 0x79, 0x9f, 0xd, 0x9d, 0x9b, 0x4b, 0x5, 0xac, 0xeb, 0x71, 0xa2, 0x19, 0x25, 0x1d, 0x98, 0x97, 0x4f, 0x7, 0x2e, 0xeb, 0xf8, 0xa2, 0x9a, 0x5, 0x6d, 0xb0, 0xe7, 0x5f, 0xfb, 0xae, 0xf5, 0xf9, 0x65, 0xf8, 0x3e, 0x39, 0xfe, 0x4b, 0x71, 0xe0, 0xb6, 0xf1, 0x75, 0x65, 0x12, 0x1e, 0xdb, 0xb6, 0xb3, 0xe3, 0x9c, 0xb2, 0xf, 0x75, 0xd0, 0x22, 0x10, 0xd7, 0x2d, 0x8d, 0x76, 0x91, 0x37, 0x8f, 0x35, 0xd1, 0x22, 0x0, 0xc4, 0x25, 0x5c, 0xfe, 0xf0, 0x36, 0xbc, 0x35, 0x8e, 0x42, 0xe8, 0xa4, 0x3, 0xfc, 0xd2, 0x7d, 0xa6, 0xbc, 0xba, 0xcf, 0xc8, 0xb8, 0x15, 0x23, 0x54, 0x58, 0xb3, 0x2f, 0x5f, 0xb2, 0x9c, 0xa8, 0x89, 0x65, 0x39, 0x54, 0x38, 0xb3, 0xd7, 0x5b, 0x8c, 0xdc, 0xa6, 0x99, 0xb1, 0x79, 0x18, 0x38, 0x10, 0x57, 0xc0 + }; - const uint8_t prng_payload_sf12[] = { - 0xfd, 0x7c, 0xb4, 0xff, 0x5f, 0x9f, 0xd7, 0xab, 0x28, 0x73, 0x91, 0xff, 0xc5, 0xb5, 0xab, 0x1c, 0x92, 0xe7, 0x76, 0x74, 0x54, 0x9f, 0xfd, 0xc3, 0x7f, 0xa9, 0xb5, 0xd2, 0x5e, 0x46, 0xb7, 0x5c, 0x47, 0x7f, 0xfb, 0xff, 0xef, 0x35, 0x33, 0x1d, 0x15, 0xe7, 0x3d, 0x5f, 0x85, 0x5d, 0x91, 0xea, 0x87, 0xb7, 0x2, 0x55, 0x41, 0x4d, 0x30, 0xed, 0x18, 0x17, 0x11, 0x8d, 0x4c, 0x2, 0xab, 0xa0, 0xd9, 0x24, 0xd7, 0x24, 0x3, 0x97, 0x43, 0x1, 0x62, 0x8a, 0x7b, 0x99, 0xf4, 0xa6, 0x4e, 0x6f, 0xbb, 0x55, 0x49, 0xed, 0xea, 0x73, 0xbb, 0x36, 0xd9, 0x3e, 0x9c, 0xe3, 0xb2, 0x97, 0x24, 0xe1, 0x51, 0x38, 0x6f, 0x9e, 0x38, 0xec, 0x64, 0xbe, 0x54, 0x1a, 0x99, 0x4b, 0x5, 0x60, 0x1, 0x79, 0x48, 0xd4, 0xf0, 0x5a, 0x37, 0x2f, 0xd7, 0x4f, 0x6f, 0x2, 0x30, 0x1, 0x5e, 0x60, 0xbc, 0x5f, 0xf7, 0x1d, 0xbf, 0x4e, 0x13, 0xb0, 0xcd, 0x1e, 0xe8, 0xed, 0xe9, 0x9e, 0xa4, 0x39, 0x6b, 0x55, 0x72, 0x4f, 0x38, 0xaa, 0x15, 0x39, 0x16, 0xe8, 0x40, 0x11, 0x7e, 0xd8, 0x3e, 0x34, 0x1f, 0x57, 0x8d, 0x6, 0xca, 0xc, 0x81, 0x55, 0x49, 0xa1, 0x8c, 0xc, 0x3, 0xcf, 0xc0, 0x88, 0x5b, 0xad, 0x92, 0x33, 0x2c, 0x1, 0x5c, 0x92, 0xae, 0x1, 0x93, 0x2b, 0x16, 0x9e, 0x1f, 0xa, 0xaf, 0xf6, 0x1d, 0xab, 0x64, 0xd1, 0x73, 0x44, 0x25, 0x35, 0x5, 0x9, 0xb8, 0x43, 0x9b, 0xe6, 0x61, 0x30, 0x70, 0x75, 0x2e, 0x19, 0xc4, 0x4e, 0xd8, 0xdf, 0x25, 0xee, 0x52, 0x30, 0x26, 0x76, 0x63, 0xd8, 0xf6, 0x5a, 0xc5, 0xbb, 0x26, 0x54, 0x2, 0x65, 0xb, 0x13, 0x90, 0x2a, 0x10, 0x23, 0x41, 0x1, 0xf6, 0x13, 0xfc, 0xc8, 0xf4, 0x83, 0x45, 0x2c, 0x2a, 0x53, 0x5, 0xfc, 0xa4, 0x7f, 0xdf, 0xb5, 0x27, 0x35, 0x8, 0x42, 0xa3, 0x87, 0x46, 0xb4, 0xaa, 0xdd, 0xd7, 0x67, 0x6e, 0x18, 0x82, 0xcb, 0x1a, 0x18, 0xfe, 0x82, 0x75, 0xdd, 0xb6, 0xae, 0x14, 0xf0, 0x3d, 0x52, 0xe5, 0xc8, 0xe1, 0x7f, 0x99, 0x34, 0xc9, 0x5c, 0xeb, 0x4d, 0xa9, 0x9d, 0xdf, 0x7f, 0xb6, 0x12, 0xf, 0xca, 0x41, 0xa9, 0x20, 0xfb, 0x23, 0x93, 0x7d, 0xa8, 0xec, 0xc6, 0x69, 0xc3, 0xb1, 0xf0, 0x5f, 0xd3, 0xb7, 0x1, 0x43, 0xf6, 0x13, 0xf0, 0xca, 0xb3, 0x7a, 0x17, 0xb8, 0xa7, 0xc4, 0xf, 0x72, 0x25, 0x26, 0x65, 0xc4, 0xf5, 0x73, 0xfe, 0x3b, 0x95, 0xc4, 0x4a, 0x62, 0x50, 0x3e, 0x44, 0xc6, 0xef, 0xe2, 0xfb, 0x63, 0x15, 0xe, 0xa, 0xdb, 0x64, 0x39, 0x40, 0x7, 0x6a, 0x8, 0x32, 0x81, 0x7e, 0x36, 0x93, 0x3f, 0xdf, 0xcf, 0x47, 0x5b, 0x38, 0xa7, 0x52, 0xda, 0x44, 0xbc, 0x57, 0xc6, 0x9d, 0x87, 0x42, 0x51, 0xa6, 0xa0, 0x18, 0x2, 0x6c, 0xfa, 0xde, 0x8e, 0x5d, 0xeb, 0x9e, 0x39, 0x0, 0x1a, 0x42, 0x8f, 0xcb, 0xf8, 0x96, 0xde, 0xb5, 0x13, 0x20, 0x80, 0x13, 0xc0, 0x4d, 0x68, 0x8b, 0x8b, 0xe6, 0xc0, 0xa5, 0x7f, 0x2d, 0x40, 0x59, 0xea, 0x2c, 0xf1, 0xb8, 0xd, 0xe8, 0xa, 0x75, 0x1a, 0x59, 0xf4, 0x73, 0x35, 0xb7, 0x14, 0x35, 0x17, 0x20, 0x1b, 0xb0, 0x24, 0x41, 0xd2, 0xaf, 0xc7, 0xd6, 0xa0, 0x6, 0x8, 0x17, 0x96, 0xca, 0x9a, 0x93, 0x21, 0xe7, 0x50, 0xe3, 0xa6, 0x58, 0x68, 0x9b, 0xc6, 0x4c, 0x89, 0xae, 0x55, 0x4a, 0x76, 0x67, 0xf7, 0x58, 0x65, 0xbb, 0x37, 0x2f, 0xbb, 0xc2, 0x47, 0x71, 0x4f, 0xbe, 0x20, 0x75, 0x62, 0x39, 0x5e, 0x5d, 0xba, 0xb5, 0x52, 0x3, 0x60, 0xe2, 0xf2, 0x93, 0x4, 0x6a, 0x21, 0x44, 0x48, 0x50, 0x5c, 0xef, 0x2e, 0x38, 0xda, 0x37, 0x96, 0x9, 0x33, 0x56, 0x6f, 0x68, 0x66, 0x24, 0xb2, 0x99, 0x5f - }; - } + const uint8_t prng_payload_sf12[] = { + 0xfd, 0x7c, 0xb4, 0xff, 0x5f, 0x9f, 0xd7, 0xab, 0x28, 0x73, 0x91, 0xff, 0xc5, 0xb5, 0xab, 0x1c, 0x92, 0xe7, 0x76, 0x74, 0x54, 0x9f, 0xfd, 0xc3, 0x7f, 0xa9, 0xb5, 0xd2, 0x5e, 0x46, 0xb7, 0x5c, 0x47, 0x7f, 0xfb, 0xff, 0xef, 0x35, 0x33, 0x1d, 0x15, 0xe7, 0x3d, 0x5f, 0x85, 0x5d, 0x91, 0xea, 0x87, 0xb7, 0x2, 0x55, 0x41, 0x4d, 0x30, 0xed, 0x18, 0x17, 0x11, 0x8d, 0x4c, 0x2, 0xab, 0xa0, 0xd9, 0x24, 0xd7, 0x24, 0x3, 0x97, 0x43, 0x1, 0x62, 0x8a, 0x7b, 0x99, 0xf4, 0xa6, 0x4e, 0x6f, 0xbb, 0x55, 0x49, 0xed, 0xea, 0x73, 0xbb, 0x36, 0xd9, 0x3e, 0x9c, 0xe3, 0xb2, 0x97, 0x24, 0xe1, 0x51, 0x38, 0x6f, 0x9e, 0x38, 0xec, 0x64, 0xbe, 0x54, 0x1a, 0x99, 0x4b, 0x5, 0x60, 0x1, 0x79, 0x48, 0xd4, 0xf0, 0x5a, 0x37, 0x2f, 0xd7, 0x4f, 0x6f, 0x2, 0x30, 0x1, 0x5e, 0x60, 0xbc, 0x5f, 0xf7, 0x1d, 0xbf, 0x4e, 0x13, 0xb0, 0xcd, 0x1e, 0xe8, 0xed, 0xe9, 0x9e, 0xa4, 0x39, 0x6b, 0x55, 0x72, 0x4f, 0x38, 0xaa, 0x15, 0x39, 0x16, 0xe8, 0x40, 0x11, 0x7e, 0xd8, 0x3e, 0x34, 0x1f, 0x57, 0x8d, 0x6, 0xca, 0xc, 0x81, 0x55, 0x49, 0xa1, 0x8c, 0xc, 0x3, 0xcf, 0xc0, 0x88, 0x5b, 0xad, 0x92, 0x33, 0x2c, 0x1, 0x5c, 0x92, 0xae, 0x1, 0x93, 0x2b, 0x16, 0x9e, 0x1f, 0xa, 0xaf, 0xf6, 0x1d, 0xab, 0x64, 0xd1, 0x73, 0x44, 0x25, 0x35, 0x5, 0x9, 0xb8, 0x43, 0x9b, 0xe6, 0x61, 0x30, 0x70, 0x75, 0x2e, 0x19, 0xc4, 0x4e, 0xd8, 0xdf, 0x25, 0xee, 0x52, 0x30, 0x26, 0x76, 0x63, 0xd8, 0xf6, 0x5a, 0xc5, 0xbb, 0x26, 0x54, 0x2, 0x65, 0xb, 0x13, 0x90, 0x2a, 0x10, 0x23, 0x41, 0x1, 0xf6, 0x13, 0xfc, 0xc8, 0xf4, 0x83, 0x45, 0x2c, 0x2a, 0x53, 0x5, 0xfc, 0xa4, 0x7f, 0xdf, 0xb5, 0x27, 0x35, 0x8, 0x42, 0xa3, 0x87, 0x46, 0xb4, 0xaa, 0xdd, 0xd7, 0x67, 0x6e, 0x18, 0x82, 0xcb, 0x1a, 0x18, 0xfe, 0x82, 0x75, 0xdd, 0xb6, 0xae, 0x14, 0xf0, 0x3d, 0x52, 0xe5, 0xc8, 0xe1, 0x7f, 0x99, 0x34, 0xc9, 0x5c, 0xeb, 0x4d, 0xa9, 0x9d, 0xdf, 0x7f, 0xb6, 0x12, 0xf, 0xca, 0x41, 0xa9, 0x20, 0xfb, 0x23, 0x93, 0x7d, 0xa8, 0xec, 0xc6, 0x69, 0xc3, 0xb1, 0xf0, 0x5f, 0xd3, 0xb7, 0x1, 0x43, 0xf6, 0x13, 0xf0, 0xca, 0xb3, 0x7a, 0x17, 0xb8, 0xa7, 0xc4, 0xf, 0x72, 0x25, 0x26, 0x65, 0xc4, 0xf5, 0x73, 0xfe, 0x3b, 0x95, 0xc4, 0x4a, 0x62, 0x50, 0x3e, 0x44, 0xc6, 0xef, 0xe2, 0xfb, 0x63, 0x15, 0xe, 0xa, 0xdb, 0x64, 0x39, 0x40, 0x7, 0x6a, 0x8, 0x32, 0x81, 0x7e, 0x36, 0x93, 0x3f, 0xdf, 0xcf, 0x47, 0x5b, 0x38, 0xa7, 0x52, 0xda, 0x44, 0xbc, 0x57, 0xc6, 0x9d, 0x87, 0x42, 0x51, 0xa6, 0xa0, 0x18, 0x2, 0x6c, 0xfa, 0xde, 0x8e, 0x5d, 0xeb, 0x9e, 0x39, 0x0, 0x1a, 0x42, 0x8f, 0xcb, 0xf8, 0x96, 0xde, 0xb5, 0x13, 0x20, 0x80, 0x13, 0xc0, 0x4d, 0x68, 0x8b, 0x8b, 0xe6, 0xc0, 0xa5, 0x7f, 0x2d, 0x40, 0x59, 0xea, 0x2c, 0xf1, 0xb8, 0xd, 0xe8, 0xa, 0x75, 0x1a, 0x59, 0xf4, 0x73, 0x35, 0xb7, 0x14, 0x35, 0x17, 0x20, 0x1b, 0xb0, 0x24, 0x41, 0xd2, 0xaf, 0xc7, 0xd6, 0xa0, 0x6, 0x8, 0x17, 0x96, 0xca, 0x9a, 0x93, 0x21, 0xe7, 0x50, 0xe3, 0xa6, 0x58, 0x68, 0x9b, 0xc6, 0x4c, 0x89, 0xae, 0x55, 0x4a, 0x76, 0x67, 0xf7, 0x58, 0x65, 0xbb, 0x37, 0x2f, 0xbb, 0xc2, 0x47, 0x71, 0x4f, 0xbe, 0x20, 0x75, 0x62, 0x39, 0x5e, 0x5d, 0xba, 0xb5, 0x52, 0x3, 0x60, 0xe2, 0xf2, 0x93, 0x4, 0x6a, 0x21, 0x44, 0x48, 0x50, 0x5c, 0xef, 0x2e, 0x38, 0xda, 0x37, 0x96, 0x9, 0x33, 0x56, 0x6f, 0x68, 0x66, 0x24, 0xb2, 0x99, 0x5f + }; + } } #endif /* TABLES_H */ diff --git a/lib/utilities.h b/lib/utilities.h index 7aad72d..8b957c9 100644 --- a/lib/utilities.h +++ b/lib/utilities.h @@ -1,87 +1,70 @@ #ifndef UTILITIES_H #define UTILITIES_H +#include + namespace gr { - namespace lora { + namespace lora { template - std::string to_bin(T v, int element_len_bits) { - T mask = 0; - unsigned int maxpow = element_len_bits; + std::string to_bin(T v, uint32_t bitwidth) { + unsigned long long maxpow = bitwidth ? (1ull << (bitwidth - 1)) : 0, + mask; + std::string result = ""; - for(int i = 0; i < maxpow; i++) { - mask = pow(2, i); - //std::cout << (unsigned int)v << " AND " << mask << " is " << (v & mask) << std::endl; - - if((v & mask) > 0) { - result += "1"; - } else { - result += "0"; - } - } - - return result; - } - - template - inline void print_vector(std::ostream& out, std::vector& v, std::string prefix, int element_len_bits) { - out << prefix << ": "; - for(int i = 0; i < v.size(); i++) { - out << to_bin(v[i], element_len_bits) << ", "; - } - out << std::endl << std::flush; - } - - template - inline void print_vector_raw(std::ostream& out, std::vector& v, int element_len_bits) { - for(int i = 0; i < v.size(); i++) { - out << to_bin(v[i], element_len_bits); - } - out << std::flush; - } - - bool check_parity(std::string word, bool even) { - int count = 0; - - for(int i = 0; i < 7; i++) { - if(word[i] == '1') - count += 1; - } - - if(even) - return ((count % 2) == 0); - else - return (((count+1) % 2) == 0); - } - - uint32_t select_bits(uint32_t data, uint8_t* indices, uint8_t n) { - uint32_t result = 0; - - for(uint32_t j = 0; j < n; j++) { - uint32_t power = pow(2, indices[j]); - if((data & power) > 0) { - result += pow(2, j); - } + for (mask = 0x1; mask <= maxpow; mask <<= 1) { + result += (v & mask) ? "1" : "0"; } return result; } - void fec_extract_data_only(uint8_t* in_data, uint32_t len, uint8_t* indices, uint8_t n, uint8_t* out_data) { - uint8_t out_index = 0; + template + inline void print_vector(std::ostream& out, std::vector& v, std::string prefix, int element_len_bits) { + out << prefix << ": "; - for(uint32_t i = 0; i < len; i+=2) { - uint8_t d1 = 0; - d1 = select_bits(in_data[i], indices, n) & 0xff; + for (T x : v) + out << to_bin(x, element_len_bits) << ", "; + out << std::endl << std::flush; + } - uint8_t d2 = 0; - if(i+1 < len) - d2 = select_bits(in_data[i+1], indices, n) & 0xff; + template + inline void print_vector_raw(std::ostream& out, std::vector& v, int element_len_bits) { - out_data[out_index] = (d1 << 4) | d2; - out_index++; + for (T x : v) + out << to_bin(x, element_len_bits); + + out << std::flush; + } + + bool check_parity(std::string& word, bool even) { + size_t count = 0, i = 0; + + while(i < 7) { + if (word[i++] == '1') + ++count; + } + + return (count & 0x1) == (even ? 0 : 1); + } + + uint32_t select_bits(uint32_t data, uint8_t *indices, uint8_t n) { + uint32_t r = 0; + + for(uint8_t i = 0; i < n; ++i) + r |= (data & (1 << indices[i])) ? (1 << i) : 0; + + return r; + } + + void fec_extract_data_only(uint8_t *in_data, uint32_t len, uint8_t *indices, uint8_t n, uint8_t *out_data) { + for (uint32_t i = 0, out_index = 0; i < len; i += 2) { + uint8_t d1 = (select_bits(in_data[i], indices, n) & 0xff) << 4; + d1 |= (i + 1 < len) ? select_bits(in_data[i + 1], indices, n) & 0xff : 0; + + out_data[out_index++] = d1; } } @@ -127,11 +110,7 @@ namespace gr { // p4 01010101 // Syndrome matrix = columns of "cover bits" above - uint8_t H[16]; - - for(uint8_t i = 0; i < 16; i++) { - H[i] = 0; - } + uint8_t H[16] = { 0 }; uint8_t i0 = pack_nibble(1, 0, 0, 0); uint8_t i1 = pack_nibble(0, 1, 1, 1); @@ -164,9 +143,8 @@ namespace gr { uint8_t syndrome = pack_nibble((uint8_t)(p1 != p1c), (uint8_t)(p2 != p2c), (uint8_t)(p3 != p3c), (uint8_t)(p4 != p4c)); - if(syndrome != 0) { - uint8_t index = H[syndrome]; - v = v ^ pow2[index]; + if (syndrome) { + v ^= pow2[ H[syndrome] ]; } uint8_t d1 = bit(v, 1); @@ -178,22 +156,16 @@ namespace gr { } // Manual Hamming - void hamming_decode_soft(uint8_t* words, uint32_t len, uint8_t* out_data) { - uint32_t out_index = 0; - for(int i = 0; i < len; i+=2) { - uint8_t d1 = 0; - d1 = hamming_decode_soft_byte(words[i]); + void hamming_decode_soft(uint8_t *words, uint32_t len, uint8_t *out_data) { + for (uint32_t i = 0, out_index = 0; i < len; i += 2) { + uint8_t d1 = hamming_decode_soft_byte(words[i]) << 4; + d1 |= (i + 1 < len) ? hamming_decode_soft_byte(words[i + 1]) : 0; - uint8_t d2 = 0; - if(i+1 < len) - d2 = hamming_decode_soft_byte(words[i+1]); - - out_data[out_index] = (d1 << 4) | d2; - out_index++; + out_data[out_index++] = d1; } } - } + } } #endif /* UTILITIES_H */ From 53af2322b0305e2f306704290b46f231c3c78b8f Mon Sep 17 00:00:00 2001 From: Wosser1sProductions Date: Thu, 23 Feb 2017 21:16:27 +0100 Subject: [PATCH 2/3] Starting decoder rework ~ Reworked flow of most of the functions --- lib/decoder_impl.cc | 90 +++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/lib/decoder_impl.cc b/lib/decoder_impl.cc index 3dd895d..504de18 100644 --- a/lib/decoder_impl.cc +++ b/lib/decoder_impl.cc @@ -558,9 +558,9 @@ namespace gr { } } - float sum = 0.0f; - for(int i = 0; i < d_samples_per_symbol-1; i++) { - sum += instantaneous_freq[i]; + this->d_words_deshuffled.push_back(result); + } + #ifndef NDEBUG //print_vector(d_debug, d_words_deshuffled, "S", sizeof(uint8_t)*8); print_vector_raw(this->d_debug, this->d_words_deshuffled, sizeof(uint8_t) * 8); @@ -570,6 +570,7 @@ namespace gr { // We're done with these words if (is_header){ this->d_demodulated.erase(this->d_demodulated.begin(), this->d_demodulated.begin() + 5); + } else { this->d_demodulated.clear(); } } @@ -577,12 +578,21 @@ namespace gr { void decoder_impl::dewhiten(const uint8_t *prng) { uint32_t i, len = this->d_words_deshuffled.size(); - /*d_cfo_estimation = (*std::max_element(instantaneous_freq, instantaneous_freq+d_samples_per_symbol-1) + *std::min_element(instantaneous_freq, instantaneous_freq+d_samples_per_symbol-1)) / 2;*/ - } + for (i = 0; i < len; i++) { + uint8_t xor_b = this->d_words_deshuffled[i] ^ prng[i]; + + // TODO: reverse bit order is performed here, + // but is probably due to mistake in whitening or interleaving + xor_b = (xor_b & 0xF0) >> 4 | (xor_b & 0x0F) << 4; + xor_b = (xor_b & 0xCC) >> 2 | (xor_b & 0x33) << 2; + xor_b = (xor_b & 0xAA) >> 1 | (xor_b & 0x55) << 1; + this->d_words_dewhitened.push_back(xor_b); + } + + #ifndef NDEBUG + print_vector(this->d_debug, this->d_words_dewhitened, "W", sizeof(uint8_t) * 8); + #endif - void decoder_impl::correct_cfo(gr_complex* samples, int num_samples) { - for(uint32_t i = 0; i < num_samples; i++) { - samples[i] = samples[i] * gr_expj(2.0f * M_PI * -d_cfo_estimation * (d_dt * i)); this->d_words_deshuffled.clear(); } @@ -674,32 +684,50 @@ namespace gr { uint32_t rising = 0; static const uint32_t rising_required = 2; - void decoder_impl::msg_lora_frame(const uint8_t *frame_bytes, uint32_t frame_len) { + float theta1, theta2, theta3, theta4, + grad_prev = 0.0f, grad_cur; - } + for (uint32_t i = 1; i < decimation; i++) { + theta1 = arg(samples[ (i - 1) * decim_size ]); + theta2 = theta3 = arg(samples[ i * decim_size ]); + theta4 = arg(samples[ (i + 1) * decim_size ]); - int decoder_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) { - gr_complex* input = (gr_complex*) input_items[0]; - gr_complex* raw_input = (gr_complex*) input_items[1]; - float *out = (float*)output_items[0]; + // Unwrap phase + while ( (theta2 - theta1) > M_PI ) theta2 -= 2*M_PI; + while ( (theta2 - theta1) < -M_PI ) theta2 += 2*M_PI; + while ( (theta4 - theta3) > M_PI ) theta4 -= 2*M_PI; + while ( (theta4 - theta3) < -M_PI ) theta4 += 2*M_PI; + + grad_cur = (theta4 - theta3 - theta2 + theta1) * mul; + + if (grad_cur > grad_prev) + rising++; + + if (rising >= rising_required && grad_cur <= -20000) { + // TODO: Make this a bit more logical, e.g. d_bw / decimation * 2 -> 2 steps down + return i * decim_size; + } + + #ifndef NDEBUG + this->d_debug << "G:" << grad_cur << std::endl; + #endif + + grad_prev = grad_cur; + } + + return -1; + } + + uint8_t decoder_impl::lookup_cr(uint8_t bytevalue) { + switch (bytevalue & 0x0f) { + case 0x01: return 4; + case 0x0f: return 3; + case 0x0d: return 2; + case 0x0b: return 1; + default: return 4; + } + } - switch(d_state) { - case DETECT: { - int i = find_preamble_start_fast(&input[0], 2*d_samples_per_symbol); - if(i != -1) { - uint32_t c_window = std::min(2*d_samples_per_symbol - i, d_samples_per_symbol); - int32_t index_correction = 0; - float c = detect_upchirp(&input[i], c_window, d_samples_per_symbol / d_corr_decim_factor, &index_correction); - if(c > 0.8f) { - d_debug << "Cu: " << c << std::endl; - samples_to_file("/tmp/detectb", &input[i], d_samples_per_symbol, sizeof(gr_complex)); - samples_to_file("/tmp/detect", &input[i+index_correction], d_samples_per_symbol, sizeof(gr_complex)); - d_corr_fails = 0; - d_state = SYNC; - consume_each(i+index_correction); - break; void decoder_impl::msg_raw_chirp_debug(const gr_complex *raw_samples, uint32_t num_samples) { pmt::pmt_t chirp_blob = pmt::make_blob(raw_samples, sizeof(gr_complex) * num_samples); message_port_pub(pmt::mp("debug"), chirp_blob); From 5f01ddeaf193a20dcfa8bcb1ce07d5227ea41453 Mon Sep 17 00:00:00 2001 From: Wosser1sProductions Date: Fri, 17 Mar 2017 16:51:40 +0100 Subject: [PATCH 3/3] Detection and Sync improvements + Added header with debug macros + Added warning for SF 6: the samples are actually wrapped around to SF 12 ~ Unwrapped some function calls to liquid-dsp::liquid_unwrap_phase ~ Simplified some more code ~ Rewrote sliding_norm_cross_correlate_upchirp: Now we detect a falling edge and do a correlation from there to test the sync rate. Also added code that can perform a perfect overlay shift to the ideal chirp (but this leaves the falling edge inside the window) ~ Rewrote find_preamble_start_fast: Now detects the start of the preamble by looking for for absolute complex values above a threshold ~ Fixed ids in qa_BasicTest_Data.xml ~ qa_BasicTest.log contains test runs showing the improvements in passing tests. + Added createWhiteningValues.py to generate a sample with zeros and append the whitening sequence to a file so it can be averaged (untested). This uses lora-whitening-sequencer. ~ Added zero padding to whitening sequences in tables.h --- examples/_examplify.py | 1 - .../lora-whitening/createWhiteningValues.py | 65 ++ examples/lora-whitening/runScript.sh | 4 + examples/qa_BasicTest.log | 580 ++++++++++++++++++ examples/qa_BasicTest_Data.xml | 28 +- include/lora/decoder.h | 3 +- lib/dbugr.hpp | 82 +++ lib/decoder_impl.cc | 356 +++++++---- lib/decoder_impl.h | 14 +- lib/message_socket_sink_impl.cc | 2 + lib/tables.h | 12 +- lib/utilities.h | 21 +- 12 files changed, 1030 insertions(+), 138 deletions(-) create mode 100644 examples/lora-whitening/createWhiteningValues.py create mode 100644 examples/lora-whitening/runScript.sh create mode 100644 lib/dbugr.hpp diff --git a/examples/_examplify.py b/examples/_examplify.py index ade9bf5..81f159d 100644 --- a/examples/_examplify.py +++ b/examples/_examplify.py @@ -151,7 +151,6 @@ class Examplify: f.close() - if __name__ == '__main__': e = Examplify(6, "4/7", './lora-samples/', 'hackrf') diff --git a/examples/lora-whitening/createWhiteningValues.py b/examples/lora-whitening/createWhiteningValues.py new file mode 100644 index 0000000..a8cf11a --- /dev/null +++ b/examples/lora-whitening/createWhiteningValues.py @@ -0,0 +1,65 @@ +#!/usr/bin/python2 +import collections +import os +from loranode import RN2483Controller + +from ../_examplify.py import Examplify + +import lora, pmt, osmosdr +from gnuradio import gr, blocks + +class ReceiveWhitening: + def __init__(self, sf = 7, output_file = './test_out.csv'): + self.target_freq = 868.1e6 + self.sf = sf + self.samp_rate = 1e6 + self.capture_freq = 868.0e6 + self.offset = -(self.capture_freq - self.target_freq) + + self.inputFile = './' + self.outputFile = output_file + self.tempFile = '/tmp/whitening_out' + + self.tb = None + + def captureSequence(self, inputFile): + self.inputFile = inputFile + + if os.path.isfile(self.inputFile): + self.tb = gr.top_block() + + self.file_source = blocks.file_source(gr.sizeof_gr_complex*1, self.inputFile, False) # Repeat input: True/False + self.lora_lora_receiver_0 = lora.lora_receiver(self.samp_rate, self.capture_freq, self.offset, self.sf, self.samp_rate) + self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, self.samp_rate, True) + + self.tb.connect( (self.file_source, 0), (self.blocks_throttle_0, 0)) + self.tb.connect( (self.blocks_throttle_0, 0), (self.lora_lora_receiver_0, 0)) + + self.tb.run() + + self.tb = None + + if os.path.isfile(self.tempFile): + if os.path.isfile(self.outputFile): + inf = open(self.tempFile, 'r') + seq = inf.read() + print(seq) + out = open(self.outputFile, 'a') + out.write(seq) + out.close() + inf.close() + else: + raise Exception("[ReceiveWhitening] Outputfile '" + self.outputFile + "' does not exist!") + else: + raise Exception("[ReceiveWhitening] Tempfile '" + self.tempFile + "' does not exist!") + else: + raise Exception("[ReceiveWhitening] Inputfile '" + self.inputFile + "' does not exist!") + +if __name__ == '__main__': + ofile = 'tmp/tmp_whitening.cfile' + + examplifr = Examplify(7, "4/7") + whitening = ReceiveWhitening(7, './test_out.csv') + + examplifr.transmitToFile(["00000000000"] * 10, ofile) + whitening.captureSequence(ofile) diff --git a/examples/lora-whitening/runScript.sh b/examples/lora-whitening/runScript.sh new file mode 100644 index 0000000..4e3567b --- /dev/null +++ b/examples/lora-whitening/runScript.sh @@ -0,0 +1,4 @@ +# Uses lora-whitening-sequencer from: +# https://github.com/Wosser1sProductions/gr-lora-whitening-sequencer + +./lora-whitening-sequencer -sf 7 -in ./test_out.csv diff --git a/examples/qa_BasicTest.log b/examples/qa_BasicTest.log index 02215ca..3f48afb 100644 --- a/examples/qa_BasicTest.log +++ b/examples/qa_BasicTest.log @@ -116,3 +116,583 @@ Test serie 10: [u'88 88 88 88'] * 10 ====== Total passed: 75 out of 413 (18.16%) ====== Ran 1 test in 612.239s + + +-------- Test Results on 2017-02-27 15:38:54 --------- +Test serie 0: [u'01 23 45 67 89 ab cd ef'] * 10 + Test 1 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) +1 + Test 2 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) +3 + Test 3 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 4 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 5 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) +4 + Test 6 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 7 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) +5 + => Total passed: 27 out of 70 (38.57%) + +Test serie 1: [u'11 11 11'] * 1 + Test 8 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 9 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 10 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 11 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 12 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) +1 + Test 13 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 14 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) +1 + => Total passed: 4 out of 7 (57.14%) + +Test serie 2: [u'11 11 11'] * 5 + Test 15 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) + Test 16 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) +2 + Test 17 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 18 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 19 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) +3 + Test 20 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 21 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) +4 + => Total passed: 13 out of 35 (37.14%) + +Test serie 3: [u'aa aa aa aa'] * 3 + Test 22 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) +1 + Test 23 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 3 out of 3 (100.00%) +2 + Test 24 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 25 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 26 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) +2 + Test 27 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 28 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) +2 + => Total passed: 10 out of 21 (47.62%) + +Test serie 4: [u'ff ff ff ff'] * 1 + Test 29 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) +1 + Test 30 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) -1 + Test 31 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 32 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 33 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 34 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 35 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 2 out of 7 (28.57%) + +Test serie 5: [u'ff ff ff ff'] * 10 + Test 36 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) +6 + Test 37 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) +1 + Test 38 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 39 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 40 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 41 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 42 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 9 out of 10 ( 90.00%) +6 + => Total passed: 23 out of 70 (32.86%) + +Test serie 6: [u'55 55 55 55'] * 3 + Test 43 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) -2 + Test 44 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) + Test 45 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 46 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 47 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) +1 + Test 48 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 49 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) +3 + => Total passed: 9 out of 21 (42.86%) + +Test serie 7: [u'55 55 55 55'] * 10 + Test 50 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) +6 + Test 51 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) +4 + Test 52 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 53 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 54 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) +3 + Test 55 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 56 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) +7 + => Total passed: 34 out of 70 (48.57%) + +Test serie 8: [u'88 88 88 88'] * 1 + Test 57 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 58 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) -1 + Test 59 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 60 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 61 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 62 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 63 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 2 out of 7 (28.57%) + +Test serie 9: [u'88 88 88 88'] * 5 + Test 64 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) +2 + Test 65 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 5 out of 5 (100.00%) +3 + Test 66 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) -1 + Test 67 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 68 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 69 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 70 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) +4 + => Total passed: 14 out of 35 (40.00%) + +Test serie 10: [u'88 88 88 88'] * 10 + Test 71 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) +1 + Test 72 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) +6 + Test 73 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 74 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 75 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 76 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 77 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) +6 + => Total passed: 24 out of 70 (34.29%) + + + ====== Total passed: 162 out of 413 (39.23%) ====== +Ran 1 test in 490.191s + +-------- Test Results on 2017-03-06 11:41:54 --------- +Test serie 0: [u'01 23 45 67 89 ab cd ef'] * 10 + Test 1 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 2 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + Test 3 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 4 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 5 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 6 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 7 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + => Total passed: 24 out of 70 (34.29%) + +Test serie 1: [u'11 11 11'] * 1 + Test 8 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 9 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 10 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 11 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 12 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 13 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 14 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + => Total passed: 3 out of 7 (42.86%) + +Test serie 2: [u'11 11 11'] * 5 + Test 15 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + Test 16 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 17 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 18 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 19 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 5 ( 40.00%) + Test 20 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 21 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + => Total passed: 4 out of 35 (11.43%) + +Test serie 3: [u'aa aa aa aa'] * 3 + Test 22 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) + Test 23 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 24 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 25 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 26 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 27 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 28 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) + => Total passed: 7 out of 21 (33.33%) + +Test serie 4: [u'ff ff ff ff'] * 1 + Test 29 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 30 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 31 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 32 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 33 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 34 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 35 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 1 out of 7 (14.29%) + +Test serie 5: [u'ff ff ff ff'] * 10 + Test 36 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + Test 37 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 9 out of 10 ( 90.00%) + Test 38 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 39 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 40 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 41 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 42 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + => Total passed: 19 out of 70 (27.14%) + +Test serie 6: [u'55 55 55 55'] * 3 + Test 43 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 44 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 45 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 46 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 47 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 48 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 49 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + => Total passed: 7 out of 21 (33.33%) + +Test serie 7: [u'55 55 55 55'] * 10 + Test 50 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) + Test 51 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + Test 52 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 53 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 54 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 3 out of 10 ( 30.00%) + Test 55 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 56 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 10 ( 30.00%) + => Total passed: 22 out of 70 (31.43%) + +Test serie 8: [u'88 88 88 88'] * 1 + Test 57 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 58 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 59 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 60 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 61 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 62 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 63 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 1 out of 7 (14.29%) + +Test serie 9: [u'88 88 88 88'] * 5 + Test 64 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 5 ( 40.00%) + Test 65 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 66 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 67 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 68 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 69 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 70 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) + => Total passed: 9 out of 35 (25.71%) + +Test serie 10: [u'88 88 88 88'] * 10 + Test 71 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + Test 72 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 73 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 74 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 75 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 76 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 77 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) + => Total passed: 21 out of 70 (30.00%) + + + ====== Total passed: 118 out of 413 (28.57%) ====== +Ran 1 test in 349.914s + + +-------- Test Results on 2017-03-06 14:41:02 --------- +Test serie 0: [u'01 23 45 67 89 ab cd ef'] * 10 + Test 1 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 2 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + Test 3 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 4 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 5 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 6 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 7 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + => Total passed: 25 out of 70 (35.71%) + +Test serie 1: [u'11 11 11'] * 1 + Test 8 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 9 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 10 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 11 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 12 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 13 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 14 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 4 out of 7 (57.14%) + +Test serie 2: [u'11 11 11'] * 5 + Test 15 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 16 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 5 out of 5 (100.00%) + Test 17 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 18 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 19 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 20 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 21 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + => Total passed: 17 out of 35 (48.57%) + +Test serie 3: [u'aa aa aa aa'] * 3 + Test 22 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) + Test 23 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 24 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 25 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 26 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 27 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 28 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + => Total passed: 9 out of 21 (42.86%) + +Test serie 4: [u'ff ff ff ff'] * 1 + Test 29 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 30 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 31 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 32 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 33 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 34 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 35 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 2 out of 7 (28.57%) + +Test serie 5: [u'ff ff ff ff'] * 10 + Test 36 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 37 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 38 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 39 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 40 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 41 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 42 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) + => Total passed: 25 out of 70 (35.71%) + +Test serie 6: [u'55 55 55 55'] * 3 + Test 43 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 44 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) + Test 45 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 46 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 47 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 48 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 49 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + => Total passed: 9 out of 21 (42.86%) + +Test serie 7: [u'55 55 55 55'] * 10 + Test 50 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) + Test 51 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 9 out of 10 ( 90.00%) + Test 52 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 53 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 54 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) + Test 55 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 56 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + => Total passed: 31 out of 70 (44.29%) + +Test serie 8: [u'88 88 88 88'] * 1 + Test 57 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 58 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 59 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 60 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 61 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 62 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 63 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 1 out of 7 (14.29%) + +Test serie 9: [u'88 88 88 88'] * 5 + Test 64 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 5 ( 40.00%) + Test 65 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 66 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + Test 67 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 68 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 69 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 70 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) + => Total passed: 12 out of 35 (34.29%) + +Test serie 10: [u'88 88 88 88'] * 10 + Test 71 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 72 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 73 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 74 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 75 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 76 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 77 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 10 out of 10 (100.00%) + => Total passed: 25 out of 70 (35.71%) + + + ====== Total passed: 160 out of 413 (38.74%) ====== +Ran 1 test in 405.855s + + +-------- Test Results on 2017-03-08 16:50:19 --------- +Test serie 0: [u'01 23 45 67 89 ab cd ef'] * 10 + Test 1 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 2 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 3 out of 10 ( 30.00%) + Test 3 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 4 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 5 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 6 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 7 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) + => Total passed: 22 out of 70 (31.43%) + +Test serie 1: [u'11 11 11'] * 1 + Test 8 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 9 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 10 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 11 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 12 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 13 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 14 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 4 out of 7 (57.14%) + +Test serie 2: [u'11 11 11'] * 5 + Test 15 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) + Test 16 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + Test 17 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 18 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 19 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 20 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 21 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + => Total passed: 12 out of 35 (34.29%) + +Test serie 3: [u'aa aa aa aa'] * 3 + Test 22 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 23 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 24 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 25 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 26 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 27 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 28 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + => Total passed: 7 out of 21 (33.33%) + +Test serie 4: [u'ff ff ff ff'] * 1 + Test 29 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 30 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 31 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 32 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 33 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 34 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 35 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 3 out of 7 (42.86%) + +Test serie 5: [u'ff ff ff ff'] * 10 + Test 36 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 37 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) + Test 38 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 39 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 40 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 41 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 42 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + => Total passed: 20 out of 70 (28.57%) + +Test serie 6: [u'55 55 55 55'] * 3 + Test 43 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 44 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 45 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 46 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 47 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 48 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 49 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + => Total passed: 9 out of 21 (42.86%) + +Test serie 7: [u'55 55 55 55'] * 10 + Test 50 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 51 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) + Test 52 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 53 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 54 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 9 out of 10 ( 90.00%) + Test 55 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 56 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + => Total passed: 29 out of 70 (41.43%) + +Test serie 8: [u'88 88 88 88'] * 1 + Test 57 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 58 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 59 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 60 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 61 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 62 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 63 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 3 out of 7 (42.86%) + +Test serie 9: [u'88 88 88 88'] * 5 + Test 64 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) + Test 65 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 66 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + Test 67 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 68 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 69 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 70 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) + => Total passed: 15 out of 35 (42.86%) + +Test serie 10: [u'88 88 88 88'] * 10 + Test 71 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + Test 72 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 73 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 74 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 75 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 76 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 77 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + => Total passed: 18 out of 70 (25.71%) + + + ====== Total passed: 142 out of 413 (34.38%) ====== +Ran 1 test in 278.433s + + +-------- Test Results on 2017-03-09 17:06:45 --------- +Test serie 0: [u'01 23 45 67 89 ab cd ef'] * 10 + Test 1 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 2 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 8 out of 10 ( 80.00%) + Test 3 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 4 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 5 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 6 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 7 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 9 out of 10 ( 90.00%) + => Total passed: 31 out of 70 (44.29%) + +Test serie 1: [u'11 11 11'] * 1 + Test 8 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 9 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 10 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 11 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 12 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 13 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 14 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 3 out of 7 (42.86%) + +Test serie 2: [u'11 11 11'] * 5 + Test 15 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + Test 16 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) + Test 17 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 18 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 19 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 20 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 21 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 5 (100.00%) + => Total passed: 13 out of 35 (37.14%) + +Test serie 3: [u'aa aa aa aa'] * 3 + Test 22 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 23 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 24 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 25 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 26 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 27 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 28 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + => Total passed: 10 out of 21 (47.62%) + +Test serie 4: [u'ff ff ff ff'] * 1 + Test 29 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 30 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 31 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 32 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 33 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 34 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 35 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 3 out of 7 (42.86%) + +Test serie 5: [u'ff ff ff ff'] * 10 + Test 36 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 37 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 9 out of 10 ( 90.00%) + Test 38 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 39 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 40 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 41 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 42 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + => Total passed: 23 out of 70 (32.86%) + +Test serie 6: [u'55 55 55 55'] * 3 + Test 43 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 44 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 3 out of 3 (100.00%) + Test 45 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 46 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 47 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + Test 48 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) + Test 49 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 2 out of 3 ( 66.67%) + => Total passed: 10 out of 21 (47.62%) + +Test serie 7: [u'55 55 55 55'] * 10 + Test 50 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + Test 51 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + Test 52 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 53 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 54 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 55 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 56 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 6 out of 10 ( 60.00%) + => Total passed: 23 out of 70 (32.86%) + +Test serie 8: [u'88 88 88 88'] * 1 + Test 57 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 58 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 1 out of 1 (100.00%) + Test 59 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 60 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 61 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 62 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) + Test 63 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) + => Total passed: 3 out of 7 (42.86%) + +Test serie 9: [u'88 88 88 88'] * 5 + Test 64 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) + Test 65 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 4 out of 5 ( 80.00%) + Test 66 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) + Test 67 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 68 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 69 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) + Test 70 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) + => Total passed: 11 out of 35 (31.43%) + +Test serie 10: [u'88 88 88 88'] * 10 + Test 71 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) + Test 72 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 7 out of 10 ( 70.00%) + Test 73 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 74 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 75 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 76 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) + Test 77 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) + => Total passed: 16 out of 70 (22.86%) + + + ====== Total passed: 146 out of 413 (35.35%) ====== +Ran 1 test in 278.635s + diff --git a/examples/qa_BasicTest_Data.xml b/examples/qa_BasicTest_Data.xml index 327d8a2..0b2e35e 100644 --- a/examples/qa_BasicTest_Data.xml +++ b/examples/qa_BasicTest_Data.xml @@ -504,7 +504,7 @@ 88 88 88 88 1 - + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_009.cfile 7 @@ -512,7 +512,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_009.cfile 8 @@ -520,7 +520,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_009.cfile 12 @@ -528,7 +528,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_009.cfile 6 @@ -536,7 +536,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_009.cfile 7 @@ -544,7 +544,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_009.cfile 6 @@ -552,7 +552,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_009.cfile 7 @@ -560,7 +560,7 @@ 88 88 88 88 5 - + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_010.cfile 7 @@ -568,7 +568,7 @@ 88 88 88 88 10 - + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_010.cfile 8 @@ -576,7 +576,7 @@ 88 88 88 88 10 - + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_010.cfile 12 @@ -584,7 +584,7 @@ 88 88 88 88 10 - + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_010.cfile 6 @@ -592,7 +592,7 @@ 88 88 88 88 10 - + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_010.cfile 7 @@ -600,7 +600,7 @@ 88 88 88 88 10 - + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_010.cfile 6 @@ -608,7 +608,7 @@ 88 88 88 88 10 - + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_010.cfile 7 diff --git a/include/lora/decoder.h b/include/lora/decoder.h index 90c2830..d5fd2c3 100644 --- a/include/lora/decoder.h +++ b/include/lora/decoder.h @@ -690,8 +690,7 @@ namespace gr { * \ingroup lora * */ - class LORA_API decoder : virtual public gr::sync_block - { + class LORA_API decoder : virtual public gr::sync_block { public: typedef boost::shared_ptr sptr; diff --git a/lib/dbugr.hpp b/lib/dbugr.hpp new file mode 100644 index 0000000..a06545e --- /dev/null +++ b/lib/dbugr.hpp @@ -0,0 +1,82 @@ +#ifndef DBUGR_HPP +#define DBUGR_HPP + +#include +#include + +#include "utilities.h" + +#undef NDEBUG +//#define NDEBUG + +#ifdef NDEBUG + #define DBGR_PAUSE(MSG) + #define DBGR_WRITE_SIGNAL(IDEAL_SIG_FP, SAMPLE_SIG_FP, WINDOW, OFFSET, MIN, MAX, FULL, PAUSE, MSG) +#else + #define DBGR_PAUSE(MSG) system("read -rsp $'" #MSG "\nPress any key to continue...\n' -n 1 key") + + #define DBGR_QUICK_TO_FILE(FILEPATH, APPEND, DATA, SIZE, FORMAT) \ + do { \ + int32_t DBGR_j; \ + char DBGR_buf[20]; \ + std::ofstream DBGR_out_file; \ + DBGR_out_file.open(FILEPATH, std::ios::out | (APPEND ? std::ios::app : std::ios::out )); \ + \ + for (DBGR_j = 0; DBGR_j < int32_t(SIZE); DBGR_j++) { \ + sprintf(DBGR_buf, FORMAT, DATA[DBGR_j]); \ + DBGR_out_file.write(DBGR_buf, strlen(DBGR_buf)); \ + } \ + \ + if (APPEND) DBGR_out_file.write("\n", sizeof(char)); \ + \ + } while(0) \ + + #define DBGR_WRITE_SIGNAL(IDEAL_SIG_FP, SAMPLE_SIG_FP, WINDOW, OFFSET, MIN, MAX, FULL, PAUSE, MSG) \ + do { \ + int32_t DBGR_j; \ + char DBGR_buf[20]; \ + const char DBGR_delim[] = "-----------------------------------------------------------------\n\0"; \ + std::ofstream DBGR_out_file; \ + DBGR_out_file.open("/tmp/DBGR.txt", std::ios::out); \ + \ + \ + printf("DBGR_Ideal\n"); \ + for (DBGR_j = 0; DBGR_j < int32_t(WINDOW); DBGR_j++) { \ + sprintf(DBGR_buf, "%f\n", IDEAL_SIG_FP[DBGR_j]); \ + DBGR_out_file.write(DBGR_buf, strlen(DBGR_buf)); \ + } DBGR_out_file.write(DBGR_delim, strlen(DBGR_delim)); \ + \ + printf("%s", DBGR_delim); \ + \ + printf("DBGR_Before\n"); \ + for (DBGR_j = 0; DBGR_j < int32_t(WINDOW); DBGR_j++) { \ + sprintf(DBGR_buf, "%f\n", gr::lora::clamp(SAMPLE_SIG_FP[DBGR_j], -0.5f, 0.5f)); \ + DBGR_out_file.write(DBGR_buf, strlen(DBGR_buf)); \ + } DBGR_out_file.write(DBGR_delim, strlen(DBGR_delim)); \ + \ + printf("%s", DBGR_delim); \ + \ + printf("DBGR_After %d of %d in %d\n", MIN, MAX, WINDOW); \ + for (DBGR_j = OFFSET; DBGR_j < int32_t(OFFSET > 0 ? WINDOW : MAX); DBGR_j++) { \ + sprintf(DBGR_buf, "%f\n", gr::lora::clamp(*(SAMPLE_SIG_FP + DBGR_j), -0.5f, 0.5f)); \ + DBGR_out_file.write(DBGR_buf, strlen(DBGR_buf)); \ + } DBGR_out_file.write(DBGR_delim, strlen(DBGR_delim)); \ + \ + printf("%s", DBGR_delim); \ + \ + /*if (FULL) { \ + printf("DBGR_Full\n"); \ + for (DBGR_j = 0; DBGR_j < WINDOW; DBGR_j++) { \ + sprintf(buf, "%f\n\0", SAMPLE_SIG_FP[DBGR_j]); \ + DBGR_out_file.write(DBGR_buf, strlen(DBGR_buf)); \ + } DBGR_out_file.write(DBGR_delim, strlen(DBGR_delim)); \ + printf("%s", DBGR_delim); \ + }*/ \ + \ + printf("DBGR_End\n"); \ + DBGR_out_file.close(); \ + if(PAUSE) DBGR_PAUSE(MSG); \ + } while(0) +#endif + +#endif // DBUGR_HPP diff --git a/lib/decoder_impl.cc b/lib/decoder_impl.cc index 504de18..11777c4 100644 --- a/lib/decoder_impl.cc +++ b/lib/decoder_impl.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "decoder_impl.h" #include "tables.h" #include "utilities.h" @@ -34,7 +35,8 @@ //#define CFO_CORRECT 1 /// Correct shift fft estimation -#undef NDEBUG /// Debug printing +//#undef NDEBUG /// Debug printing +#include "dbugr.hpp" namespace gr { namespace lora { @@ -55,8 +57,12 @@ namespace gr { if (sf < 6 || sf > 13) { //throw std::invalid_argument("[LoRa Decoder] ERROR : Spreading factor should be between 6 and 12 (inclusive)!\n Other values are currently not supported."); - std::cerr << "[LoRa Decoder] ERROR : Spreading factor should be between 6 and 12 (inclusive)!\n Other values are currently not supported." << std::endl; + std::cerr << "[LoRa Decoder] ERROR : Spreading factor should be between 6 and 12 (inclusive)!" << std::endl + << " Other values are currently not supported." << std::endl; exit(1); + } else if (sf == 6) { + std::cerr << "[LoRa Decoder] WARNING : Spreading factor wrapped around to 12 due to incompatibility in hardware!" << std::endl; + sf = 12; } #ifndef NDEBUG @@ -109,6 +115,10 @@ namespace gr { // Register gnuradio ports this->message_port_register_out(pmt::mp("frames")); this->message_port_register_out(pmt::mp("debug")); + + + // // Whitening empty file + // DBGR_QUICK_TO_FILE("/tmp/whitening_out", false, g, -1, ""); } /** @@ -148,8 +158,15 @@ namespace gr { } // Store instant. frequency - instantaneous_frequency(&this->d_downchirp[0], &this->d_downchirp_ifreq[0], this->d_samples_per_symbol); - instantaneous_frequency(&this->d_upchirp[0], &this->d_upchirp_ifreq[0], this->d_samples_per_symbol); + this->instantaneous_frequency(&this->d_downchirp[0], &this->d_downchirp_ifreq[0], this->d_samples_per_symbol); + this->instantaneous_frequency(&this->d_upchirp[0], &this->d_upchirp_ifreq[0], this->d_samples_per_symbol); + + // Precalc for correlation + this->d_upchirp_avg = std::accumulate(this->d_upchirp_ifreq.begin(), this->d_upchirp_ifreq.end(), 0.0f) / (float)this->d_samples_per_symbol; + this->d_upchirp_stddev = this->stddev(&this->d_upchirp_ifreq[0], this->d_samples_per_symbol, this->d_upchirp_avg); + + this->d_downchirp_avg = std::accumulate(this->d_downchirp_ifreq.begin(), this->d_downchirp_ifreq.end(), 0.0f) / (float)this->d_samples_per_symbol; + this->d_downchirp_stddev = this->stddev(&this->d_downchirp_ifreq[0], this->d_samples_per_symbol, this->d_downchirp_avg); samples_to_file("/tmp/downchirp", &this->d_downchirp[0], this->d_downchirp.size(), sizeof(gr_complex)); samples_to_file("/tmp/upchirp", &this->d_upchirp[0], this->d_upchirp.size(), sizeof(gr_complex)); @@ -206,19 +223,24 @@ namespace gr { } void decoder_impl::instantaneous_frequency(const gr_complex *in_samples, float *out_ifreq, uint32_t window) { - float iphase[window]; - if (window < 2) { // TODO: throw warning here std::cerr << "LoRa Decoder Warning: window size < 2 !" << std::endl; return; } - this->instantaneous_phase(in_samples, iphase, window); + /* instantaneous_phase */ + float iphase_1, iphase_2; - // Instant freq for (uint32_t i = 1; i < window; i++) { - out_ifreq[i - 1] = iphase[i] - iphase[i - 1]; + iphase_1 = std::arg(in_samples[i - 1]); + iphase_2 = std::arg(in_samples[i]); + + // Unwrapped loops from liquid_unwrap_phase + while ( (iphase_2 - iphase_1) > M_PI ) iphase_2 -= 2*M_PI; + while ( (iphase_2 - iphase_1) < -M_PI ) iphase_2 += 2*M_PI; + + out_ifreq[i - 1] = iphase_2 - iphase_1; } // Make sure there is no strong gradient if this value is accessed by mistake @@ -226,19 +248,23 @@ namespace gr { } inline void decoder_impl::instantaneous_phase(const gr_complex *in_samples, float *out_iphase, uint32_t window) { - for (uint32_t i = 0; i < window; i++) { - out_iphase[i] = arg(in_samples[i]); - // = the same as atan2(imag(in_samples[i]),real(in_samples[i])); - } + out_iphase[0] = std::arg(in_samples[0]); - liquid_unwrap_phase(out_iphase, window); + for (uint32_t i = 1; i < window; i++) { + out_iphase[i] = std::arg(in_samples[i]); + // = the same as atan2(imag(in_samples[i]),real(in_samples[i])); + + // Unwrapped loops from liquid_unwrap_phase + while ( (out_iphase[i] - out_iphase[i-1]) > M_PI ) out_iphase[i] -= 2*M_PI; + while ( (out_iphase[i] - out_iphase[i-1]) < -M_PI ) out_iphase[i] += 2*M_PI; + } } float decoder_impl::cross_correlate(const gr_complex *samples_1, const gr_complex *samples_2, int window) { float result = 0.0f; for (int i = 0; i < window; i++) { - result += real(samples_1[i] * conj(samples_2[i])); + result += std::real(samples_1[i] * std::conj(samples_2[i])); } result /= (float)window; @@ -249,25 +275,23 @@ namespace gr { float decoder_impl::detect_downchirp(const gr_complex *samples, uint32_t window) { float samples_ifreq[window]; - instantaneous_frequency(samples, samples_ifreq, window); - return norm_cross_correlate(samples_ifreq, &this->d_downchirp_ifreq[0], window); + this->instantaneous_frequency(samples, samples_ifreq, window); + return this->norm_cross_correlate_downchirp(samples_ifreq, window - 1); } /** * Calculate normalized cross correlation of real values. * See https://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation. */ - float decoder_impl::norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window) { + float decoder_impl::norm_cross_correlate_downchirp(const float *samples, uint32_t window) { float result = 0.0f; - float average_1 = std::accumulate(samples_1, samples_1 + window, 0.0f) / window; - float average_2 = std::accumulate(samples_2, samples_2 + window, 0.0f) / window; - float sd_1 = stddev(samples_1, window, average_1); - float sd_2 = stddev(samples_2, window, average_2); + const float average = std::accumulate(samples, samples + window, 0.0f) / (float)(window); + const float sd = this->stddev(samples, window, average); - for (uint32_t i = 0; i < window - 1; i++) { - result += (samples_1[i] - average_1) * (samples_2[i] - average_2) - / (sd_1 * sd_2); + for (uint32_t i = 0; i < window; i++) { + result += (samples[i] - average) * (this->d_downchirp_ifreq[i] - this->d_downchirp_avg) + / (sd * this->d_downchirp_stddev); } result /= (float)(window - 1); @@ -275,41 +299,119 @@ namespace gr { return result; } - float decoder_impl::sliding_norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window, uint32_t slide, int32_t *index) { - float correlations[slide * 2]; - float samples_1_padded[window + slide * 2] = { 0.0f }; + float decoder_impl::sliding_norm_cross_correlate_upchirp(const float *samples, uint32_t window, uint32_t slide, int32_t *index) { + (void) slide; - double average_1 = std::accumulate(samples_1, samples_1 + window, 0.0) / window; - double average_2 = std::accumulate(samples_2, samples_2 + window, 0.0) / window; - double sd_1 = stddev(samples_1, window, average_1); - double sd_2 = stddev(samples_2, window, average_2); + bool found_change = false; + uint32_t max = 0, min; + const uint32_t coeff = 16; - uint32_t i, j; - float result; - - // Create padding on both sides of the samples - for (i = 0; i < window; i++) { - samples_1_padded[i + slide - 1] = samples_1[i]; - } - - // Slide and correlate - for (i = 0; i < 2 * slide; i++) { - result = 0.0f; - - for (j = 0; j < window; j++) { - result += (samples_1_padded[i + j] - average_1) * (samples_2[j] - average_2) - / (sd_1 * sd_2); + for (uint32_t i = 0; i < window - coeff - 1; i += coeff / 2) { + if (samples[i] - samples[i + coeff] > 0.2f) { // Goes down + max = i; + found_change = true; + break; } - - correlations[i] = result / (float)window; } - // Determine best correlation - uint32_t argmax = (std::max_element(correlations, correlations + slide * 2) - correlations); - // Determine how much we have to slide before the best correlation is reached - *index = argmax - slide; + if (!found_change) { + return 0.0f; + } - return correlations[argmax]; + max = std::max_element(samples + gr::lora::clamp((int)(max - coeff), 0, (int)window), + samples + gr::lora::clamp(max + coeff, 0u, window)) - samples; + min = std::min_element(samples + gr::lora::clamp(max + 1u, 0u, window), + samples + gr::lora::clamp(max + 2u * coeff, 0u, window)) - samples; + + max += (min - max) / 2; + + *index = max; + + // Extra to allow falling edge on 99% of sample == Practically synced + // Should improve detection by not discarding almost synced samples, but doesn't.. +// if ((max - coeff / 2) > (window * 0.98f)) { +//// printf("ALREADY SYNCED\n"); +// *index = 0; +// return 0.99f; +// } + + float max_correlation = 0.0f; + + const float average = std::accumulate(samples + max, samples + window, 0.0f) / (window - max); + const float au = std::accumulate(&this->d_upchirp_ifreq[max], &this->d_upchirp_ifreq[window], 0.0f) / (window - max); + const float sd = this->stddev(&samples[max], window - max, average) * this->stddev(&this->d_upchirp_ifreq[max], window - max, au); + + for (uint32_t j = max; j < window; j++) { + max_correlation += (samples[j] - average) * (this->d_upchirp_ifreq[j] - au) / sd; + } + + max_correlation /= (float)(window - max); + + return max_correlation; + + /* NEWER *********************************************************************/ + /// Perfect shift to ideal frequency +// const uint32_t t_low = window / 4, +// t_mid = window / 2; + +// // Average before compare +// const uint32_t coeff = 20; +// float avg = std::accumulate(&samples[t_mid] - coeff / 2, &samples[t_mid] + coeff / 2, 0.0f) / coeff; +//// printf("%5d\t%12.6f\n", t_mid, avg); + + +// uint32_t idx = std::lower_bound( this->d_upchirp_ifreq.begin() + t_low, +// this->d_upchirp_ifreq.begin() + t_mid, +// avg) +// - this->d_upchirp_ifreq.begin(); +// if (idx <= t_low || idx >= t_mid) { +// return 0.5f; +// } +// *index = t_mid - idx; +//// printf("idx %5d\n", idx); +//// printf("slide with: %5d\n", idx - t_mid); +//// printf("slide with: %5d\n", idx - t_mid - slide); +// printf("slide with: %5d\n", *index); + +// return 0.9f; + /****************************************************************************/ + + /* OLD *********************************************************************/ +// float samples_1_padded[window + slide * 2] = { 0.0f }; + +// float average = std::accumulate(samples, samples + window, 0.0f) / window; +// float sd = this->stddev(samples, window, average); + +// uint32_t i, j, max_cor_idx = -1; +// float result, max_correlation = -1000.0f; + +// // Create padding on both sides of the samples +// for (i = 0; i < window; i++) { +// samples_1_padded[i + slide - 1] = samples[i]; +// } + +// // Slide and correlate +// for (i = 0; i < 2 * slide; i++) { +// result = 0.0f; + +// for (j = 0; j < window; j++) { +// result += (samples_1_padded[i + j] - average) * (this->d_upchirp_ifreq[j] - this->d_upchirp_avg) +// / (sd * this->d_upchirp_stddev); +// } + +// // Determine best correlation +// result /= (float)window; +// if (result > max_correlation) { +// max_correlation = result; +// max_cor_idx = i; +// } +// } + +// // Determine how much we have to slide before the best correlation is reached +// *index = max_cor_idx - slide; +//// printf("slide with: %5d\n", *index); +// return max_correlation; + /****************************************************************************/ } float decoder_impl::stddev(const float *values, uint32_t len, float mean) { @@ -327,11 +429,12 @@ namespace gr { float decoder_impl::detect_upchirp(const gr_complex *samples, uint32_t window, uint32_t slide, int32_t *index) { float samples_ifreq[window]; - instantaneous_frequency(samples, samples_ifreq, window); - return sliding_norm_cross_correlate(samples_ifreq, &this->d_upchirp_ifreq[0], window, slide, index); + this->instantaneous_frequency(samples, samples_ifreq, window); + + return this->sliding_norm_cross_correlate_upchirp(samples_ifreq, window, slide, index); } - unsigned int decoder_impl::get_shift_fft(gr_complex *samples) { + unsigned int decoder_impl::get_shift_fft(const gr_complex *samples) { float fft_mag[this->d_number_of_bins]; gr_complex mult_hf[this->d_samples_per_symbol]; @@ -347,7 +450,7 @@ namespace gr { // Multiply with ideal downchirp for (uint32_t i = 0; i < this->d_samples_per_symbol; i++) { - mult_hf[i] = conj(samples[i] * this->d_downchirp[i]); + mult_hf[i] = std::conj(samples[i] * this->d_downchirp[i]); } samples_to_file("/tmp/mult", &mult_hf[0], this->d_samples_per_symbol, sizeof(gr_complex)); @@ -382,7 +485,7 @@ namespace gr { // Determine instant phase for (unsigned int i = 0; i < this->d_samples_per_symbol; i++) { - instantaneous_phase[i] = arg(samples[i]); + instantaneous_phase[i] = std::arg(samples[i]); } liquid_unwrap_phase(instantaneous_phase, this->d_samples_per_symbol); @@ -407,7 +510,7 @@ namespace gr { avg /= (float)osr; - float diff = abs(last_avg - avg); + const float diff = abs(last_avg - avg); if (diff > max_if_diff) { max_if_diff = diff; @@ -424,18 +527,16 @@ namespace gr { bool decoder_impl::demodulate(gr_complex *samples, bool is_header) { unsigned int bin_idx = this->max_frequency_gradient_idx(samples); - //unsigned int bin_idx = get_shift_fft(samples); - //unsigned int bin_idx_test = get_shift_fft(samples); unsigned int bin_idx_test = 0; // Header has additional redundancy if (is_header) { - bin_idx /= 4; - bin_idx_test /= 4; + bin_idx /= 4u; + bin_idx_test /= 4u; } // Decode (actually gray encode) the bin to get the symbol value - unsigned int word = gray_encode(bin_idx); + unsigned int word = /* LiquidDSP:: */ gray_encode(bin_idx); #ifndef NDEBUG this->d_debug << gr::lora::to_bin(word, is_header ? this->d_sf - 2 : this->d_sf) << " " << bin_idx << std::endl; #endif @@ -453,7 +554,7 @@ namespace gr { } void decoder_impl::deinterleave(uint32_t ppm) { - unsigned int bits_per_word = this->d_words.size(); + const unsigned int bits_per_word = this->d_words.size(); if (bits_per_word > 8) { // Not sure if this can ever occur. It would imply coding rate high than 4/8 e.g. 4/9. @@ -469,15 +570,15 @@ namespace gr { offset_diag = offset_start; for (unsigned int j = 0; j < bits_per_word; j++) { - uint8_t power = 1 << j; - unsigned int power_check = 1 << offset_diag; + const uint8_t power = 1 << j; + const unsigned int power_check = 1 << offset_diag; if (this->d_words[j] & power_check) { // Mask triggers d += power; } - if (offset_diag) offset_diag--; - else offset_diag = ppm - 1; + if (offset_diag) offset_diag--; + else offset_diag = ppm - 1; } offset_start--; @@ -578,6 +679,10 @@ namespace gr { void decoder_impl::dewhiten(const uint8_t *prng) { uint32_t i, len = this->d_words_deshuffled.size(); + // // Whitening out + // if (prng != gr::lora::prng_header) + // DBGR_QUICK_TO_FILE("/tmp/whitening_out", true, this->d_words_deshuffled, len, "0x%02X,"); + for (i = 0; i < len; i++) { uint8_t xor_b = this->d_words_deshuffled[i] ^ prng[i]; @@ -677,45 +782,68 @@ namespace gr { int decoder_impl::find_preamble_start_fast(gr_complex *samples, uint32_t len) { (void) len; - const uint32_t decimation = this->d_corr_decim_factor; + const uint32_t decimation = this->d_corr_decim_factor * 4; const uint32_t decim_size = this->d_samples_per_symbol / decimation; + const float detect_thresh = 0.01f; - const float mul = (float)this->d_samples_per_second / (2.0f * M_PI); - uint32_t rising = 0; - static const uint32_t rising_required = 2; - - float theta1, theta2, theta3, theta4, - grad_prev = 0.0f, grad_cur; - - for (uint32_t i = 1; i < decimation; i++) { - theta1 = arg(samples[ (i - 1) * decim_size ]); - theta2 = theta3 = arg(samples[ i * decim_size ]); - theta4 = arg(samples[ (i + 1) * decim_size ]); - - // Unwrap phase - while ( (theta2 - theta1) > M_PI ) theta2 -= 2*M_PI; - while ( (theta2 - theta1) < -M_PI ) theta2 += 2*M_PI; - while ( (theta4 - theta3) > M_PI ) theta4 -= 2*M_PI; - while ( (theta4 - theta3) < -M_PI ) theta4 += 2*M_PI; - - grad_cur = (theta4 - theta3 - theta2 + theta1) * mul; - - if (grad_cur > grad_prev) - rising++; - - if (rising >= rising_required && grad_cur <= -20000) { - // TODO: Make this a bit more logical, e.g. d_bw / decimation * 2 -> 2 steps down + // Absolute value + for (uint32_t i = 1; i < decimation - 1; i++) { + if ( std::abs(samples[ i * decim_size]) > detect_thresh + && std::abs(samples[(i - 1) * decim_size]) < std::abs(samples[i * decim_size]) + && std::abs(samples[(i + 1) * decim_size]) > std::abs(samples[i * decim_size]) + ) { return i * decim_size; } - - #ifndef NDEBUG - this->d_debug << "G:" << grad_cur << std::endl; - #endif - - grad_prev = grad_cur; } return -1; + + /* OLD ****************************************************************************/ +// const uint32_t decimation = this->d_corr_decim_factor; +// const uint32_t decim_size = this->d_samples_per_symbol / decimation; + +// if (std::abs(samples[ this->d_samples_per_symbol / 2]) > 0.01f) { + +// const float mul = (float)this->d_samples_per_second / (2.0f * M_PI); +// uint32_t rising = 0; +// static const uint32_t rising_required = 2; + +// float theta1, theta2, theta3, theta4, +// grad_prev = 0.0f, grad_cur; + +// for (uint32_t i = 1; i < decimation-1; i++) { +// theta1 = std::arg(samples[ (i - 1) * decim_size ]); +// theta2 = theta3 = std::arg(samples[ i * decim_size ]); +// theta4 = std::arg(samples[ (i + 1) * decim_size ]); + +// // Unwrap phase +// while ( (theta2 - theta1) > M_PI ) theta2 -= 2*M_PI; +// while ( (theta2 - theta1) < -M_PI ) theta2 += 2*M_PI; +// while ( (theta4 - theta3) > M_PI ) theta4 -= 2*M_PI; +// while ( (theta4 - theta3) < -M_PI ) theta4 += 2*M_PI; + +// /* - grad_prev --> happens in old code, but is less reliable? */ +// grad_cur = (theta4 - theta3 - theta2 + theta1) * mul /* - grad_prev */; + +// if (grad_cur > grad_prev) +// rising++; + +// if (rising >= rising_required && grad_cur <= -20000) { +// // TODO: Make this a bit more logical, e.g. d_bw / decimation * 2 -> 2 steps down +// return i * decim_size; +// } + +// #ifndef NDEBUG +// this->d_debug << "G:" << grad_cur << std::endl; +// #endif + +// grad_prev = grad_cur; +// } + +// } +// return -1; + /**********************************************************************************/ + } uint8_t decoder_impl::lookup_cr(uint8_t bytevalue) { @@ -751,10 +879,16 @@ namespace gr { case gr::lora::DecoderState::DETECT: { int i = this->find_preamble_start_fast(&input[0], 2 * this->d_samples_per_symbol); + if (i != -1) { - uint32_t c_window = std::min(2 * this->d_samples_per_symbol - i, - this->d_samples_per_symbol); + // BUG: (2*d_samples_per_symbol - i) always bigger than d_samples_per_symbol + // Thus c_window is always d_samples_per_symbol? +// uint32_t c_window = std::min(2 * this->d_samples_per_symbol - i, +// this->d_samples_per_symbol); + uint32_t c_window = this->d_samples_per_symbol; + int32_t index_correction = 0; + float c = this->detect_upchirp(&input[i], c_window, this->d_samples_per_symbol / this->d_corr_decim_factor, @@ -790,6 +924,8 @@ namespace gr { // Debug stuff this->samples_to_file("/tmp/sync", &input[0], this->d_samples_per_symbol, sizeof(gr_complex)); + printf("---------------------- SYNC!\n"); + this->d_state = gr::lora::DecoderState::PAUSE; } else { this->d_corr_fails++; @@ -808,7 +944,6 @@ namespace gr { case gr::lora::DecoderState::PAUSE: { this->d_state = gr::lora::DecoderState::DECODE_HEADER; - //samples_debug(input, d_samples_per_symbol + d_delay_after_sync); this->consume_each(this->d_samples_per_symbol + this->d_delay_after_sync); break; @@ -828,11 +963,11 @@ namespace gr { this->d_payload_length = decoded[0]; this->d_cr = this->lookup_cr(decoded[1]); - int symbols_per_block = this->d_cr + 4; - int bits_needed = this->d_payload_length * 8 + 16; - float symbols_needed = float(bits_needed) * (symbols_per_block / 4.0f) / float(this->d_sf); - int blocks_needed = ceil(symbols_needed / symbols_per_block); - this->d_payload_symbols = blocks_needed * symbols_per_block; + const int symbols_per_block = this->d_cr + 4; + const float bits_needed = float(this->d_payload_length) * 8.0f + 16.0f; + const float symbols_needed = bits_needed * (symbols_per_block / 4.0f) / float(this->d_sf); + const int blocks_needed = std::ceil(symbols_needed / symbols_per_block); + this->d_payload_symbols = blocks_needed * symbols_per_block; #ifndef NDEBUG this->d_debug << "LEN: " << this->d_payload_length << " (" << this->d_payload_symbols << " symbols)" << std::endl; @@ -868,6 +1003,7 @@ namespace gr { } case gr::lora::DecoderState::STOP: { + this->consume_each(this->d_samples_per_symbol); break; } diff --git a/lib/decoder_impl.h b/lib/decoder_impl.h index f9be2c8..7d5347d 100644 --- a/lib/decoder_impl.h +++ b/lib/decoder_impl.h @@ -49,9 +49,15 @@ namespace gr { /// using std::complex = gr_complex std::vector d_downchirp; - std::vector d_upchirp; std::vector d_downchirp_ifreq; + float d_downchirp_avg; + float d_downchirp_stddev; + + std::vector d_upchirp; std::vector d_upchirp_ifreq; + float d_upchirp_avg; + float d_upchirp_stddev; + std::vector d_fft; std::vector d_mult; @@ -94,13 +100,13 @@ namespace gr { void build_ideal_chirps(void); void samples_to_file(const std::string path, const gr_complex *v, uint32_t length, uint32_t elem_size); void samples_debug(const gr_complex *v, uint32_t length); - float sliding_norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window, uint32_t slide, int32_t *index); - float norm_cross_correlate(const float *samples_1, const float *samples_2, uint32_t window); + float sliding_norm_cross_correlate_upchirp(const float *samples, uint32_t window, uint32_t slide, int32_t *index); + float norm_cross_correlate_downchirp(const float *samples, uint32_t window); float detect_downchirp(const gr_complex *samples, uint32_t window); float detect_upchirp(const gr_complex *samples_1, uint32_t window, uint32_t slide, int32_t *index); float cross_correlate(const gr_complex *samples_1, const gr_complex *samples_2, int window); - unsigned int get_shift_fft(gr_complex *samples); + unsigned int get_shift_fft(const gr_complex *samples); void determine_cfo(const gr_complex *samples); void correct_cfo(gr_complex *samples, uint32_t num_samples); diff --git a/lib/message_socket_sink_impl.cc b/lib/message_socket_sink_impl.cc index 287944c..b413f87 100644 --- a/lib/message_socket_sink_impl.cc +++ b/lib/message_socket_sink_impl.cc @@ -682,6 +682,8 @@ #include #include "message_socket_sink_impl.h" +#define NDEBUG /// Debug printing + namespace gr { namespace lora { diff --git a/lib/tables.h b/lib/tables.h index 8f2a6ff..b6d0c64 100644 --- a/lib/tables.h +++ b/lib/tables.h @@ -8,27 +8,27 @@ namespace gr { }; const uint8_t prng_payload_sf7[] = { // OK - 0xdc, 0xec, 0xb0, 0xf4, 0x9c, 0xfc, 0xc4, 0xdc, 0x10, 0xf8, 0x40, 0x34, 0xa8, 0x5c, 0xf0, 0x94, 0x60, 0x8, 0xf8, 0x48, 0xbc, 0x88, 0xa4, 0xd4, 0x14, 0xe4, 0x84, 0x38, 0x68, 0xec, 0xe4, 0xbc, 0xb0, 0x1c, 0x14, 0xa4, 0x3c, 0x4c, 0x90, 0x60, 0x84, 0x70, 0x20, 0x44, 0x4, 0x24, 0x80, 0x98, 0x40, 0xa4, 0x58, 0x4, 0xa0, 0x80, 0x98, 0x40, 0xa4, 0x10, 0x4c, 0x40, 0x60, 0xa8, 0x38, 0xb8, 0xa4, 0x80, 0x14, 0xc8, 0x84, 0xa0, 0x68, 0x68, 0xac, 0xbc, 0x18, 0x1c, 0x8c, 0xa4, 0xb8, 0x4c, 0xd8, 0x28, 0x64, 0xd8, 0x58, 0xdc, 0xb0, 0xa0, 0x9c, 0xd0, 0xc4, 0x44, 0x10, 0x7c, 0x8, 0xb4, 0x0, 0x5c, 0x68, 0x94, 0xe4, 0x8, 0xb0, 0x0, 0x5c, 0x20, 0xdc, 0x4c, 0xa0, 0x60, 0x98, 0x70, 0xec, 0xc, 0xac, 0xc4, 0x18, 0xa8, 0x8c, 0xb8, 0xf0, 0xc8, 0x38, 0x28, 0x54, 0xd8, 0x44, 0xdc, 0x7c, 0xe8, 0x34, 0x30, 0x5c, 0x74, 0xdc, 0x60, 0xa0, 0xf8, 0x98, 0xf4, 0xa4, 0x1c, 0x4, 0xc4, 0x80, 0xa8, 0x8, 0xb8, 0xb8, 0x80, 0xd8, 0x80, 0x2c, 0x40, 0xf0, 0x58, 0x60, 0xa0, 0xb0, 0xd0, 0x14, 0xc, 0x74, 0xd4, 0x38, 0xe4, 0x54, 0x70, 0xc, 0x44, 0xd4, 0x6c, 0xe4, 0x30, 0x70, 0x74, 0xc, 0x28, 0xc4, 0x50, 0xa8, 0x24, 0xf0, 0x20, 0x60, 0x14, 0xb0, 0xcc, 0x5c, 0x88, 0x94, 0xd4, 0x8, 0xe4, 0x48, 0x70, 0xc0, 0xc, 0x7c, 0x8c, 0x7c, 0x0, 0xbc, 0x68, 0xa4, 0xe4, 0x5c, 0xf8, 0x64, 0xbc, 0x10, 0xec, 0x50, 0xbc, 0xe4, 0x54, 0x38, 0x44, 0xec, 0x34, 0xbc, 0xd4, 0x54, 0x24, 0xc, 0x68, 0xd4, 0xf4, 0xe4, 0xb4, 0x38, 0x74, 0xa4, 0x28, 0x5c, 0x50, 0x2c, 0x24, 0xb8, 0x68, 0x80, 0xbc, 0xc8, 0x54, 0xe8, 0xc, 0x88, 0x9c, 0x8c, 0x4, 0x0, 0x8, 0x68, 0xb8, 0xe4, 0x90, 0xb0, 0x84, 0x14, 0x20, 0x74, 0x4c, 0x38, 0x60, 0x1c, 0x70, 0xa4, 0x44, 0x4c, 0x6c, 0x60, 0x30, 0x38, 0x3c, 0xec, 0x80, 0xbc, 0xc8, 0x1c, 0xa0, 0xec, 0x68, 0xe4, 0xf4, 0xf8, 0xb4, 0xf4, 0x3c, 0xc, 0xc8, 0xc4, 0x60, 0xe0, 0x38, 0x10, 0xa4, 0x18, 0x14, 0x4, 0xcc, 0x8, 0xc0, 0xb8, 0x34, 0xd8, 0x9c, 0x64, 0xc4, 0x10, 0x58, 0x50, 0xa0, 0xac, 0xd0, 0xd8, 0x44, 0xdc, 0x34, 0xa0, 0xd4, 0x98, 0x6c, 0xa4, 0x88, 0x4c, 0xc4, 0x28, 0xa8, 0x90, 0xb8, 0x3c, 0x80, 0x90, 0xc8, 0xcc, 0xe8, 0x88, 0xc0, 0xd4, 0x24, 0xac, 0x98, 0x90 + 0xdc, 0xec, 0xb0, 0xf4, 0x9c, 0xfc, 0xc4, 0xdc, 0x10, 0xf8, 0x40, 0x34, 0xa8, 0x5c, 0xf0, 0x94, 0x60, 0x08, 0xf8, 0x48, 0xbc, 0x88, 0xa4, 0xd4, 0x14, 0xe4, 0x84, 0x38, 0x68, 0xec, 0xe4, 0xbc, 0xb0, 0x1c, 0x14, 0xa4, 0x3c, 0x4c, 0x90, 0x60, 0x84, 0x70, 0x20, 0x44, 0x04, 0x24, 0x80, 0x98, 0x40, 0xa4, 0x58, 0x04, 0xa0, 0x80, 0x98, 0x40, 0xa4, 0x10, 0x4c, 0x40, 0x60, 0xa8, 0x38, 0xb8, 0xa4, 0x80, 0x14, 0xc8, 0x84, 0xa0, 0x68, 0x68, 0xac, 0xbc, 0x18, 0x1c, 0x8c, 0xa4, 0xb8, 0x4c, 0xd8, 0x28, 0x64, 0xd8, 0x58, 0xdc, 0xb0, 0xa0, 0x9c, 0xd0, 0xc4, 0x44, 0x10, 0x7c, 0x08, 0xb4, 0x00, 0x5c, 0x68, 0x94, 0xe4, 0x08, 0xb0, 0x00, 0x5c, 0x20, 0xdc, 0x4c, 0xa0, 0x60, 0x98, 0x70, 0xec, 0x0c, 0xac, 0xc4, 0x18, 0xa8, 0x8c, 0xb8, 0xf0, 0xc8, 0x38, 0x28, 0x54, 0xd8, 0x44, 0xdc, 0x7c, 0xe8, 0x34, 0x30, 0x5c, 0x74, 0xdc, 0x60, 0xa0, 0xf8, 0x98, 0xf4, 0xa4, 0x1c, 0x04, 0xc4, 0x80, 0xa8, 0x08, 0xb8, 0xb8, 0x80, 0xd8, 0x80, 0x2c, 0x40, 0xf0, 0x58, 0x60, 0xa0, 0xb0, 0xd0, 0x14, 0x0c, 0x74, 0xd4, 0x38, 0xe4, 0x54, 0x70, 0x0c, 0x44, 0xd4, 0x6c, 0xe4, 0x30, 0x70, 0x74, 0x0c, 0x28, 0xc4, 0x50, 0xa8, 0x24, 0xf0, 0x20, 0x60, 0x14, 0xb0, 0xcc, 0x5c, 0x88, 0x94, 0xd4, 0x08, 0xe4, 0x48, 0x70, 0xc0, 0x0c, 0x7c, 0x8c, 0x7c, 0x00, 0xbc, 0x68, 0xa4, 0xe4, 0x5c, 0xf8, 0x64, 0xbc, 0x10, 0xec, 0x50, 0xbc, 0xe4, 0x54, 0x38, 0x44, 0xec, 0x34, 0xbc, 0xd4, 0x54, 0x24, 0x0c, 0x68, 0xd4, 0xf4, 0xe4, 0xb4, 0x38, 0x74, 0xa4, 0x28, 0x5c, 0x50, 0x2c, 0x24, 0xb8, 0x68, 0x80, 0xbc, 0xc8, 0x54, 0xe8, 0x0c, 0x88, 0x9c, 0x8c, 0x04, 0x00, 0x08, 0x68, 0xb8, 0xe4, 0x90, 0xb0, 0x84, 0x14, 0x20, 0x74, 0x4c, 0x38, 0x60, 0x1c, 0x70, 0xa4, 0x44, 0x4c, 0x6c, 0x60, 0x30, 0x38, 0x3c, 0xec, 0x80, 0xbc, 0xc8, 0x1c, 0xa0, 0xec, 0x68, 0xe4, 0xf4, 0xf8, 0xb4, 0xf4, 0x3c, 0x0c, 0xc8, 0xc4, 0x60, 0xe0, 0x38, 0x10, 0xa4, 0x18, 0x14, 0x04, 0xcc, 0x08, 0xc0, 0xb8, 0x34, 0xd8, 0x9c, 0x64, 0xc4, 0x10, 0x58, 0x50, 0xa0, 0xac, 0xd0, 0xd8, 0x44, 0xdc, 0x34, 0xa0, 0xd4, 0x98, 0x6c, 0xa4, 0x88, 0x4c, 0xc4, 0x28, 0xa8, 0x90, 0xb8, 0x3c, 0x80, 0x90, 0xc8, 0xcc, 0xe8, 0x88, 0xc0, 0xd4, 0x24, 0xac, 0x98, 0x90 }; const uint8_t prng_payload_sf8[] = { - 0xbd, 0xdf, 0xa4, 0xfb, 0x16, 0x7f, 0x85, 0xfe, 0x40, 0xdf, 0x5b, 0xb0, 0xa2, 0x9e, 0xd0, 0x86, 0x26, 0x20, 0x68, 0x4f, 0xf7, 0x2a, 0xb6, 0xd3, 0x5e, 0x46, 0x97, 0x7c, 0x43, 0x7f, 0xe3, 0xb5, 0x73, 0x3e, 0x45, 0x83, 0x25, 0xcb, 0x9b, 0xe0, 0xc7, 0x13, 0x10, 0x51, 0x8, 0xad, 0x2, 0x98, 0x40, 0xa7, 0x5b, 0x4, 0xa2, 0x80, 0x9b, 0x1, 0xc7, 0x20, 0x5b, 0x4f, 0xe9, 0x2a, 0x7a, 0x98, 0xf4, 0xa7, 0xe, 0x4f, 0x8f, 0x61, 0x49, 0x79, 0xea, 0x94, 0x89, 0x1a, 0xc4, 0x7, 0xa8, 0x4a, 0x92, 0x8a, 0x76, 0x9d, 0x70, 0x4c, 0xb6, 0xab, 0x5e, 0xf2, 0x97, 0x62, 0x8, 0xf8, 0x2, 0xb5, 0x40, 0x3e, 0x5b, 0x83, 0xe9, 0x80, 0x31, 0x1, 0x5e, 0x20, 0xdc, 0x4f, 0xa2, 0x61, 0x9b, 0x32, 0x8c, 0x3e, 0x9a, 0xd8, 0x95, 0x22, 0x4e, 0x9a, 0xa0, 0xac, 0x23, 0x8e, 0x5d, 0x5, 0x64, 0xcf, 0xb9, 0xc1, 0xc4, 0x37, 0x2, 0xdd, 0xce, 0xe7, 0xe9, 0x58, 0xc9, 0xb1, 0xbf, 0x98, 0xa, 0xcd, 0xc0, 0x8b, 0x7b, 0xdd, 0xb2, 0xf, 0x54, 0x3, 0x6d, 0x60, 0xe2, 0x4f, 0x6e, 0x2e, 0xb9, 0xc3, 0x16, 0x5, 0x76, 0xb6, 0x2f, 0xe6, 0xd7, 0x30, 0x6c, 0x37, 0xc3, 0x62, 0x4a, 0xbb, 0xa1, 0x54, 0x5e, 0x4d, 0xfd, 0xc6, 0xa2, 0xee, 0xd4, 0xb2, 0x24, 0x3e, 0x23, 0xe9, 0x56, 0x3e, 0x8d, 0x53, 0x42, 0x6, 0x7b, 0x37, 0xf9, 0x9e, 0xf6, 0x86, 0xbc, 0x20, 0xcf, 0xe, 0xbc, 0x7d, 0xd7, 0x7b, 0x26, 0xdf, 0x61, 0xcb, 0x5d, 0x38, 0xe4, 0x54, 0x39, 0xe, 0xef, 0x87, 0xb8, 0xd5, 0x57, 0x67, 0x6e, 0xd8, 0x82, 0xeb, 0x4b, 0x3c, 0x7a, 0x56, 0xf4, 0xd, 0x45, 0x96, 0x31, 0xc6, 0x1b, 0x73, 0xc6, 0x95, 0x7b, 0x11, 0xb2, 0xa5, 0x1f, 0x9a, 0xc7, 0xe6, 0x30, 0x4f, 0x47, 0x2a, 0xeb, 0x1a, 0x63, 0xa7, 0x65, 0x54, 0x6e, 0xcf, 0x39, 0xe2, 0xdf, 0x5b, 0xb6, 0x51, 0x57, 0xe6, 0xe3, 0xb0, 0x38, 0x3e, 0xcf, 0xc2, 0xbc, 0xd7, 0x9c, 0xe2, 0x8c, 0x58, 0xb1, 0xca, 0x74, 0x3c, 0xb6, 0x9d, 0x5e, 0xae, 0xfc, 0xe5, 0xe9, 0xf8, 0xa9, 0xb5, 0x5b, 0x3e, 0xb7, 0xd9, 0x7, 0x61, 0x28, 0x3a, 0x90, 0x7e, 0x76, 0xb3, 0x3f, 0xcb, 0x5f, 0xab, 0xee, 0xf3, 0xeb, 0x72, 0xc0, 0xb3, 0x28, 0x5c, 0xd9, 0x4d, 0xb6, 0x9d, 0x57, 0x4c, 0xa0, 0x29, 0x92, 0xb9, 0x1d, 0x83, 0x95, 0xd3, 0x8e, 0x2b, 0xe9, 0xf3, 0xa2, 0x29, 0x25, 0x15, 0x40, 0xcf, 0x6d, 0xca, 0x89, 0xd6, 0xd4, 0xa1, 0xc3, 0x51, 0x39, 0x4d, 0x85, 0x8d, 0x49, 0x44, 0xe8, 0xe2, 0xbb, 0x1a, 0x84, 0x0, 0x49, 0x98, 0xec, 0x65, 0x72, 0x10, 0x6e, 0x80, 0x40, 0xdd, 0x76, 0x65, 0x3b, 0x51, 0x8e, 0x2, 0xb8, 0x70, 0xd7, 0xe2, 0xa7, 0x9a, 0x48, 0xab, 0xc2, 0x38, 0x7d, 0x5e, 0xbe, 0x6, 0x86, 0x4c, 0x9, 0x72, 0xaf, 0xf4, 0x58, 0x9e, 0x3c, 0x80, 0xed, 0xdd, 0xa5, 0x2e, 0x55, 0xf8, 0xbc, 0xd8, 0xed, 0x4d, 0xb9, 0xa0, 0x16, 0xfe, 0x5f, 0xf9, 0xde, 0x79, 0xa7, 0x34, 0xd8, 0x37, 0xf6, 0xb9, 0x77, 0x5a, 0x6b, 0x2e, 0x76, 0xf8, 0x36, 0xb5, 0x8b, 0xc3, 0xc2, 0xe2, 0xc1, 0x53, 0x38, 0xa, 0xfd, 0x2b, 0xf2, 0x83, 0xf5, 0x64, 0x25, 0x5e, 0x33, 0x49, 0x50, 0xfb, 0x64, 0xd5, 0xa2, 0x41, 0x21, 0x85, 0x5c, 0x41, 0x25, 0x4d, 0x9, 0xe6, 0xe3, 0xa5, 0x79, 0xd9, 0x77, 0x6, 0x6e, 0x4c, 0xc0, 0x77, 0x35, 0xfc, 0x11, 0xd5, 0x5d, 0xa, 0x97, 0x50, 0x5, 0xa9, 0xe9, 0xb3, 0x7b, 0x79, 0x96, 0x15, 0x13, 0x4, 0x8f, 0x62, 0x91, 0x5e, 0x74, 0x12, 0x75, 0x9e, 0x3e, 0xad, 0x4b, 0x97, 0xe3, 0xf0, 0x8a, 0x3, 0x41, 0x60, 0xd1, 0xd2, 0x4b, 0xbb, 0xda, 0x3f, 0x3d + 0xbd, 0xdf, 0xa4, 0xfb, 0x16, 0x7f, 0x85, 0xfe, 0x40, 0xdf, 0x5b, 0xb0, 0xa2, 0x9e, 0xd0, 0x86, 0x26, 0x20, 0x68, 0x4f, 0xf7, 0x2a, 0xb6, 0xd3, 0x5e, 0x46, 0x97, 0x7c, 0x43, 0x7f, 0xe3, 0xb5, 0x73, 0x3e, 0x45, 0x83, 0x25, 0xcb, 0x9b, 0xe0, 0xc7, 0x13, 0x10, 0x51, 0x08, 0xad, 0x02, 0x98, 0x40, 0xa7, 0x5b, 0x04, 0xa2, 0x80, 0x9b, 0x01, 0xc7, 0x20, 0x5b, 0x4f, 0xe9, 0x2a, 0x7a, 0x98, 0xf4, 0xa7, 0x0e, 0x4f, 0x8f, 0x61, 0x49, 0x79, 0xea, 0x94, 0x89, 0x1a, 0xc4, 0x07, 0xa8, 0x4a, 0x92, 0x8a, 0x76, 0x9d, 0x70, 0x4c, 0xb6, 0xab, 0x5e, 0xf2, 0x97, 0x62, 0x08, 0xf8, 0x02, 0xb5, 0x40, 0x3e, 0x5b, 0x83, 0xe9, 0x80, 0x31, 0x01, 0x5e, 0x20, 0xdc, 0x4f, 0xa2, 0x61, 0x9b, 0x32, 0x8c, 0x3e, 0x9a, 0xd8, 0x95, 0x22, 0x4e, 0x9a, 0xa0, 0xac, 0x23, 0x8e, 0x5d, 0x05, 0x64, 0xcf, 0xb9, 0xc1, 0xc4, 0x37, 0x02, 0xdd, 0xce, 0xe7, 0xe9, 0x58, 0xc9, 0xb1, 0xbf, 0x98, 0x0a, 0xcd, 0xc0, 0x8b, 0x7b, 0xdd, 0xb2, 0x0f, 0x54, 0x03, 0x6d, 0x60, 0xe2, 0x4f, 0x6e, 0x2e, 0xb9, 0xc3, 0x16, 0x50, 0x76, 0xb6, 0x2f, 0xe6, 0xd7, 0x30, 0x6c, 0x37, 0xc3, 0x62, 0x4a, 0xbb, 0xa1, 0x54, 0x5e, 0x4d, 0xfd, 0xc6, 0xa2, 0xee, 0xd4, 0xb2, 0x24, 0x3e, 0x23, 0xe9, 0x56, 0x3e, 0x8d, 0x53, 0x42, 0x06, 0x7b, 0x37, 0xf9, 0x9e, 0xf6, 0x86, 0xbc, 0x20, 0xcf, 0x0e, 0xbc, 0x7d, 0xd7, 0x7b, 0x26, 0xdf, 0x61, 0xcb, 0x5d, 0x38, 0xe4, 0x54, 0x39, 0x0e, 0xef, 0x87, 0xb8, 0xd5, 0x57, 0x67, 0x6e, 0xd8, 0x82, 0xeb, 0x4b, 0x3c, 0x7a, 0x56, 0xf4, 0x0d, 0x45, 0x96, 0x31, 0xc6, 0x1b, 0x73, 0xc6, 0x95, 0x7b, 0x11, 0xb2, 0xa5, 0x1f, 0x9a, 0xc7, 0xe6, 0x30, 0x4f, 0x47, 0x2a, 0xeb, 0x1a, 0x63, 0xa7, 0x65, 0x54, 0x6e, 0xcf, 0x39, 0xe2, 0xdf, 0x5b, 0xb6, 0x51, 0x57, 0xe6, 0xe3, 0xb0, 0x38, 0x3e, 0xcf, 0xc2, 0xbc, 0xd7, 0x9c, 0xe2, 0x8c, 0x58, 0xb1, 0xca, 0x74, 0x3c, 0xb6, 0x9d, 0x5e, 0xae, 0xfc, 0xe5, 0xe9, 0xf8, 0xa9, 0xb5, 0x5b, 0x3e, 0xb7, 0xd9, 0x07, 0x61, 0x28, 0x3a, 0x90, 0x7e, 0x76, 0xb3, 0x3f, 0xcb, 0x5f, 0xab, 0xee, 0xf3, 0xeb, 0x72, 0xc0, 0xb3, 0x28, 0x5c, 0xd9, 0x4d, 0xb6, 0x9d, 0x57, 0x4c, 0xa0, 0x29, 0x92, 0xb9, 0x1d, 0x83, 0x95, 0xd3, 0x8e, 0x2b, 0xe9, 0xf3, 0xa2, 0x29, 0x25, 0x15, 0x40, 0xcf, 0x6d, 0xca, 0x89, 0xd6, 0xd4, 0xa1, 0xc3, 0x51, 0x39, 0x4d, 0x85, 0x8d, 0x49, 0x44, 0xe8, 0xe2, 0xbb, 0x1a, 0x84, 0x00, 0x49, 0x98, 0xec, 0x65, 0x72, 0x10, 0x6e, 0x80, 0x40, 0xdd, 0x76, 0x65, 0x3b, 0x51, 0x8e, 0x02, 0xb8, 0x70, 0xd7, 0xe2, 0xa7, 0x9a, 0x48, 0xab, 0xc2, 0x38, 0x7d, 0x5e, 0xbe, 0x06, 0x86, 0x4c, 0x09, 0x72, 0xaf, 0xf4, 0x58, 0x9e, 0x3c, 0x80, 0xed, 0xdd, 0xa5, 0x2e, 0x55, 0xf8, 0xbc, 0xd8, 0xed, 0x4d, 0xb9, 0xa0, 0x16, 0xfe, 0x5f, 0xf9, 0xde, 0x79, 0xa7, 0x34, 0xd8, 0x37, 0xf6, 0xb9, 0x77, 0x5a, 0x6b, 0x2e, 0x76, 0xf8, 0x36, 0xb5, 0x8b, 0xc3, 0xc2, 0xe2, 0xc1, 0x53, 0x38, 0x0a, 0xfd, 0x2b, 0xf2, 0x83, 0xf5, 0x64, 0x25, 0x5e, 0x33, 0x49, 0x50, 0xfb, 0x64, 0xd5, 0xa2, 0x41, 0x21, 0x85, 0x5c, 0x41, 0x25, 0x4d, 0x09, 0xe6, 0xe3, 0xa5, 0x79, 0xd9, 0x77, 0x06, 0x6e, 0x4c, 0xc0, 0x77, 0x35, 0xfc, 0x11, 0xd5, 0x5d, 0x0a, 0x97, 0x50, 0x05, 0xa9, 0xe9, 0xb3, 0x7b, 0x79, 0x96, 0x15, 0x13, 0x04, 0x8f, 0x62, 0x91, 0x5e, 0x74, 0x12, 0x75, 0x9e, 0x3e, 0xad, 0x4b, 0x97, 0xe3, 0xf0, 0x8a, 0x03, 0x41, 0x60, 0xd1, 0xd2, 0x4b, 0xbb, 0xda, 0x3f, 0x3d }; const uint8_t prng_payload_sf9[] = { - 0xfd, 0xbe, 0x94, 0xef, 0x1a, 0xf7, 0x7, 0xfd, 0x1, 0xff, 0xb, 0x94, 0xba, 0x1a, 0xda, 0x7, 0x64, 0x1, 0x78, 0xb, 0xdf, 0xba, 0xb0, 0xda, 0x9e, 0x64, 0x86, 0x78, 0xb, 0xdf, 0xf1, 0xb0, 0x3b, 0x9e, 0x57, 0x86, 0x2d, 0xb, 0xb9, 0xf1, 0x83, 0x3b, 0x80, 0x57, 0x1, 0x2d, 0x40, 0xb9, 0x10, 0x83, 0x47, 0x80, 0xa8, 0x3, 0x99, 0x41, 0xa3, 0x12, 0x5f, 0x3, 0x69, 0x8, 0x79, 0x98, 0xf4, 0xa7, 0xe, 0x5f, 0xcf, 0x6d, 0xe9, 0x79, 0xab, 0xf6, 0xb9, 0x2e, 0xd8, 0xcf, 0x2e, 0x41, 0xd1, 0x2b, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x7, 0x27, 0x60, 0x48, 0x14, 0xb8, 0x88, 0x9c, 0x48, 0x86, 0xa1, 0x60, 0x3, 0x4, 0x16, 0x94, 0x4e, 0x42, 0xa9, 0xa1, 0xf9, 0x3, 0xc8, 0x16, 0x3e, 0x46, 0x98, 0xab, 0x8e, 0xf9, 0xf1, 0xe8, 0x3b, 0x32, 0x57, 0x9e, 0xe7, 0x8c, 0x18, 0xf1, 0x80, 0x3f, 0x9e, 0x5f, 0xcd, 0xe7, 0xe8, 0x58, 0xe9, 0xb1, 0x9f, 0x92, 0x82, 0xcf, 0x0, 0xea, 0x2b, 0x88, 0xbe, 0xaf, 0x56, 0x82, 0x2e, 0x8, 0x92, 0x6b, 0x17, 0xae, 0x3b, 0x4a, 0xd7, 0x2a, 0x66, 0x92, 0x13, 0x76, 0x21, 0x3b, 0xa5, 0xd3, 0xd3, 0x65, 0x26, 0x13, 0x2, 0x41, 0x52, 0xad, 0x46, 0xd3, 0xa8, 0x26, 0xb2, 0x23, 0x52, 0x12, 0xb3, 0xce, 0x97, 0xa9, 0xc6, 0x33, 0x30, 0x72, 0x27, 0xbf, 0x7b, 0x1d, 0x7b, 0xc7, 0x9d, 0x30, 0xeb, 0x27, 0x38, 0x73, 0xd6, 0x79, 0x2f, 0x9f, 0x3, 0xeb, 0x39, 0x2c, 0xe8, 0xd6, 0x7b, 0x27, 0x9d, 0x43, 0x80, 0x59, 0xc9, 0xec, 0xae, 0x79, 0x93, 0x9f, 0x16, 0x80, 0x74, 0xc9, 0x3e, 0xae, 0x56, 0x93, 0x4d, 0x57, 0xcd, 0x64, 0x2b, 0x3e, 0xc8, 0x56, 0xea, 0x6d, 0xa8, 0x8d, 0x9b, 0xf, 0x86, 0xc8, 0x2, 0xe8, 0x80, 0xe9, 0x27, 0xbb, 0xdd, 0x86, 0xe5, 0x4a, 0x79, 0x80, 0x2e, 0x7, 0x9b, 0xd9, 0x89, 0xed, 0xe2, 0x73, 0x18, 0x2e, 0xe9, 0xeb, 0x38, 0xd9, 0x95, 0xe0, 0x8d, 0x98, 0xd1, 0x8a, 0x74, 0x2c, 0x32, 0x1d, 0x17, 0x8e, 0x2d, 0x91, 0xf5, 0x44, 0xbf, 0x36, 0x1d, 0x15, 0xc7, 0x2d, 0x7b, 0xb5, 0x96, 0xbb, 0x50, 0x1d, 0x6b, 0xc5, 0x53, 0x3b, 0x41, 0xb6, 0x85, 0x54, 0x1a, 0x6d, 0x8d, 0x53, 0xdb, 0x41, 0x85, 0xa5, 0x29, 0x9a, 0xca, 0x8e, 0x8a, 0xfa, 0xd6, 0x91, 0xb8, 0xa5, 0x98, 0xc1, 0x8c, 0xca, 0xda, 0xe6, 0xaa, 0xa1, 0x27, 0x18, 0xc8, 0x8d, 0x5, 0xfb, 0x8d, 0xca, 0x40, 0xa7, 0x40, 0x51, 0x29, 0x4d, 0xc5, 0xbd, 0x7d, 0x1c, 0xe0, 0x60, 0xfb, 0x31, 0x94, 0x44, 0x71, 0x7d, 0xfe, 0xe8, 0xb0, 0x7a, 0x55, 0xd7, 0xbc, 0x21, 0xfd, 0xda, 0xf6, 0xb8, 0xfc, 0xdf, 0xd4, 0x9c, 0x21, 0xfc, 0xf2, 0x76, 0xf9, 0xfc, 0xbe, 0x17, 0xaf, 0x41, 0xe3, 0xca, 0xbe, 0x6f, 0x5f, 0xbf, 0xc, 0x87, 0x2d, 0xc3, 0x48, 0x36, 0x74, 0x57, 0x73, 0x4d, 0x43, 0xad, 0xd0, 0x18, 0xe3, 0xe0, 0xb0, 0x72, 0x35, 0x6f, 0x49, 0xf4, 0x52, 0x6b, 0xac, 0xb4, 0xd8, 0x35, 0xf6, 0x59, 0x77, 0x5e, 0x7b, 0xae, 0xbc, 0xda, 0x3e, 0xf7, 0x32, 0x53, 0x84, 0xeb, 0x23, 0x30, 0x18, 0x7e, 0xb1, 0x52, 0x64, 0xb4, 0xbe, 0x5, 0x56, 0xa, 0xc, 0x91, 0x76, 0x50, 0xb1, 0x3e, 0x59, 0x57, 0x6e, 0xd, 0xa3, 0xb6, 0x7e, 0x89, 0x76, 0x4b, 0x7d, 0x6e, 0xde, 0x82, 0x90, 0x5e, 0xca, 0x72, 0x4d, 0x71, 0xe9, 0xdc, 0x82, 0xd0, 0x15, 0x9a, 0x83, 0x4d, 0x9, 0xeb, 0x20, 0x82, 0x6f, 0x74, 0x1e, 0x93, 0x18, 0x8d, 0xb, 0x20, 0xb1, 0x2e, 0x60, 0x1e, 0xf1, 0x10, 0xfd, 0xf, 0x5e, 0xb7, 0x9b, 0x40, 0x94, 0xa, 0x89, 0x2, 0xa0, 0xb7, 0x66, 0x43, 0x77, 0xb6, 0xc7, 0x3e, 0x3f, 0xdf + 0xfd, 0xbe, 0x94, 0xef, 0x1a, 0xf7, 0x07, 0xfd, 0x01, 0xff, 0x0b, 0x94, 0xba, 0x1a, 0xda, 0x07, 0x64, 0x01, 0x78, 0x0b, 0xdf, 0xba, 0xb0, 0xda, 0x9e, 0x64, 0x86, 0x78, 0x0b, 0xdf, 0xf1, 0xb0, 0x3b, 0x9e, 0x57, 0x86, 0x2d, 0x0b, 0xb9, 0xf1, 0x83, 0x3b, 0x80, 0x57, 0x01, 0x2d, 0x40, 0xb9, 0x10, 0x83, 0x47, 0x80, 0xa8, 0x03, 0x99, 0x41, 0xa3, 0x12, 0x5f, 0x03, 0x69, 0x08, 0x79, 0x98, 0xf4, 0xa7, 0x0e, 0x5f, 0xcf, 0x6d, 0xe9, 0x79, 0xab, 0xf6, 0xb9, 0x2e, 0xd8, 0xcf, 0x2e, 0x41, 0xd1, 0x2b, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x07, 0x27, 0x60, 0x48, 0x14, 0xb8, 0x88, 0x9c, 0x48, 0x86, 0xa1, 0x60, 0x03, 0x04, 0x16, 0x94, 0x4e, 0x42, 0xa9, 0xa1, 0xf9, 0x03, 0xc8, 0x16, 0x3e, 0x46, 0x98, 0xab, 0x8e, 0xf9, 0xf1, 0xe8, 0x3b, 0x32, 0x57, 0x9e, 0xe7, 0x8c, 0x18, 0xf1, 0x80, 0x3f, 0x9e, 0x5f, 0xcd, 0xe7, 0xe8, 0x58, 0xe9, 0xb1, 0x9f, 0x92, 0x82, 0xcf, 0x00, 0xea, 0x2b, 0x88, 0xbe, 0xaf, 0x56, 0x82, 0x2e, 0x08, 0x92, 0x6b, 0x17, 0xae, 0x3b, 0x4a, 0xd7, 0x2a, 0x66, 0x92, 0x13, 0x76, 0x21, 0x3b, 0xa5, 0xd3, 0xd3, 0x65, 0x26, 0x13, 0x02, 0x41, 0x52, 0xad, 0x46, 0xd3, 0xa8, 0x26, 0xb2, 0x23, 0x52, 0x12, 0xb3, 0xce, 0x97, 0xa9, 0xc6, 0x33, 0x30, 0x72, 0x27, 0xbf, 0x7b, 0x1d, 0x7b, 0xc7, 0x9d, 0x30, 0xeb, 0x27, 0x38, 0x73, 0xd6, 0x79, 0x2f, 0x9f, 0x03, 0xeb, 0x39, 0x2c, 0xe8, 0xd6, 0x7b, 0x27, 0x9d, 0x43, 0x80, 0x59, 0xc9, 0xec, 0xae, 0x79, 0x93, 0x9f, 0x16, 0x80, 0x74, 0xc9, 0x3e, 0xae, 0x56, 0x93, 0x4d, 0x57, 0xcd, 0x64, 0x2b, 0x3e, 0xc8, 0x56, 0xea, 0x6d, 0xa8, 0x8d, 0x9b, 0x0f, 0x86, 0xc8, 0x02, 0xe8, 0x80, 0xe9, 0x27, 0xbb, 0xdd, 0x86, 0xe5, 0x4a, 0x79, 0x80, 0x2e, 0x07, 0x9b, 0xd9, 0x89, 0xed, 0xe2, 0x73, 0x18, 0x2e, 0xe9, 0xeb, 0x38, 0xd9, 0x95, 0xe0, 0x8d, 0x98, 0xd1, 0x8a, 0x74, 0x2c, 0x32, 0x1d, 0x17, 0x8e, 0x2d, 0x91, 0xf5, 0x44, 0xbf, 0x36, 0x1d, 0x15, 0xc7, 0x2d, 0x7b, 0xb5, 0x96, 0xbb, 0x50, 0x1d, 0x6b, 0xc5, 0x53, 0x3b, 0x41, 0xb6, 0x85, 0x54, 0x1a, 0x6d, 0x8d, 0x53, 0xdb, 0x41, 0x85, 0xa5, 0x29, 0x9a, 0xca, 0x8e, 0x8a, 0xfa, 0xd6, 0x91, 0xb8, 0xa5, 0x98, 0xc1, 0x8c, 0xca, 0xda, 0xe6, 0xaa, 0xa1, 0x27, 0x18, 0xc8, 0x8d, 0x05, 0xfb, 0x8d, 0xca, 0x40, 0xa7, 0x40, 0x51, 0x29, 0x4d, 0xc5, 0xbd, 0x7d, 0x1c, 0xe0, 0x60, 0xfb, 0x31, 0x94, 0x44, 0x71, 0x7d, 0xfe, 0xe8, 0xb0, 0x7a, 0x55, 0xd7, 0xbc, 0x21, 0xfd, 0xda, 0xf6, 0xb8, 0xfc, 0xdf, 0xd4, 0x9c, 0x21, 0xfc, 0xf2, 0x76, 0xf9, 0xfc, 0xbe, 0x17, 0xaf, 0x41, 0xe3, 0xca, 0xbe, 0x6f, 0x5f, 0xbf, 0x0c, 0x87, 0x2d, 0xc3, 0x48, 0x36, 0x74, 0x57, 0x73, 0x4d, 0x43, 0xad, 0xd0, 0x18, 0xe3, 0xe0, 0xb0, 0x72, 0x35, 0x6f, 0x49, 0xf4, 0x52, 0x6b, 0xac, 0xb4, 0xd8, 0x35, 0xf6, 0x59, 0x77, 0x5e, 0x7b, 0xae, 0xbc, 0xda, 0x3e, 0xf7, 0x32, 0x53, 0x84, 0xeb, 0x23, 0x30, 0x18, 0x7e, 0xb1, 0x52, 0x64, 0xb4, 0xbe, 0x05, 0x56, 0x0a, 0x0c, 0x91, 0x76, 0x50, 0xb1, 0x3e, 0x59, 0x57, 0x6e, 0x0d, 0xa3, 0xb6, 0x7e, 0x89, 0x76, 0x4b, 0x7d, 0x6e, 0xde, 0x82, 0x90, 0x5e, 0xca, 0x72, 0x4d, 0x71, 0xe9, 0xdc, 0x82, 0xd0, 0x15, 0x9a, 0x83, 0x4d, 0x09, 0xeb, 0x20, 0x82, 0x6f, 0x74, 0x1e, 0x93, 0x18, 0x8d, 0x0b, 0x20, 0xb1, 0x2e, 0x60, 0x1e, 0xf1, 0x10, 0xfd, 0x0f, 0x5e, 0xb7, 0x9b, 0x40, 0x94, 0x0a, 0x89, 0x02, 0xa0, 0xb7, 0x66, 0x43, 0x77, 0xb6, 0xc7, 0x3e, 0x3f, 0xdf }; const uint8_t prng_payload_sf10[] = { - 0xfd, 0xfe, 0xf4, 0xdf, 0xe, 0xfb, 0x8f, 0x7f, 0x2, 0xfe, 0x4b, 0xb4, 0xea, 0x3e, 0xc2, 0x83, 0x6a, 0x88, 0xfa, 0x48, 0xfe, 0xaa, 0xf4, 0xf2, 0x4e, 0x62, 0xab, 0xf8, 0xd1, 0xfc, 0xe0, 0xb4, 0x73, 0x7e, 0x65, 0x83, 0x21, 0xcb, 0x93, 0x72, 0x87, 0x32, 0x40, 0x75, 0x50, 0x29, 0x2c, 0x19, 0x9a, 0x84, 0x4a, 0x0, 0xea, 0x30, 0xa9, 0x4, 0x8b, 0x88, 0x49, 0xa, 0xe2, 0x2a, 0x38, 0xb9, 0xa4, 0xa3, 0x16, 0xdf, 0xcd, 0x60, 0x4b, 0x7b, 0xea, 0x94, 0x89, 0x1a, 0xd0, 0x47, 0x28, 0x60, 0xd3, 0xaa, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x6, 0x65, 0x40, 0x18, 0x30, 0xa0, 0x3c, 0x92, 0xc9, 0x4c, 0xe2, 0x1, 0x73, 0x64, 0x2e, 0x34, 0xd0, 0x83, 0x20, 0xe2, 0x18, 0x32, 0x8e, 0x7c, 0x9a, 0xf8, 0xd5, 0x32, 0x46, 0x1e, 0xe0, 0xcd, 0x73, 0xca, 0x25, 0x8d, 0x7a, 0x64, 0xfe, 0x6a, 0xb5, 0x33, 0x5d, 0x35, 0xbd, 0x72, 0x96, 0xf0, 0x1b, 0xbf, 0x2, 0x1c, 0x40, 0xad, 0x30, 0x9e, 0x47, 0x55, 0x30, 0x4, 0xd3, 0x2, 0x6d, 0x62, 0xe2, 0x3f, 0x6a, 0x26, 0xb1, 0x41, 0x54, 0x2c, 0x2e, 0xb2, 0x3, 0x52, 0x1, 0xaf, 0xab, 0xd4, 0xd0, 0xe7, 0x26, 0x13, 0x62, 0x41, 0x6, 0xa5, 0x62, 0x53, 0xbb, 0xed, 0x92, 0x13, 0x17, 0x3a, 0x1b, 0x50, 0x94, 0x29, 0xd, 0xd2, 0x42, 0x6, 0x3b, 0x17, 0xc9, 0xda, 0xea, 0xe, 0x7e, 0x3, 0xbe, 0x2b, 0xe4, 0xa5, 0x69, 0xf4, 0xe8, 0x76, 0xb3, 0xfd, 0x14, 0x94, 0x36, 0x41, 0x64, 0xca, 0xf1, 0x28, 0xb6, 0xd6, 0x15, 0x46, 0x1f, 0x5c, 0x9a, 0x63, 0xcc, 0x3f, 0xfa, 0x54, 0xf4, 0xd, 0x5, 0xf6, 0x21, 0xe2, 0x93, 0xe9, 0x5, 0xb3, 0xa, 0x55, 0xfa, 0x29, 0x81, 0x1d, 0x9d, 0xa, 0x82, 0x4a, 0x48, 0x8b, 0x31, 0xfd, 0x2b, 0x23, 0x5f, 0x9d, 0x64, 0x48, 0x73, 0xc9, 0x4e, 0x57, 0xbf, 0xd1, 0x51, 0xe7, 0x67, 0x30, 0x39, 0x3e, 0xaf, 0xe3, 0xac, 0xef, 0x10, 0x70, 0x4e, 0x73, 0xa0, 0xde, 0x28, 0x90, 0xac, 0xba, 0x0, 0x4d, 0x86, 0x62, 0xa1, 0x58, 0x63, 0xd1, 0x26, 0x8a, 0x89, 0x45, 0xc9, 0xe2, 0xea, 0x13, 0x82, 0x7a, 0x5e, 0x3, 0x3d, 0xda, 0xdf, 0xa9, 0x6c, 0xf3, 0xc9, 0x12, 0xf0, 0x8f, 0xa0, 0x56, 0x1f, 0x27, 0xc7, 0xf8, 0x3b, 0xe8, 0xd6, 0x3e, 0xd4, 0x82, 0x2f, 0x85, 0x59, 0x29, 0x9d, 0xce, 0x96, 0x4e, 0x4c, 0xa4, 0xf, 0x9b, 0x12, 0xec, 0x1d, 0xce, 0xa1, 0x4e, 0x42, 0xaa, 0xeb, 0x50, 0x29, 0x8d, 0xc5, 0xfd, 0x5d, 0x4, 0xec, 0x46, 0x7a, 0x63, 0xf5, 0x94, 0x5, 0x21, 0x5e, 0x8e, 0xb9, 0xe1, 0x9d, 0xb3, 0x8f, 0x35, 0xb1, 0x32, 0x64, 0x97, 0xe1, 0x17, 0x35, 0xcf, 0x1c, 0x82, 0x16, 0x1c, 0x54, 0x7b, 0xed, 0xb3, 0xfe, 0xdd, 0xbf, 0x6, 0xc4, 0xc, 0x29, 0x46, 0xa7, 0x70, 0x8, 0xf5, 0xc, 0xd5, 0xd1, 0x61, 0x4f, 0x93, 0x80, 0x12, 0x4f, 0xc3, 0x20, 0x80, 0x43, 0x67, 0x49, 0xc2, 0xab, 0x6f, 0x5d, 0xf3, 0xef, 0x51, 0xe8, 0x81, 0xfb, 0xb5, 0xc9, 0x51, 0x72, 0x2e, 0x7e, 0xf8, 0x2e, 0xf7, 0xab, 0xd7, 0x86, 0x6a, 0xa3, 0xb1, 0x9, 0x7e, 0x91, 0x52, 0x4, 0x98, 0x2a, 0x8b, 0xd4, 0x48, 0x64, 0x0, 0xe2, 0x4c, 0x41, 0x28, 0x7c, 0xda, 0xac, 0x26, 0x93, 0xb3, 0x34, 0x49, 0x14, 0x52, 0x69, 0xa, 0x76, 0xd0, 0x75, 0xe, 0xc, 0x2c, 0xc4, 0x2b, 0x4, 0xf0, 0x42, 0x36, 0x6c, 0x3c, 0x89, 0x89, 0xab, 0x3a, 0x8e, 0xdd, 0xca, 0xa7, 0xeb, 0xbe, 0xa9, 0xd3, 0xe4, 0x94, 0xe7, 0xe0, 0xf9, 0xb8, 0x3e, 0xf9, 0xe7, 0xac, 0xd3, 0x9, 0x79, 0x61, 0x80, 0x82, 0x41, 0x31, 0x48, 0xa0, 0x50, 0x96, 0x2, 0x26, 0x64, 0x85, 0x16 + 0xfd, 0xfe, 0xf4, 0xdf, 0x0e, 0xfb, 0x8f, 0x7f, 0x02, 0xfe, 0x4b, 0xb4, 0xea, 0x3e, 0xc2, 0x83, 0x6a, 0x88, 0xfa, 0x48, 0xfe, 0xaa, 0xf4, 0xf2, 0x4e, 0x62, 0xab, 0xf8, 0xd1, 0xfc, 0xe0, 0xb4, 0x73, 0x7e, 0x65, 0x83, 0x21, 0xcb, 0x93, 0x72, 0x87, 0x32, 0x40, 0x75, 0x50, 0x29, 0x2c, 0x19, 0x9a, 0x84, 0x4a, 0x00, 0xea, 0x30, 0xa9, 0x04, 0x8b, 0x88, 0x49, 0x0a, 0xe2, 0x2a, 0x38, 0xb9, 0xa4, 0xa3, 0x16, 0xdf, 0xcd, 0x60, 0x4b, 0x7b, 0xea, 0x94, 0x89, 0x1a, 0xd0, 0x47, 0x28, 0x60, 0xd3, 0xaa, 0x26, 0xb9, 0x68, 0xb8, 0xb8, 0x22, 0x1c, 0xd1, 0x06, 0x65, 0x40, 0x18, 0x30, 0xa0, 0x3c, 0x92, 0xc9, 0x4c, 0xe2, 0x01, 0x73, 0x64, 0x2e, 0x34, 0xd0, 0x83, 0x20, 0xe2, 0x18, 0x32, 0x8e, 0x7c, 0x9a, 0xf8, 0xd5, 0x32, 0x46, 0x1e, 0xe0, 0xcd, 0x73, 0xca, 0x25, 0x8d, 0x7a, 0x64, 0xfe, 0x6a, 0xb5, 0x33, 0x5d, 0x35, 0xbd, 0x72, 0x96, 0xf0, 0x1b, 0xbf, 0x02, 0x1c, 0x40, 0xad, 0x30, 0x9e, 0x47, 0x55, 0x30, 0x04, 0xd3, 0x02, 0x6d, 0x62, 0xe2, 0x3f, 0x6a, 0x26, 0xb1, 0x41, 0x54, 0x2c, 0x2e, 0xb2, 0x03, 0x52, 0x01, 0xaf, 0xab, 0xd4, 0xd0, 0xe7, 0x26, 0x13, 0x62, 0x41, 0x06, 0xa5, 0x62, 0x53, 0xbb, 0xed, 0x92, 0x13, 0x17, 0x3a, 0x1b, 0x50, 0x94, 0x29, 0x0d, 0xd2, 0x42, 0x06, 0x3b, 0x17, 0xc9, 0xda, 0xea, 0x0e, 0x7e, 0x03, 0xbe, 0x2b, 0xe4, 0xa5, 0x69, 0xf4, 0xe8, 0x76, 0xb3, 0xfd, 0x14, 0x94, 0x36, 0x41, 0x64, 0xca, 0xf1, 0x28, 0xb6, 0xd6, 0x15, 0x46, 0x1f, 0x5c, 0x9a, 0x63, 0xcc, 0x3f, 0xfa, 0x54, 0xf4, 0x0d, 0x05, 0xf6, 0x21, 0xe2, 0x93, 0xe9, 0x05, 0xb3, 0x0a, 0x55, 0xfa, 0x29, 0x81, 0x1d, 0x9d, 0x0a, 0x82, 0x4a, 0x48, 0x8b, 0x31, 0xfd, 0x2b, 0x23, 0x5f, 0x9d, 0x64, 0x48, 0x73, 0xc9, 0x4e, 0x57, 0xbf, 0xd1, 0x51, 0xe7, 0x67, 0x30, 0x39, 0x3e, 0xaf, 0xe3, 0xac, 0xef, 0x10, 0x70, 0x4e, 0x73, 0xa0, 0xde, 0x28, 0x90, 0xac, 0xba, 0x00, 0x4d, 0x86, 0x62, 0xa1, 0x58, 0x63, 0xd1, 0x26, 0x8a, 0x89, 0x45, 0xc9, 0xe2, 0xea, 0x13, 0x82, 0x7a, 0x5e, 0x03, 0x3d, 0xda, 0xdf, 0xa9, 0x6c, 0xf3, 0xc9, 0x12, 0xf0, 0x8f, 0xa0, 0x56, 0x1f, 0x27, 0xc7, 0xf8, 0x3b, 0xe8, 0xd6, 0x3e, 0xd4, 0x82, 0x2f, 0x85, 0x59, 0x29, 0x9d, 0xce, 0x96, 0x4e, 0x4c, 0xa4, 0x0f, 0x9b, 0x12, 0xec, 0x1d, 0xce, 0xa1, 0x4e, 0x42, 0xaa, 0xeb, 0x50, 0x29, 0x8d, 0xc5, 0xfd, 0x5d, 0x04, 0xec, 0x46, 0x7a, 0x63, 0xf5, 0x94, 0x05, 0x21, 0x5e, 0x8e, 0xb9, 0xe1, 0x9d, 0xb3, 0x8f, 0x35, 0xb1, 0x32, 0x64, 0x97, 0xe1, 0x17, 0x35, 0xcf, 0x1c, 0x82, 0x16, 0x1c, 0x54, 0x7b, 0xed, 0xb3, 0xfe, 0xdd, 0xbf, 0x06, 0xc4, 0x0c, 0x29, 0x46, 0xa7, 0x70, 0x08, 0xf5, 0x0c, 0xd5, 0xd1, 0x61, 0x4f, 0x93, 0x80, 0x12, 0x4f, 0xc3, 0x20, 0x80, 0x43, 0x67, 0x49, 0xc2, 0xab, 0x6f, 0x5d, 0xf3, 0xef, 0x51, 0xe8, 0x81, 0xfb, 0xb5, 0xc9, 0x51, 0x72, 0x2e, 0x7e, 0xf8, 0x2e, 0xf7, 0xab, 0xd7, 0x86, 0x6a, 0xa3, 0xb1, 0x09, 0x7e, 0x91, 0x52, 0x04, 0x98, 0x2a, 0x8b, 0xd4, 0x48, 0x64, 0x00, 0xe2, 0x4c, 0x41, 0x28, 0x7c, 0xda, 0xac, 0x26, 0x93, 0xb3, 0x34, 0x49, 0x14, 0x52, 0x69, 0x0a, 0x76, 0xd0, 0x75, 0x0e, 0x0c, 0x2c, 0xc4, 0x2b, 0x04, 0xf0, 0x42, 0x36, 0x6c, 0x3c, 0x89, 0x89, 0xab, 0x3a, 0x8e, 0xdd, 0xca, 0xa7, 0xeb, 0xbe, 0xa9, 0xd3, 0xe4, 0x94, 0xe7, 0xe0, 0xf9, 0xb8, 0x3e, 0xf9, 0xe7, 0xac, 0xd3, 0x09, 0x79, 0x61, 0x80, 0x82, 0x41, 0x31, 0x48, 0xa0, 0x50, 0x96, 0x02, 0x26, 0x64, 0x85, 0x16 }; const uint8_t prng_payload_sf11[] = { - 0xfd, 0xfe, 0xb4, 0xbf, 0x3e, 0x8f, 0xa3, 0xd3, 0xd0, 0x75, 0x4, 0xfe, 0xc1, 0xb5, 0xea, 0x3e, 0xc2, 0xc3, 0x4a, 0x80, 0x6e, 0x2c, 0x7a, 0x59, 0xfe, 0x6a, 0x94, 0x82, 0x2a, 0x7a, 0x47, 0x62, 0x84, 0xf8, 0x42, 0xfd, 0xa0, 0x94, 0x43, 0x4a, 0x39, 0x27, 0xd3, 0x6, 0x2d, 0x43, 0x9a, 0x21, 0xe7, 0x61, 0x54, 0x3d, 0xbc, 0xd3, 0x3, 0x2d, 0x9, 0x98, 0xc0, 0xe7, 0x7b, 0x74, 0xf6, 0x98, 0xab, 0xb, 0x99, 0x80, 0x87, 0x47, 0x6b, 0x3b, 0xd5, 0x86, 0xec, 0x87, 0xfb, 0x3, 0xb7, 0x86, 0x5e, 0x6b, 0xb7, 0xd5, 0x57, 0xe8, 0xec, 0x7b, 0x31, 0xb6, 0x98, 0x5e, 0xec, 0xb7, 0xbe, 0x7, 0x3a, 0xec, 0xd3, 0xab, 0xee, 0x9a, 0x38, 0xe4, 0xe4, 0xfe, 0x76, 0xa, 0x99, 0x43, 0x5, 0x64, 0x1, 0x38, 0x63, 0xe4, 0x14, 0x6, 0x9b, 0x99, 0x4a, 0x4f, 0xe1, 0x0, 0x73, 0x22, 0xe, 0x44, 0xa0, 0x97, 0x44, 0xc4, 0xaa, 0x61, 0x99, 0x72, 0xac, 0x4e, 0xce, 0xe0, 0x35, 0x4c, 0x9d, 0xa0, 0x4e, 0x98, 0xa1, 0xad, 0x43, 0xce, 0x59, 0x25, 0x54, 0x5, 0xe4, 0xcf, 0x78, 0xa1, 0x94, 0x43, 0xa, 0x19, 0x10, 0x40, 0x85, 0x66, 0xaa, 0xfb, 0xd8, 0x85, 0xd7, 0x6a, 0x28, 0x4, 0x6, 0x45, 0xc6, 0x28, 0x60, 0xd9, 0x8a, 0xd7, 0xc7, 0x38, 0xe1, 0x56, 0xa1, 0x82, 0xd0, 0xc8, 0x2e, 0x8a, 0x3, 0xe6, 0x49, 0xe5, 0x58, 0x31, 0xec, 0x51, 0x32, 0x25, 0x35, 0x3, 0x29, 0x19, 0x12, 0xd0, 0xb, 0xef, 0xe1, 0x30, 0x72, 0x75, 0x2e, 0x39, 0xa4, 0x3a, 0xf8, 0x9b, 0x2b, 0xec, 0xd5, 0x72, 0x46, 0x2e, 0x17, 0xb5, 0x8a, 0xd8, 0xd6, 0x25, 0x5, 0xd3, 0x42, 0x46, 0x3b, 0x16, 0xfd, 0xce, 0xfe, 0x16, 0xf7, 0x4, 0xfc, 0x40, 0xdf, 0x3b, 0x90, 0xfd, 0xcd, 0xf6, 0x5b, 0xfb, 0x6c, 0xfe, 0xf0, 0xde, 0x65, 0xb0, 0x7e, 0xcd, 0xea, 0xdf, 0xe7, 0xe5, 0xfe, 0x71, 0xd4, 0x65, 0x51, 0x2e, 0xcd, 0xfa, 0x87, 0xfd, 0x58, 0xfc, 0x27, 0xd4, 0x68, 0x51, 0x8c, 0xed, 0xab, 0xa7, 0xd1, 0x50, 0x2e, 0x2f, 0xf9, 0x48, 0xc3, 0x9a, 0xb3, 0x23, 0xc5, 0xde, 0x28, 0x2c, 0xd8, 0xa8, 0xd7, 0xc5, 0x68, 0x93, 0xd, 0x41, 0xca, 0xa1, 0x40, 0xd9, 0x13, 0x97, 0x41, 0x28, 0xc2, 0x55, 0x6c, 0xec, 0x38, 0xe2, 0xdf, 0x13, 0xd6, 0x61, 0x73, 0xe2, 0x4f, 0x6c, 0x6c, 0xb0, 0x6b, 0x5d, 0x1f, 0x95, 0xa0, 0x43, 0xc6, 0x5b, 0x9, 0x60, 0x4f, 0x72, 0xa0, 0x9e, 0x48, 0xe0, 0xe8, 0xe6, 0x4, 0x15, 0x82, 0x4c, 0x47, 0xa0, 0x82, 0x8, 0x7, 0x98, 0x96, 0x3c, 0x2c, 0x9a, 0xe, 0x4d, 0x4a, 0x8a, 0x9a, 0x27, 0xea, 0xee, 0xe8, 0x1a, 0xf5, 0x5, 0xb1, 0xb, 0x74, 0xba, 0x39, 0xee, 0x79, 0xec, 0x8f, 0x67, 0x48, 0x38, 0xeb, 0x75, 0xe8, 0x79, 0x9f, 0x9, 0x99, 0x1f, 0xcd, 0x6, 0x29, 0xe9, 0xf2, 0xe9, 0x79, 0x9f, 0xd, 0x9d, 0x9b, 0x4b, 0x5, 0xac, 0xeb, 0x71, 0xa2, 0x19, 0x25, 0x1d, 0x98, 0x97, 0x4f, 0x7, 0x2e, 0xeb, 0xf8, 0xa2, 0x9a, 0x5, 0x6d, 0xb0, 0xe7, 0x5f, 0xfb, 0xae, 0xf5, 0xf9, 0x65, 0xf8, 0x3e, 0x39, 0xfe, 0x4b, 0x71, 0xe0, 0xb6, 0xf1, 0x75, 0x65, 0x12, 0x1e, 0xdb, 0xb6, 0xb3, 0xe3, 0x9c, 0xb2, 0xf, 0x75, 0xd0, 0x22, 0x10, 0xd7, 0x2d, 0x8d, 0x76, 0x91, 0x37, 0x8f, 0x35, 0xd1, 0x22, 0x0, 0xc4, 0x25, 0x5c, 0xfe, 0xf0, 0x36, 0xbc, 0x35, 0x8e, 0x42, 0xe8, 0xa4, 0x3, 0xfc, 0xd2, 0x7d, 0xa6, 0xbc, 0xba, 0xcf, 0xc8, 0xb8, 0x15, 0x23, 0x54, 0x58, 0xb3, 0x2f, 0x5f, 0xb2, 0x9c, 0xa8, 0x89, 0x65, 0x39, 0x54, 0x38, 0xb3, 0xd7, 0x5b, 0x8c, 0xdc, 0xa6, 0x99, 0xb1, 0x79, 0x18, 0x38, 0x10, 0x57, 0xc0 + 0xfd, 0xfe, 0xb4, 0xbf, 0x3e, 0x8f, 0xa3, 0xd3, 0xd0, 0x75, 0x04, 0xfe, 0xc1, 0xb5, 0xea, 0x3e, 0xc2, 0xc3, 0x4a, 0x80, 0x6e, 0x2c, 0x7a, 0x59, 0xfe, 0x6a, 0x94, 0x82, 0x2a, 0x7a, 0x47, 0x62, 0x84, 0xf8, 0x42, 0xfd, 0xa0, 0x94, 0x43, 0x4a, 0x39, 0x27, 0xd3, 0x06, 0x2d, 0x43, 0x9a, 0x21, 0xe7, 0x61, 0x54, 0x3d, 0xbc, 0xd3, 0x03, 0x2d, 0x09, 0x98, 0xc0, 0xe7, 0x7b, 0x74, 0xf6, 0x98, 0xab, 0x0b, 0x99, 0x80, 0x87, 0x47, 0x6b, 0x3b, 0xd5, 0x86, 0xec, 0x87, 0xfb, 0x03, 0xb7, 0x86, 0x5e, 0x6b, 0xb7, 0xd5, 0x57, 0xe8, 0xec, 0x7b, 0x31, 0xb6, 0x98, 0x5e, 0xec, 0xb7, 0xbe, 0x07, 0x3a, 0xec, 0xd3, 0xab, 0xee, 0x9a, 0x38, 0xe4, 0xe4, 0xfe, 0x76, 0x0a, 0x99, 0x43, 0x05, 0x64, 0x01, 0x38, 0x63, 0xe4, 0x14, 0x06, 0x9b, 0x99, 0x4a, 0x4f, 0xe1, 0x00, 0x73, 0x22, 0x0e, 0x44, 0xa0, 0x97, 0x44, 0xc4, 0xaa, 0x61, 0x99, 0x72, 0xac, 0x4e, 0xce, 0xe0, 0x35, 0x4c, 0x9d, 0xa0, 0x4e, 0x98, 0xa1, 0xad, 0x43, 0xce, 0x59, 0x25, 0x54, 0x05, 0xe4, 0xcf, 0x78, 0xa1, 0x94, 0x43, 0x0a, 0x19, 0x10, 0x40, 0x85, 0x66, 0xaa, 0xfb, 0xd8, 0x85, 0xd7, 0x6a, 0x28, 0x04, 0x06, 0x45, 0xc6, 0x28, 0x60, 0xd9, 0x8a, 0xd7, 0xc7, 0x38, 0xe1, 0x56, 0xa1, 0x82, 0xd0, 0xc8, 0x2e, 0x8a, 0x03, 0xe6, 0x49, 0xe5, 0x58, 0x31, 0xec, 0x51, 0x32, 0x25, 0x35, 0x03, 0x29, 0x19, 0x12, 0xd0, 0x0b, 0xef, 0xe1, 0x30, 0x72, 0x75, 0x2e, 0x39, 0xa4, 0x3a, 0xf8, 0x9b, 0x2b, 0xec, 0xd5, 0x72, 0x46, 0x2e, 0x17, 0xb5, 0x8a, 0xd8, 0xd6, 0x25, 0x05, 0xd3, 0x42, 0x46, 0x3b, 0x16, 0xfd, 0xce, 0xfe, 0x16, 0xf7, 0x04, 0xfc, 0x40, 0xdf, 0x3b, 0x90, 0xfd, 0xcd, 0xf6, 0x5b, 0xfb, 0x6c, 0xfe, 0xf0, 0xde, 0x65, 0xb0, 0x7e, 0xcd, 0xea, 0xdf, 0xe7, 0xe5, 0xfe, 0x71, 0xd4, 0x65, 0x51, 0x2e, 0xcd, 0xfa, 0x87, 0xfd, 0x58, 0xfc, 0x27, 0xd4, 0x68, 0x51, 0x8c, 0xed, 0xab, 0xa7, 0xd1, 0x50, 0x2e, 0x2f, 0xf9, 0x48, 0xc3, 0x9a, 0xb3, 0x23, 0xc5, 0xde, 0x28, 0x2c, 0xd8, 0xa8, 0xd7, 0xc5, 0x68, 0x93, 0x0d, 0x41, 0xca, 0xa1, 0x40, 0xd9, 0x13, 0x97, 0x41, 0x28, 0xc2, 0x55, 0x6c, 0xec, 0x38, 0xe2, 0xdf, 0x13, 0xd6, 0x61, 0x73, 0xe2, 0x4f, 0x6c, 0x6c, 0xb0, 0x6b, 0x5d, 0x1f, 0x95, 0xa0, 0x43, 0xc6, 0x5b, 0x09, 0x60, 0x4f, 0x72, 0xa0, 0x9e, 0x48, 0xe0, 0xe8, 0xe6, 0x04, 0x15, 0x82, 0x4c, 0x47, 0xa0, 0x82, 0x08, 0x07, 0x98, 0x96, 0x3c, 0x2c, 0x9a, 0x0e, 0x4d, 0x4a, 0x8a, 0x9a, 0x27, 0xea, 0xee, 0xe8, 0x1a, 0xf5, 0x05, 0xb1, 0x0b, 0x74, 0xba, 0x39, 0xee, 0x79, 0xec, 0x8f, 0x67, 0x48, 0x38, 0xeb, 0x75, 0xe8, 0x79, 0x9f, 0x09, 0x99, 0x1f, 0xcd, 0x06, 0x29, 0xe9, 0xf2, 0xe9, 0x79, 0x9f, 0x0d, 0x9d, 0x9b, 0x4b, 0x05, 0xac, 0xeb, 0x71, 0xa2, 0x19, 0x25, 0x1d, 0x98, 0x97, 0x4f, 0x07, 0x2e, 0xeb, 0xf8, 0xa2, 0x9a, 0x05, 0x6d, 0xb0, 0xe7, 0x5f, 0xfb, 0xae, 0xf5, 0xf9, 0x65, 0xf8, 0x3e, 0x39, 0xfe, 0x4b, 0x71, 0xe0, 0xb6, 0xf1, 0x75, 0x65, 0x12, 0x1e, 0xdb, 0xb6, 0xb3, 0xe3, 0x9c, 0xb2, 0x0f, 0x75, 0xd0, 0x22, 0x10, 0xd7, 0x2d, 0x8d, 0x76, 0x91, 0x37, 0x8f, 0x35, 0xd1, 0x22, 0x00, 0xc4, 0x25, 0x5c, 0xfe, 0xf0, 0x36, 0xbc, 0x35, 0x8e, 0x42, 0xe8, 0xa4, 0x03, 0xfc, 0xd2, 0x7d, 0xa6, 0xbc, 0xba, 0xcf, 0xc8, 0xb8, 0x15, 0x23, 0x54, 0x58, 0xb3, 0x2f, 0x5f, 0xb2, 0x9c, 0xa8, 0x89, 0x65, 0x39, 0x54, 0x38, 0xb3, 0xd7, 0x5b, 0x8c, 0xdc, 0xa6, 0x99, 0xb1, 0x79, 0x18, 0x38, 0x10, 0x57, 0xc0 }; const uint8_t prng_payload_sf12[] = { - 0xfd, 0x7c, 0xb4, 0xff, 0x5f, 0x9f, 0xd7, 0xab, 0x28, 0x73, 0x91, 0xff, 0xc5, 0xb5, 0xab, 0x1c, 0x92, 0xe7, 0x76, 0x74, 0x54, 0x9f, 0xfd, 0xc3, 0x7f, 0xa9, 0xb5, 0xd2, 0x5e, 0x46, 0xb7, 0x5c, 0x47, 0x7f, 0xfb, 0xff, 0xef, 0x35, 0x33, 0x1d, 0x15, 0xe7, 0x3d, 0x5f, 0x85, 0x5d, 0x91, 0xea, 0x87, 0xb7, 0x2, 0x55, 0x41, 0x4d, 0x30, 0xed, 0x18, 0x17, 0x11, 0x8d, 0x4c, 0x2, 0xab, 0xa0, 0xd9, 0x24, 0xd7, 0x24, 0x3, 0x97, 0x43, 0x1, 0x62, 0x8a, 0x7b, 0x99, 0xf4, 0xa6, 0x4e, 0x6f, 0xbb, 0x55, 0x49, 0xed, 0xea, 0x73, 0xbb, 0x36, 0xd9, 0x3e, 0x9c, 0xe3, 0xb2, 0x97, 0x24, 0xe1, 0x51, 0x38, 0x6f, 0x9e, 0x38, 0xec, 0x64, 0xbe, 0x54, 0x1a, 0x99, 0x4b, 0x5, 0x60, 0x1, 0x79, 0x48, 0xd4, 0xf0, 0x5a, 0x37, 0x2f, 0xd7, 0x4f, 0x6f, 0x2, 0x30, 0x1, 0x5e, 0x60, 0xbc, 0x5f, 0xf7, 0x1d, 0xbf, 0x4e, 0x13, 0xb0, 0xcd, 0x1e, 0xe8, 0xed, 0xe9, 0x9e, 0xa4, 0x39, 0x6b, 0x55, 0x72, 0x4f, 0x38, 0xaa, 0x15, 0x39, 0x16, 0xe8, 0x40, 0x11, 0x7e, 0xd8, 0x3e, 0x34, 0x1f, 0x57, 0x8d, 0x6, 0xca, 0xc, 0x81, 0x55, 0x49, 0xa1, 0x8c, 0xc, 0x3, 0xcf, 0xc0, 0x88, 0x5b, 0xad, 0x92, 0x33, 0x2c, 0x1, 0x5c, 0x92, 0xae, 0x1, 0x93, 0x2b, 0x16, 0x9e, 0x1f, 0xa, 0xaf, 0xf6, 0x1d, 0xab, 0x64, 0xd1, 0x73, 0x44, 0x25, 0x35, 0x5, 0x9, 0xb8, 0x43, 0x9b, 0xe6, 0x61, 0x30, 0x70, 0x75, 0x2e, 0x19, 0xc4, 0x4e, 0xd8, 0xdf, 0x25, 0xee, 0x52, 0x30, 0x26, 0x76, 0x63, 0xd8, 0xf6, 0x5a, 0xc5, 0xbb, 0x26, 0x54, 0x2, 0x65, 0xb, 0x13, 0x90, 0x2a, 0x10, 0x23, 0x41, 0x1, 0xf6, 0x13, 0xfc, 0xc8, 0xf4, 0x83, 0x45, 0x2c, 0x2a, 0x53, 0x5, 0xfc, 0xa4, 0x7f, 0xdf, 0xb5, 0x27, 0x35, 0x8, 0x42, 0xa3, 0x87, 0x46, 0xb4, 0xaa, 0xdd, 0xd7, 0x67, 0x6e, 0x18, 0x82, 0xcb, 0x1a, 0x18, 0xfe, 0x82, 0x75, 0xdd, 0xb6, 0xae, 0x14, 0xf0, 0x3d, 0x52, 0xe5, 0xc8, 0xe1, 0x7f, 0x99, 0x34, 0xc9, 0x5c, 0xeb, 0x4d, 0xa9, 0x9d, 0xdf, 0x7f, 0xb6, 0x12, 0xf, 0xca, 0x41, 0xa9, 0x20, 0xfb, 0x23, 0x93, 0x7d, 0xa8, 0xec, 0xc6, 0x69, 0xc3, 0xb1, 0xf0, 0x5f, 0xd3, 0xb7, 0x1, 0x43, 0xf6, 0x13, 0xf0, 0xca, 0xb3, 0x7a, 0x17, 0xb8, 0xa7, 0xc4, 0xf, 0x72, 0x25, 0x26, 0x65, 0xc4, 0xf5, 0x73, 0xfe, 0x3b, 0x95, 0xc4, 0x4a, 0x62, 0x50, 0x3e, 0x44, 0xc6, 0xef, 0xe2, 0xfb, 0x63, 0x15, 0xe, 0xa, 0xdb, 0x64, 0x39, 0x40, 0x7, 0x6a, 0x8, 0x32, 0x81, 0x7e, 0x36, 0x93, 0x3f, 0xdf, 0xcf, 0x47, 0x5b, 0x38, 0xa7, 0x52, 0xda, 0x44, 0xbc, 0x57, 0xc6, 0x9d, 0x87, 0x42, 0x51, 0xa6, 0xa0, 0x18, 0x2, 0x6c, 0xfa, 0xde, 0x8e, 0x5d, 0xeb, 0x9e, 0x39, 0x0, 0x1a, 0x42, 0x8f, 0xcb, 0xf8, 0x96, 0xde, 0xb5, 0x13, 0x20, 0x80, 0x13, 0xc0, 0x4d, 0x68, 0x8b, 0x8b, 0xe6, 0xc0, 0xa5, 0x7f, 0x2d, 0x40, 0x59, 0xea, 0x2c, 0xf1, 0xb8, 0xd, 0xe8, 0xa, 0x75, 0x1a, 0x59, 0xf4, 0x73, 0x35, 0xb7, 0x14, 0x35, 0x17, 0x20, 0x1b, 0xb0, 0x24, 0x41, 0xd2, 0xaf, 0xc7, 0xd6, 0xa0, 0x6, 0x8, 0x17, 0x96, 0xca, 0x9a, 0x93, 0x21, 0xe7, 0x50, 0xe3, 0xa6, 0x58, 0x68, 0x9b, 0xc6, 0x4c, 0x89, 0xae, 0x55, 0x4a, 0x76, 0x67, 0xf7, 0x58, 0x65, 0xbb, 0x37, 0x2f, 0xbb, 0xc2, 0x47, 0x71, 0x4f, 0xbe, 0x20, 0x75, 0x62, 0x39, 0x5e, 0x5d, 0xba, 0xb5, 0x52, 0x3, 0x60, 0xe2, 0xf2, 0x93, 0x4, 0x6a, 0x21, 0x44, 0x48, 0x50, 0x5c, 0xef, 0x2e, 0x38, 0xda, 0x37, 0x96, 0x9, 0x33, 0x56, 0x6f, 0x68, 0x66, 0x24, 0xb2, 0x99, 0x5f + 0xfd, 0x7c, 0xb4, 0xff, 0x5f, 0x9f, 0xd7, 0xab, 0x28, 0x73, 0x91, 0xff, 0xc5, 0xb5, 0xab, 0x1c, 0x92, 0xe7, 0x76, 0x74, 0x54, 0x9f, 0xfd, 0xc3, 0x7f, 0xa9, 0xb5, 0xd2, 0x5e, 0x46, 0xb7, 0x5c, 0x47, 0x7f, 0xfb, 0xff, 0xef, 0x35, 0x33, 0x1d, 0x15, 0xe7, 0x3d, 0x5f, 0x85, 0x5d, 0x91, 0xea, 0x87, 0xb7, 0x02, 0x55, 0x41, 0x4d, 0x30, 0xed, 0x18, 0x17, 0x11, 0x8d, 0x4c, 0x02, 0xab, 0xa0, 0xd9, 0x24, 0xd7, 0x24, 0x03, 0x97, 0x43, 0x01, 0x62, 0x8a, 0x7b, 0x99, 0xf4, 0xa6, 0x4e, 0x6f, 0xbb, 0x55, 0x49, 0xed, 0xea, 0x73, 0xbb, 0x36, 0xd9, 0x3e, 0x9c, 0xe3, 0xb2, 0x97, 0x24, 0xe1, 0x51, 0x38, 0x6f, 0x9e, 0x38, 0xec, 0x64, 0xbe, 0x54, 0x1a, 0x99, 0x4b, 0x05, 0x60, 0x01, 0x79, 0x48, 0xd4, 0xf0, 0x5a, 0x37, 0x2f, 0xd7, 0x4f, 0x6f, 0x02, 0x30, 0x01, 0x5e, 0x60, 0xbc, 0x5f, 0xf7, 0x1d, 0xbf, 0x4e, 0x13, 0xb0, 0xcd, 0x1e, 0xe8, 0xed, 0xe9, 0x9e, 0xa4, 0x39, 0x6b, 0x55, 0x72, 0x4f, 0x38, 0xaa, 0x15, 0x39, 0x16, 0xe8, 0x40, 0x11, 0x7e, 0xd8, 0x3e, 0x34, 0x1f, 0x57, 0x8d, 0x06, 0xca, 0x0c, 0x81, 0x55, 0x49, 0xa1, 0x8c, 0x0c, 0x03, 0xcf, 0xc0, 0x88, 0x5b, 0xad, 0x92, 0x33, 0x2c, 0x01, 0x5c, 0x92, 0xae, 0x01, 0x93, 0x2b, 0x16, 0x9e, 0x1f, 0x0a, 0xaf, 0xf6, 0x1d, 0xab, 0x64, 0xd1, 0x73, 0x44, 0x25, 0x35, 0x05, 0x09, 0xb8, 0x43, 0x9b, 0xe6, 0x61, 0x30, 0x70, 0x75, 0x2e, 0x19, 0xc4, 0x4e, 0xd8, 0xdf, 0x25, 0xee, 0x52, 0x30, 0x26, 0x76, 0x63, 0xd8, 0xf6, 0x5a, 0xc5, 0xbb, 0x26, 0x54, 0x02, 0x65, 0x0b, 0x13, 0x90, 0x2a, 0x10, 0x23, 0x41, 0x01, 0xf6, 0x13, 0xfc, 0xc8, 0xf4, 0x83, 0x45, 0x2c, 0x2a, 0x53, 0x05, 0xfc, 0xa4, 0x7f, 0xdf, 0xb5, 0x27, 0x35, 0x08, 0x42, 0xa3, 0x87, 0x46, 0xb4, 0xaa, 0xdd, 0xd7, 0x67, 0x6e, 0x18, 0x82, 0xcb, 0x1a, 0x18, 0xfe, 0x82, 0x75, 0xdd, 0xb6, 0xae, 0x14, 0xf0, 0x3d, 0x52, 0xe5, 0xc8, 0xe1, 0x7f, 0x99, 0x34, 0xc9, 0x5c, 0xeb, 0x4d, 0xa9, 0x9d, 0xdf, 0x7f, 0xb6, 0x12, 0x0f, 0xca, 0x41, 0xa9, 0x20, 0xfb, 0x23, 0x93, 0x7d, 0xa8, 0xec, 0xc6, 0x69, 0xc3, 0xb1, 0xf0, 0x5f, 0xd3, 0xb7, 0x01, 0x43, 0xf6, 0x13, 0xf0, 0xca, 0xb3, 0x7a, 0x17, 0xb8, 0xa7, 0xc4, 0x0f, 0x72, 0x25, 0x26, 0x65, 0xc4, 0xf5, 0x73, 0xfe, 0x3b, 0x95, 0xc4, 0x4a, 0x62, 0x50, 0x3e, 0x44, 0xc6, 0xef, 0xe2, 0xfb, 0x63, 0x15, 0x0e, 0x0a, 0xdb, 0x64, 0x39, 0x40, 0x07, 0x6a, 0x08, 0x32, 0x81, 0x7e, 0x36, 0x93, 0x3f, 0xdf, 0xcf, 0x47, 0x5b, 0x38, 0xa7, 0x52, 0xda, 0x44, 0xbc, 0x57, 0xc6, 0x9d, 0x87, 0x42, 0x51, 0xa6, 0xa0, 0x18, 0x02, 0x6c, 0xfa, 0xde, 0x8e, 0x5d, 0xeb, 0x9e, 0x39, 0x00, 0x1a, 0x42, 0x8f, 0xcb, 0xf8, 0x96, 0xde, 0xb5, 0x13, 0x20, 0x80, 0x13, 0xc0, 0x4d, 0x68, 0x8b, 0x8b, 0xe6, 0xc0, 0xa5, 0x7f, 0x2d, 0x40, 0x59, 0xea, 0x2c, 0xf1, 0xb8, 0x0d, 0xe8, 0x0a, 0x75, 0x1a, 0x59, 0xf4, 0x73, 0x35, 0xb7, 0x14, 0x35, 0x17, 0x20, 0x1b, 0xb0, 0x24, 0x41, 0xd2, 0xaf, 0xc7, 0xd6, 0xa0, 0x06, 0x08, 0x17, 0x96, 0xca, 0x9a, 0x93, 0x21, 0xe7, 0x50, 0xe3, 0xa6, 0x58, 0x68, 0x9b, 0xc6, 0x4c, 0x89, 0xae, 0x55, 0x4a, 0x76, 0x67, 0xf7, 0x58, 0x65, 0xbb, 0x37, 0x2f, 0xbb, 0xc2, 0x47, 0x71, 0x4f, 0xbe, 0x20, 0x75, 0x62, 0x39, 0x5e, 0x5d, 0xba, 0xb5, 0x52, 0x03, 0x60, 0xe2, 0xf2, 0x93, 0x04, 0x6a, 0x21, 0x44, 0x48, 0x50, 0x5c, 0xef, 0x2e, 0x38, 0xda, 0x37, 0x96, 0x09, 0x33, 0x56, 0x6f, 0x68, 0x66, 0x24, 0xb2, 0x99, 0x5f }; } } diff --git a/lib/utilities.h b/lib/utilities.h index 8b957c9..695edf1 100644 --- a/lib/utilities.h +++ b/lib/utilities.h @@ -5,7 +5,26 @@ namespace gr { namespace lora { - + + /** + * \brief Clamp given value in the given range. + * + * \tparam T + * The type of variable to clamp. + *
`d`, `min` and `max` must be of this type. + * \param d + * The value to clamp. + * \param min + * The lower bound of the range. + * \param max + * The upper bound of the range. + */ + template + inline T clamp(T d, T min, T max) { + const T t = d < min ? min : d; + return t > max ? max : t; + } + template std::string to_bin(T v, uint32_t bitwidth) { unsigned long long maxpow = bitwidth ? (1ull << (bitwidth - 1)) : 0,