Skip to content

Commit

Permalink
v1.0.5
Browse files Browse the repository at this point in the history
* HAL: Fixed packet timestamp issue which was "jumping in time" in specific
conditions.
* HAL: Workaround hardware issue when reading 32-bits registers (timestamp, nb
bytes in RX buffer...)
* HAL: Fixed potential endless loop in sx1302_tx_abort() in SPI access fails.
* Packet Forwarder: Added global_conf.json.sx1250.US915 for US915 band
* test_hal_rx: added command line to specify RSSI offset to be applied
  • Loading branch information
mcoracin committed Feb 21, 2020
1 parent 81e748c commit 6291e62
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 68 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.4
1.0.5
22 changes: 16 additions & 6 deletions libloragw/inc/loragw_sx1302_timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
/* --- DEPENDANCIES --------------------------------------------------------- */

#include <stdint.h> /* C99 types*/
#include <stdbool.h> /* boolean type */
#include <stdbool.h> /* boolean type */


#include "config.h" /* library configuration options (dynamically generated) */
Expand All @@ -41,13 +41,15 @@ License: Revised BSD License, see LICENSE.TXT file include in the project

/**
@struct timestamp_counter_s
@brief context to maintain the internal counters (inst and pps trig) wrapping
@brief context to maintain the internal counters (inst and pps trig) rollover status
*/
struct timestamp_info_s {
uint32_t counter_us_27bits_ref; /* reference value (last read) */
uint8_t counter_us_27bits_wrap; /* rollover/wrap status */
};
typedef struct timestamp_counter_s {
uint32_t counter_us_raw_27bits_inst_prev;
uint32_t counter_us_raw_27bits_pps_prev;
uint8_t counter_us_raw_27bits_inst_wrap;
uint8_t counter_us_raw_27bits_pps_wrap;
struct timestamp_info_s inst; /* holds current reference of the instantaneous counter */
struct timestamp_info_s pps; /* holds current reference of the pps-trigged counter */
} timestamp_counter_t;

/* -------------------------------------------------------------------------- */
Expand Down Expand Up @@ -85,6 +87,14 @@ void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt
*/
uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_us);

/**
@brief Convert the 27-bits packet timestamp to a 32-bits counter which wraps on a uint32_t.
@param self Pointer to the counter handler
@param cnt_us The packet 27-bits counter to be expanded
@return the 32-bits counter
*/
uint32_t timestamp_pkt_expand(timestamp_counter_t * self, uint32_t cnt_us);

/**
@brief Reads the SX1302 internal counter register, and return the 32-bits 1 MHz counter
@param self Pointer to the counter handler
Expand Down
26 changes: 19 additions & 7 deletions libloragw/src/loragw_sx1302.c
Original file line number Diff line number Diff line change
Expand Up @@ -1812,10 +1812,15 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) {
timestamp_correction = 0;
}

/* Scale packet timestamp to 1 MHz (microseconds) */
/* Update counter reference / wrap status before expanding */
timestamp_counter_get(&counter_us, false);

/* Scale 32 MHz packet timestamp to 1 MHz (microseconds) */
p->count_us = pkt.timestamp_cnt / 32;

/* Expand 27-bits counter to 32-bits counter, based on current wrapping status */
p->count_us = timestamp_counter_expand(&counter_us, false, p->count_us);
p->count_us = timestamp_pkt_expand(&counter_us, p->count_us);

/* Packet timestamp corrected */
p->count_us = p->count_us - timestamp_correction;

Expand Down Expand Up @@ -1940,7 +1945,7 @@ uint8_t sx1302_tx_status(uint8_t rf_chain) {

err = lgw_reg_r(SX1302_REG_TX_TOP_TX_FSM_STATUS_TX_STATUS(rf_chain), &read_value);
if (err != LGW_REG_SUCCESS) {
printf("ERROR: Failed to read TX STATUS");
printf("ERROR: Failed to read TX STATUS\n");
return TX_STATUS_UNKNOWN;
}

Expand All @@ -1967,13 +1972,20 @@ uint8_t sx1302_rx_status(uint8_t rf_chain) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

int sx1302_tx_abort(uint8_t rf_chain) {
lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_IMMEDIATE(rf_chain), 0x00);
lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_DELAYED(rf_chain), 0x00);
lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_GPS(rf_chain), 0x00);
int err;
uint8_t tx_status;

err = lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_IMMEDIATE(rf_chain), 0x00);
err |= lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_DELAYED(rf_chain), 0x00);
err |= lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_GPS(rf_chain), 0x00);
if (err != LGW_REG_SUCCESS) {
printf("ERROR: Failed to stop TX trigger\n");
return err;
}

do {
wait_ms(1);
} while (sx1302_tx_status(rf_chain) != TX_FREE);
} while ((tx_status = sx1302_tx_status(rf_chain)) != TX_FREE && tx_status != TX_STATUS_UNKNOWN);

return LGW_REG_SUCCESS;
}
Expand Down
22 changes: 12 additions & 10 deletions libloragw/src/loragw_sx1302_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,23 @@ int rx_buffer_del(rx_buffer_t * self) {
int rx_buffer_fetch(rx_buffer_t * self) {
int i, res;
uint8_t buff[2];
int32_t msb;

/* Check input params */
CHECK_NULL(self);

/* Check if there is data in the FIFO */
lgw_reg_rb(SX1302_REG_RX_TOP_RX_BUFFER_NB_BYTES_MSB_RX_BUFFER_NB_BYTES, buff, sizeof buff);
self->buffer_size = (uint16_t)((buff[0] << 8) & 0xFF00);
self->buffer_size |= (uint16_t)((buff[1] << 0) & 0x00FF);
/* Workaround concentrator chip issue:
- read MSB again
- if MSB changed, read the full size gain
*/
lgw_reg_r(SX1302_REG_RX_TOP_RX_BUFFER_NB_BYTES_MSB_RX_BUFFER_NB_BYTES, &msb);
if (buff[0] != (uint8_t)msb) {
lgw_reg_rb(SX1302_REG_RX_TOP_RX_BUFFER_NB_BYTES_MSB_RX_BUFFER_NB_BYTES, buff, sizeof buff);
}

self->buffer_size = (buff[0] << 8) | (buff[1] << 0);

/* Fetch bytes from fifo if any */
if (self->buffer_size > 0) {
Expand Down Expand Up @@ -277,13 +286,6 @@ int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt) {
pkt->timestamp_cnt |= (uint32_t)((SX1302_PKT_TIMESTAMP_23_16(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 16) & 0x00FF0000);
pkt->timestamp_cnt |= (uint32_t)((SX1302_PKT_TIMESTAMP_31_24(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 24) & 0xFF000000);

#if 0
/* Scale packet timestamp to 1 MHz (microseconds) */
pkt->timestamp_cnt /= 32;
/* Expand 27-bits counter to 32-bits counter, based on current wrapping status */
pkt->timestamp_cnt = timestamp_counter_expand(&counter_us, false, pkt->timestamp_cnt);
#endif

DEBUG_MSG ("-----------------\n");
DEBUG_PRINTF(" modem: %u\n", pkt->modem_id);
DEBUG_PRINTF(" chan: %u\n", pkt->rx_channel_in);
Expand Down Expand Up @@ -323,7 +325,7 @@ int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt) {
/* Move buffer index toward next message */
self->buffer_index += (SX1302_PKT_HEAD_METADATA + pkt->rxbytenb_modem + SX1302_PKT_TAIL_METADATA + (2 * pkt->num_ts_metrics_stored));

/* Update the umber of packets currently stored in the rx_buffer */
/* Update the number of packets currently stored in the rx_buffer */
self->buffer_pkt_nb -= 1;

return LGW_REG_SUCCESS;
Expand Down
113 changes: 70 additions & 43 deletions libloragw/src/loragw_sx1302_timestamp.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project

#include <stdint.h> /* C99 types */
#include <stdio.h> /* printf fprintf */
#include <memory.h> /* memset */

#include "loragw_sx1302_timestamp.h"
#include "loragw_reg.h"
Expand Down Expand Up @@ -65,50 +66,28 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */

void timestamp_counter_new(timestamp_counter_t * self) {
self->counter_us_raw_27bits_inst_prev = 0;
self->counter_us_raw_27bits_pps_prev = 0;
self->counter_us_raw_27bits_inst_wrap = 0;
self->counter_us_raw_27bits_pps_wrap = 0;
memset(self, 0, sizeof(*self));
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

void timestamp_counter_delete(timestamp_counter_t * self) {
self->counter_us_raw_27bits_inst_prev = 0;
self->counter_us_raw_27bits_pps_prev = 0;
self->counter_us_raw_27bits_inst_wrap = 0;
self->counter_us_raw_27bits_pps_wrap = 0;
memset(self, 0, sizeof(*self));
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt) {
uint32_t counter_us_raw_27bits_prev;
uint8_t counter_us_raw_27bits_wrap;

/* Get the previous counter value and wrap status */
if (pps == true) {
counter_us_raw_27bits_prev = self->counter_us_raw_27bits_pps_prev;
counter_us_raw_27bits_wrap = self->counter_us_raw_27bits_pps_wrap;
} else {
counter_us_raw_27bits_prev = self->counter_us_raw_27bits_inst_prev;
counter_us_raw_27bits_wrap = self->counter_us_raw_27bits_inst_wrap;
}
struct timestamp_info_s* tinfo = (pps == true) ? &self->pps : &self->inst;

/* Check if counter has wrapped, and update wrap status if necessary */
if (cnt < counter_us_raw_27bits_prev) {
counter_us_raw_27bits_wrap += 1;
counter_us_raw_27bits_wrap = counter_us_raw_27bits_wrap % 32;
if (cnt < tinfo->counter_us_27bits_ref) {
tinfo->counter_us_27bits_wrap += 1;
tinfo->counter_us_27bits_wrap %= 32;
}

/* Store counter value and wrap status for next time */
if (pps == true) {
self->counter_us_raw_27bits_pps_prev = cnt;
self->counter_us_raw_27bits_pps_wrap = counter_us_raw_27bits_wrap;
} else {
self->counter_us_raw_27bits_inst_prev = cnt;
self->counter_us_raw_27bits_inst_wrap = counter_us_raw_27bits_wrap;
}
/* Update counter reference */
tinfo->counter_us_27bits_ref = cnt;
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
Expand All @@ -117,20 +96,42 @@ uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps) {
int x;
uint8_t buff[4];
uint32_t counter_us_raw_27bits_now;
int32_t msb;

/* Get the 32MHz timestamp counter - 4 bytes */
/* step of 31.25 ns */
x = lgw_reg_rb((pps == true) ? SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS : SX1302_REG_TIMESTAMP_TIMESTAMP_MSB2_TIMESTAMP, &buff[0], 4);
x = lgw_reg_rb((pps == true) ? SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS :
SX1302_REG_TIMESTAMP_TIMESTAMP_MSB2_TIMESTAMP,
&buff[0], 4);
if (x != LGW_REG_SUCCESS) {
printf("ERROR: Failed to get timestamp counter value\n");
return 0;
}

counter_us_raw_27bits_now = (uint32_t)((buff[0] << 24) & 0xFF000000);
counter_us_raw_27bits_now |= (uint32_t)((buff[1] << 16) & 0x00FF0000);
counter_us_raw_27bits_now |= (uint32_t)((buff[2] << 8) & 0x0000FF00);
counter_us_raw_27bits_now |= (uint32_t)((buff[3] << 0) & 0x000000FF);
counter_us_raw_27bits_now /= 32; /* scale to 1MHz */
/* Workaround concentrator chip issue:
- read MSB again
- if MSB changed, read the full counter gain
*/
x = lgw_reg_r((pps == true) ? SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS :
SX1302_REG_TIMESTAMP_TIMESTAMP_MSB2_TIMESTAMP,
&msb);
if (x != LGW_REG_SUCCESS) {
printf("ERROR: Failed to get timestamp counter MSB value\n");
return 0;
}
if (buff[0] != (uint8_t)msb) {
x = lgw_reg_rb((pps == true) ? SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS :
SX1302_REG_TIMESTAMP_TIMESTAMP_MSB2_TIMESTAMP,
&buff[0], 4);
if (x != LGW_REG_SUCCESS) {
printf("ERROR: Failed to get timestamp counter value\n");
return 0;
}
}

counter_us_raw_27bits_now = (buff[0]<<24) | (buff[1]<<16) | (buff[2]<<8) | buff[3];

/* Scale to 1MHz */
counter_us_raw_27bits_now /= 32;

/* Update counter wrapping status */
timestamp_counter_update(self, pps, counter_us_raw_27bits_now);
Expand All @@ -142,26 +143,52 @@ uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_us) {
struct timestamp_info_s* tinfo = (pps == true) ? &self->pps : &self->inst;
uint32_t counter_us_32bits;

if (pps == true) {
counter_us_32bits = (self->counter_us_raw_27bits_pps_wrap << 27) | cnt_us;
} else {
counter_us_32bits = (self->counter_us_raw_27bits_inst_wrap << 27) | cnt_us;
}
counter_us_32bits = (tinfo->counter_us_27bits_wrap << 27) | cnt_us;

#if 0
/* DEBUG: to be enabled when running test_loragw_counter test application
This generates a CSV log, and can be plotted with gnuplot:
> set datafile separator comma
> plot for [col=1:2:1] 'log_count.txt' using col with lines
*/
printf("%u,%u,%u\n", cnt_us, counter_us_32bits, (pps == true) ? self->counter_us_raw_27bits_pps_wrap : self->counter_us_raw_27bits_inst_wrap);
printf("%u,%u,%u\n", cnt_us, counter_us_32bits, tinfo->counter_us_27bits_wrap);
#endif

return counter_us_32bits;
}


/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

uint32_t timestamp_pkt_expand(timestamp_counter_t * self, uint32_t pkt_cnt_us) {
struct timestamp_info_s* tinfo = &self->inst;
uint32_t counter_us_32bits;
uint8_t wrap_status;

/* Check if counter has wrapped since the packet has been received in the sx1302 internal FIFO */
/* If the sx1302 counter was greater than the pkt timestamp, it means that the internal counter
hasn't rolled over since the packet has been received by the sx1302
case 1: --|-P--|----|--R-|----|--||-|----|-- : use current wrap status counter
case 2: --|-P-||-|-R--|-- : use previous wrap status counter
P : packet received in sx1302 internal FIFO
R : read packet from sx1302 internal FIFO
| : last update internal counter ref value.
||: sx1302 internal counter rollover (wrap)
*/

/* Use current wrap counter or previous ? */
wrap_status = tinfo->counter_us_27bits_wrap - ((tinfo->counter_us_27bits_ref >= pkt_cnt_us) ? 0 : 1);
wrap_status &= 0x1F; /* [0..31] */

/* Expand packet counter */
counter_us_32bits = (wrap_status << 27) | pkt_cnt_us;

return counter_us_32bits;
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

int timestamp_counter_mode(bool enable_precision_ts, uint8_t max_ts_metrics, uint8_t nb_symbols) {
Expand Down
15 changes: 14 additions & 1 deletion libloragw/tst/test_loragw_hal_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ void usage(void) {
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
printf(" -a <float> Radio A RX frequency in MHz\n");
printf(" -b <float> Radio B RX frequency in MHz\n");
printf(" -o <float> RSSI Offset to be applied in dB\n");
printf(" -n <uint> Number of packet received with CRC OK for each HAL start/stop loop\n");
printf(" -z <uint> Size of the RX packet array to be passed to lgw_receive()\n");
printf(" -m <uint> Channel frequency plan mode [0:LoRaWAN-like, 1:Same frequency for all channels (-400000Hz on RF0)]\n");
Expand All @@ -99,6 +100,7 @@ int main(int argc, char **argv)
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
uint8_t max_rx_pkt = 16;
bool single_input_mode = false;
float rssi_offset = 0.0;

struct lgw_conf_board_s boardconf;
struct lgw_conf_rxrf_s rfconf;
Expand Down Expand Up @@ -138,7 +140,7 @@ int main(int argc, char **argv)
const uint8_t channel_rfchain_mode1[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };

/* parse command line options */
while ((i = getopt (argc, argv, "hja:b:k:r:n:z:m:")) != -1) {
while ((i = getopt (argc, argv, "hja:b:k:r:n:z:m:o:")) != -1) {
switch (i) {
case 'h':
usage();
Expand Down Expand Up @@ -220,6 +222,15 @@ int main(int argc, char **argv)
channel_mode = arg_u;
}
break;
case 'o': /* <float> RSSI offset in dB */
i = sscanf(optarg, "%lf", &arg_d);
if (i != 1) {
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
return EXIT_FAILURE;
} else {
rssi_offset = (float)arg_d;
}
break;
default:
printf("ERROR: argument parsing\n");
usage();
Expand Down Expand Up @@ -254,6 +265,7 @@ int main(int argc, char **argv)
rfconf.enable = true;
rfconf.freq_hz = fa;
rfconf.type = radio_type;
rfconf.rssi_offset = rssi_offset;
rfconf.tx_enable = false;
rfconf.single_input_mode = single_input_mode;
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
Expand All @@ -265,6 +277,7 @@ int main(int argc, char **argv)
rfconf.enable = true;
rfconf.freq_hz = fb;
rfconf.type = radio_type;
rfconf.rssi_offset = rssi_offset;
rfconf.tx_enable = false;
rfconf.single_input_mode = single_input_mode;
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
Expand Down
Loading

0 comments on commit 6291e62

Please sign in to comment.