Skip to content

Commit

Permalink
Fixed 'floating point exception' crash when concentrator returned a p…
Browse files Browse the repository at this point in the history
…acket 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).
  • Loading branch information
Sylvain Miermont committed Jan 27, 2014
1 parent f9203f1 commit f835eac
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 55 deletions.
2 changes: 1 addition & 1 deletion libloragw/VERSION
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
6 changes: 6 additions & 0 deletions libloragw/doc/CHANGELOG.TXT
Original file line number Diff line number Diff line change
@@ -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
---------------------

Expand Down
29 changes: 17 additions & 12 deletions libloragw/src/loragw_gps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ---------------------------------------------------- */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
74 changes: 42 additions & 32 deletions libloragw/src/loragw_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Maintainer: Sylvain Miermont
#include <stdint.h> /* C99 types */
#include <stdbool.h> /* bool type */
#include <stdio.h> /* printf fprintf */
#include <math.h> /* NaN */
#include <string.h> /* memcpy */

#include "loragw_reg.h"
Expand All @@ -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 ---------------------------------------------------- */
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand All @@ -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;
Expand Down
18 changes: 8 additions & 10 deletions loragw_pkt_logger/src/loragw_pkt_logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit f835eac

Please sign in to comment.