From f835eac31780cf7da5b69ae6bd4f57edefa45947 Mon Sep 17 00:00:00 2001 From: Sylvain Miermont Date: Mon, 27 Jan 2014 12:04:34 +0100 Subject: Fixed 'floating point exception' crash when concentrator returned a packet with SF=0 (CRC error on Lora header). Fixed buggy timezone handling HAL does not return NaN anymore for SNR and RSSI if measurements are not available (return -128). --- libloragw/VERSION | 2 +- libloragw/doc/CHANGELOG.TXT | 6 +++ libloragw/src/loragw_gps.c | 29 +++++++----- libloragw/src/loragw_hal.c | 74 ++++++++++++++++++------------- loragw_pkt_logger/src/loragw_pkt_logger.c | 18 ++++---- 5 files changed, 74 insertions(+), 55 deletions(-) diff --git a/libloragw/VERSION b/libloragw/VERSION index b44ab5c..fff109c 100644 --- a/libloragw/VERSION +++ b/libloragw/VERSION @@ -1,5 +1,5 @@ /* Software library version: */ -#define VERSION_LIBRARY "1.2.0" +#define VERSION_LIBRARY "1.2.1" /* API version */ #define VERSION_API "1" diff --git a/libloragw/doc/CHANGELOG.TXT b/libloragw/doc/CHANGELOG.TXT index bdaab2d..9402573 100644 --- a/libloragw/doc/CHANGELOG.TXT +++ b/libloragw/doc/CHANGELOG.TXT @@ -1,6 +1,12 @@ Lora Gateway HAL changelog ========================== + v1.2.1 +--------------------- + + * Fixed 'floating point exception' crash when concentrator returned a packet with SF=0 (CRC error on Lora header) + * Fixed buggy timezone handling + v1.2.0 --------------------- diff --git a/libloragw/src/loragw_gps.c b/libloragw/src/loragw_gps.c index 84db3b8..a5f8707 100644 --- a/libloragw/src/loragw_gps.c +++ b/libloragw/src/loragw_gps.c @@ -53,6 +53,7 @@ Maintainer: Sylvain Miermont #define DEBUG_ARRAY(a,b,c) for(a=0;a!=0;){} #define CHECK_NULL(a) if(a==NULL){return LGW_GPS_ERROR;} #endif +#define TRACE() fprintf(stderr, "@ %s %d\n", __FUNCTION__, __LINE__); /* -------------------------------------------------------------------------- */ /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ @@ -306,6 +307,9 @@ int lgw_gps_enable(char *tty_path, char *gps_familly, speed_t target_brate, int } tcflush(gps_tty_dev, TCIOFLUSH); + /* get timezone info */ + tzset(); + /* initialize global variables */ gps_time_ok = false; gps_pos_ok = false; @@ -429,7 +433,7 @@ int lgw_gps_get(struct timespec *utc, struct coord_s *loc, struct coord_s *err) x.tm_hour = gps_hou; x.tm_min = gps_min; x.tm_sec = gps_sec; - y = mktime(&x); + y = mktime(&x) - timezone; /* need to substract timezone bc mktime assumes time vector is local time */ if (y == (time_t)(-1)) { DEBUG_MSG("ERROR: FAILED TO CONVERT BROKEN-DOWN TIME\n"); return LGW_GPS_ERROR; @@ -470,20 +474,21 @@ int lgw_gps_sync(struct tref *ref, uint32_t count_us, struct timespec utc) { CHECK_NULL(ref); /* calculate the slope */ - cnt_diff = (count_us - ref->count_us) / TS_CPS; /* uncorrected by xtal_err */ - utc_diff = (utc.tv_sec - (ref->utc).tv_sec) + 1E-9 * (utc.tv_nsec - (ref->utc).tv_nsec); - if (utc_diff == 0.0) { // prevent divide by zero - DEBUG_MSG("ERROR: ATTEMPT TO DIVIDE BY ZERO\n"); - return LGW_GPS_ERROR; - } + cnt_diff = (double)(count_us - ref->count_us) / (double)(TS_CPS); /* uncorrected by xtal_err */ + utc_diff = (double)(utc.tv_sec - (ref->utc).tv_sec) + (1E-9 * (double)(utc.tv_nsec - (ref->utc).tv_nsec)); /* detect aberrant points by measuring if slope limits are exceeded */ - slope = cnt_diff/utc_diff; - if ((slope > PLUS_10PPM) || (slope < MINUS_10PPM)) { - DEBUG_MSG("Warning: correction range exceeded\n"); - aber_n0 = true; + if (utc_diff != 0) { // prevent divide by zero + slope = cnt_diff/utc_diff; + if ((slope > PLUS_10PPM) || (slope < MINUS_10PPM)) { + DEBUG_MSG("Warning: correction range exceeded\n"); + aber_n0 = true; + } else { + aber_n0 = false; + } } else { - aber_n0 = false; + DEBUG_MSG("Warning: aberrant UTC value for synchronization\n"); + aber_n0 = true; } /* watch if the 3 latest sync point were aberrant or not */ diff --git a/libloragw/src/loragw_hal.c b/libloragw/src/loragw_hal.c index 4319d5e..3ab1cb5 100644 --- a/libloragw/src/loragw_hal.c +++ b/libloragw/src/loragw_hal.c @@ -20,7 +20,6 @@ Maintainer: Sylvain Miermont #include /* C99 types */ #include /* bool type */ #include /* printf fprintf */ -#include /* NaN */ #include /* memcpy */ #include "loragw_reg.h" @@ -45,6 +44,7 @@ Maintainer: Sylvain Miermont #define IF_HZ_TO_REG(f) (f << 5)/15625 #define SET_PPM_ON(bw,dr) (((bw == BW_125KHZ) && ((dr == DR_LORA_SF11) || (dr == DR_LORA_SF12))) || ((bw == BW_250KHZ) && (dr == DR_LORA_SF12))) +#define TRACE() fprintf(stderr, "@ %s %d\n", __FUNCTION__, __LINE__); /* -------------------------------------------------------------------------- */ /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ @@ -763,13 +763,13 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { int nb_pkt_fetch; /* loop variable and return value */ struct lgw_pkt_rx_s *p; /* pointer to the current structure in the struct array */ uint8_t buff[255+RX_METADATA_NB]; /* buffer to store the result of SPI read bursts */ - int sz; /* size of the payload, uses to address metadata */ + unsigned sz; /* size of the payload, uses to address metadata */ int ifmod; /* type of if_chain/modem a packet was received by */ int stat_fifo; /* the packet status as indicated in the FIFO */ uint32_t raw_timestamp; /* timestamp when internal 'RX finished' was triggered */ + uint32_t delay_x, delay_y, delay_z; /* temporary variable for timestamp offset calculation */ uint32_t timestamp_correction; /* correction to account for processing delay */ - uint8_t sf, cr, bw; /* used to calculate timestamp correction */ - uint8_t crc_en, ppm; /* used to calculate timestamp correction */ + uint32_t sf, cr, bw_pow, crc_en, ppm; /* used to calculate timestamp correction */ /* check if the gateway is running */ if (lgw_is_started == false) { @@ -864,41 +864,51 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { default: p->coderate = CR_UNDEFINED; } - /* timestamp correction code */ + /* determine if 'PPM mode' is on, needed for timestamp correction */ + if (SET_PPM_ON(p->bandwidth,p->datarate)) { + ppm = 1; + } else { + ppm = 0; + } + + /* timestamp correction code, base delay */ if (ifmod == IF_LORA_STD) { /* if packet was received on the stand-alone lora modem */ switch (lora_rx_bw) { case BW_125KHZ: - timestamp_correction = 64; - bw = 1; + delay_x = 64; + bw_pow = 1; break; case BW_250KHZ: - timestamp_correction = 32; - bw = 2; + delay_x = 32; + bw_pow = 2; break; case BW_500KHZ: - timestamp_correction = 16; - bw = 4; + delay_x = 16; + bw_pow = 4; break; default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); - timestamp_correction = 0; - bw = 0; + delay_x = 0; + bw_pow = 0; } } else { /* packet was received on one of the sensor channels = 125kHz */ - timestamp_correction = 114; - bw = 1; + delay_x = 114; + bw_pow = 1; } - if (SET_PPM_ON(p->bandwidth,p->datarate)) { - ppm = 1; - } else { - ppm = 0; - } - if ((2*(sz + 2*crc_en) - sf +7) <= 0) { /* payload fits entirely in first 8 symbols */ - timestamp_correction += (((1<<(sf-1)) * (sf+1)) + (3*(1<<(sf-4))))/bw; - timestamp_correction += 32 * (2*(sz+2*crc_en) + 5)/bw; + + /* timestamp correction code, variable delay */ + if ((sf >= 6) && (sf <= 12) && (bw_pow > 0)) { + if ((2*(sz + 2*crc_en) - (sf-7)) <= 0) { /* payload fits entirely in first 8 symbols */ + delay_y = ( ((1<<(sf-1)) * (sf+1)) + (3 * (1<<(sf-4))) ) / bw_pow; + delay_z = 32 * (2*(sz+2*crc_en) + 5) / bw_pow; + } else { + delay_y = ( ((1<<(sf-1)) * (sf+1)) + ((4 - ppm) * (1<<(sf-4))) ) / bw_pow; + delay_z = (16 + 4*cr) * (((2*(sz+2*crc_en)-sf+6) % (sf - 2*ppm)) + 1) / bw_pow; + } + timestamp_correction = delay_x + delay_y + delay_z; } else { - timestamp_correction += (((1<<(sf-1)) * (sf+1)) + ((4.0-ppm)/4.0*(1<<(sf-2))))/bw; - timestamp_correction += (16 + 4*cr) * (((2*(sz+2*crc_en)-sf + 6) % (sf-2*ppm) +1) / bw); + timestamp_correction = 0; + DEBUG_MSG("WARNING: invalid packet, no timestamp correction\n"); } } else if (ifmod == IF_FSK_STD) { DEBUG_MSG("Note: FSK packet\n"); @@ -910,9 +920,9 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { } p->modulation = MOD_FSK; p->rssi = (RSSI_OFFSET_FSK + (float)buff[sz+5])/RSSI_SLOPE_FSK; - p->snr = NAN; - p->snr_min = NAN; - p->snr_max = NAN; + p->snr = -128.0; + p->snr_min = -128.0; + p->snr_max = -128.0; p->bandwidth = fsk_rx_bw; p->datarate = fsk_rx_dr; p->coderate = CR_UNDEFINED; @@ -921,10 +931,10 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); p->status = STAT_UNDEFINED; p->modulation = MOD_UNDEFINED; - p->rssi = NAN; - p->snr = NAN; - p->snr_min = NAN; - p->snr_max = NAN; + p->rssi = -128.0; + p->snr = -128.0; + p->snr_min = -128.0; + p->snr_max = -128.0; p->bandwidth = BW_UNDEFINED; p->datarate = DR_UNDEFINED; p->coderate = CR_UNDEFINED; diff --git a/loragw_pkt_logger/src/loragw_pkt_logger.c b/loragw_pkt_logger/src/loragw_pkt_logger.c index f5f6b30..c298878 100644 --- a/loragw_pkt_logger/src/loragw_pkt_logger.c +++ b/loragw_pkt_logger/src/loragw_pkt_logger.c @@ -234,16 +234,14 @@ int parse_SX1301_configuration(const char * conf_file) { ifconf.rf_chain = (uint32_t)json_object_dotget_number(conf, "chan_FSK.radio"); ifconf.freq_hz = (int32_t)json_object_dotget_number(conf, "chan_FSK.if"); bw = (uint32_t)json_object_dotget_number(conf, "chan_FSK.bandwidth"); - switch(bw) { - case 500000: ifconf.bandwidth = BW_500KHZ; break; - case 250000: ifconf.bandwidth = BW_250KHZ; break; - case 125000: ifconf.bandwidth = BW_125KHZ; break; - case 62500: ifconf.bandwidth = BW_62K5HZ; break; - case 31200: ifconf.bandwidth = BW_31K2HZ; break; - case 15600: ifconf.bandwidth = BW_15K6HZ; break; - case 7800: ifconf.bandwidth = BW_7K8HZ; break; - default: ifconf.bandwidth = BW_UNDEFINED; - } + if (bw <= 7800) ifconf.bandwidth = BW_7K8HZ; + else if (bw <= 15600) ifconf.bandwidth = BW_15K6HZ; + else if (bw <= 31200) ifconf.bandwidth = BW_31K2HZ; + else if (bw <= 62500) ifconf.bandwidth = BW_62K5HZ; + else if (bw <= 125000) ifconf.bandwidth = BW_125KHZ; + else if (bw <= 250000) ifconf.bandwidth = BW_250KHZ; + else if (bw <= 500000) ifconf.bandwidth = BW_500KHZ; + else ifconf.bandwidth = BW_UNDEFINED; ifconf.datarate = (uint32_t)json_object_dotget_number(conf, "chan_FSK.datarate"); MSG("INFO: FSK channel enabled, radio %i selected, IF %i Hz, %u Hz bandwidth, %u bps datarate\n", ifconf.rf_chain, ifconf.freq_hz, bw, ifconf.datarate); } -- cgit v1.2.3