Skip to content

Commit

Permalink
v1.0.3
Browse files Browse the repository at this point in the history
* HAL: Fixed scheduled downlink time precision by taking the tx start delay into
account.
* HAL: Fixed timestamp correction calculation for BW250 & BW500
* HAL: Fixed possible buffer overflow in lgw_receive() function
* HAL: Keep packet received in RX buffer when the buffer allocated to receive
the packets is too small. Remaining packets will be fetched on the next
lgw_receive calls (aligned on SX1301 behaviour).
  • Loading branch information
mcoracin committed Sep 20, 2019
1 parent df5cf56 commit 5942224
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 121 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.2
1.0.3
26 changes: 7 additions & 19 deletions libloragw/inc/loragw_sx1302.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,28 +350,15 @@ void sx1302_arb_print_debug_stats(void);
uint16_t sx1302_lora_payload_crc(const uint8_t * data, uint8_t size);

/**
@brief TODO
@param TODO
@return TODO
*/
uint16_t sx1302_rx_buffer_read_ptr_addr(void);

/**
@brief TODO
@param TODO
@return TODO
*/
uint16_t sx1302_rx_buffer_write_ptr_addr(void);

/**
@brief Check if any data to be fetched from the SX1302 RX buffer and fetch it if any.
@param nb_bytes A pointer to allocated memory to hold the number of bytes fetched
@brief Get the number of packets available in rx_buffer and fetch data from ...
@brief ... the SX1302 if rx_buffer is empty.
@param nb_pkt A pointer to allocated memory to hold the number of packet fetched
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int sx1302_fetch(uint16_t * nb_bytes);
int sx1302_fetch(uint8_t * nb_pkt);

/**
@brief Parse and return the next packet available in the fetched RX buffer.
@brief Parse and return the next packet available in rx_buffer.
@param context Gateway configuration context
@param p The structure to get the packet parsed
@return LGW_REG_SUCCESS if a packet could be parsed, LGW_REG_ERROR otherwise
Expand All @@ -384,9 +371,10 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p);
@param radio_type The type of radio for this RF chain
@param modulation The modulation used for the TX
@param bandwidth The bandwidth used for the TX
@param delay The TX start delay calculated and applied
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uint8_t modulation, uint8_t bandwidth);
int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uint8_t modulation, uint8_t bandwidth, uint16_t * delay);

/**
@brief Compute the offset to be applied on RSSI for temperature compensation
Expand Down
26 changes: 14 additions & 12 deletions libloragw/inc/loragw_sx1302_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,36 +72,38 @@ typedef struct rx_buffer_s {
uint8_t buffer[4096]; /*!> byte array to hald the data fetched from the RX buffer */
uint16_t buffer_size; /*!> The number of bytes currently stored in the buffer */
int buffer_index; /*!> Current parsing index in the buffer */
uint8_t buffer_pkt_nb;
} rx_buffer_t;

/* -------------------------------------------------------------------------- */
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */

/**
@brief TODO
@param TODO
@return TODO
@brief Initialize the rx_buffer instance
@param self A pointer to a rx_buffer handler
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int rx_buffer_new(rx_buffer_t * self);

/**
@brief TODO
@param TODO
@return TODO
@brief Reset the rx_buffer instance
@param self A pointer to a rx_buffer handler
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int rx_buffer_del(rx_buffer_t * self);

/**
@brief TODO
@param TODO
@return TODO
@brief Fetch packets from the SX1302 internal RX buffer, and count packets available.
@param self A pointer to a rx_buffer handler
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int rx_buffer_fetch(rx_buffer_t * self);

/**
@brief TODO
@param TODO
@return TODO
@brief Parse the rx_buffer and return the first packet available in the given structure.
@param self A pointer to a rx_buffer handler
@param pkt A pointer to the structure to receive the packet parsed
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt);

Expand Down
23 changes: 14 additions & 9 deletions libloragw/inc/loragw_sx1302_timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ typedef struct timestamp_counter_s {
/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */

/**
@brief TODO
@param TODO
@return TODO
@brief Initialize the timestamp_counter instance
@param self Pointer to the counter handler
@return N/A
*/
void timestamp_counter_new(timestamp_counter_t * self);

/**
@brief TODO
@param TODO
@return TODO
@brief Reset the timestamp_counter instance
@param self Pointer to the counter handler
@return N/A
*/
void timestamp_counter_delete(timestamp_counter_t * self);

Expand Down Expand Up @@ -106,9 +106,14 @@ uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps);
uint32_t timestamp_counter_correction(int ifmod, uint8_t bandwidth, uint8_t datarate, uint8_t coderate, uint32_t crc_en, uint16_t payload_length);

/**
@brief TODO
@param TODO
@return TODO
@brief Configure the SX1302 to output legacy timestamp or precision timestamp
@note Legacy timestamp gives a timestamp latched at the end of the packet
@note Precision timestamp gives a timestamp latched at the end of the header
@note and additionally supplies metrics every N symbols troughout the payload.
@param enable_precision_ts A boolean to enable precision timestamp output.
@param max_ts_metrics The number of timestamp metrics to be returned when precision timestamp is enabled
@param nb_symbols The sampling rate of timestamp metrics
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
*/
int timestamp_counter_mode(bool enable_precision_ts, uint8_t max_ts_metrics, uint8_t nb_symbols);

Expand Down
53 changes: 26 additions & 27 deletions libloragw/src/loragw_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
#include <time.h>
#include <unistd.h> /* symlink, unlink */
#include <fcntl.h>
#include <inttypes.h>

#include "loragw_reg.h"
#include "loragw_hal.h"
Expand Down Expand Up @@ -451,7 +452,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) {
CONTEXT_FSK.sync_word_size = conf->sync_word_size;
CONTEXT_FSK.sync_word = conf->sync_word;
}
DEBUG_PRINTF("Note: FSK if_chain %d configuration; en:%d freq:%d bw:%d dr:%d (%d real dr) sync:0x%0*llX\n", if_chain,
DEBUG_PRINTF("Note: FSK if_chain %d configuration; en:%d freq:%d bw:%d dr:%d (%d real dr) sync:0x%0*" PRIu64 "\n", if_chain,
CONTEXT_IF_CHAIN[if_chain].enable,
CONTEXT_IF_CHAIN[if_chain].freq_hz,
CONTEXT_FSK.bandwidth,
Expand Down Expand Up @@ -772,9 +773,9 @@ int lgw_stop(void) {

int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {
int res;
uint16_t sz = 0;
uint8_t nb_pkt_fetched = 0;
uint16_t nb_pkt_found = 0;
uint16_t nb_pkt_dropped = 0;
uint16_t nb_pkt_left = 0;
float current_temperature, rssi_temperature_offset;

/* Check that AGC/ARB firmwares are not corrupted, and update internal counter */
Expand All @@ -785,48 +786,46 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {
}

/* Get packets from SX1302, if any */
res = sx1302_fetch(&sz);
res = sx1302_fetch(&nb_pkt_fetched);
if (res != LGW_REG_SUCCESS) {
printf("ERROR: failed to fetch packets from SX1302\n");
return LGW_HAL_ERROR;
}
if (sz == 0) {
if (nb_pkt_fetched == 0) {
return 0;
}
if (nb_pkt_fetched > max_pkt) {
nb_pkt_left = nb_pkt_fetched - max_pkt;
printf("WARNING: not enough space allocated, fetched %d packet(s), %d will be left in RX buffer\n", nb_pkt_fetched, nb_pkt_left);
}

/* Get the current temperature for further RSSI compensation : TODO */
/* Apply RSSI temperature compensation */
res = stts751_get_temperature(ts_fd, ts_addr, &current_temperature);
if (res != LGW_I2C_SUCCESS) {
printf("ERROR: failed to get current temperature\n");
return LGW_HAL_ERROR;
}
DEBUG_PRINTF("INFO: current temperature is %f C\n", current_temperature);

/* Iterate on the RX buffer to get parsed packets */
res = LGW_REG_SUCCESS;
while ((res == LGW_REG_SUCCESS) && (nb_pkt_found <= max_pkt)) {
for (nb_pkt_found = 0; nb_pkt_found < ((nb_pkt_fetched <= max_pkt) ? nb_pkt_fetched : max_pkt); nb_pkt_found++) {
/* Get packet and move to next one */
res = sx1302_parse(&lgw_context, &pkt_data[nb_pkt_found]);
if (res == LGW_REG_SUCCESS) {
/* we found a packet and parsed it */
if ((nb_pkt_found + 1) > max_pkt) {
printf("WARNING: no space left, dropping packet\n");
nb_pkt_dropped += 1;
continue;
}
/* Appli RSSI offset calibrated for the board */
pkt_data[nb_pkt_found].rssic += CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_offset;
pkt_data[nb_pkt_found].rssis += CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_offset;
/* Apply RSSI temperature compensation */
rssi_temperature_offset = sx1302_rssi_get_temperature_offset(&CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_tcomp, current_temperature);
pkt_data[nb_pkt_found].rssic += rssi_temperature_offset;
pkt_data[nb_pkt_found].rssis += rssi_temperature_offset;
DEBUG_PRINTF("INFO: RSSI temperature offset applied: %.3f dB\n", rssi_temperature_offset);
/* Next packet */
nb_pkt_found += 1;
if (res != LGW_REG_SUCCESS) {
printf("ERROR: failed to parse fetched packet %d, aborting...\n", nb_pkt_found);
return LGW_HAL_ERROR;
}

/* Appli RSSI offset calibrated for the board */
pkt_data[nb_pkt_found].rssic += CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_offset;
pkt_data[nb_pkt_found].rssis += CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_offset;

rssi_temperature_offset = sx1302_rssi_get_temperature_offset(&CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_tcomp, current_temperature);
pkt_data[nb_pkt_found].rssic += rssi_temperature_offset;
pkt_data[nb_pkt_found].rssis += rssi_temperature_offset;
DEBUG_PRINTF("INFO: RSSI temperature offset applied: %.3f dB (current temperature %.1f C)\n", rssi_temperature_offset, current_temperature);
}

DEBUG_PRINTF("INFO: nb pkt found:%u dropped:%u\n", nb_pkt_found, nb_pkt_dropped);
DEBUG_PRINTF("INFO: nb pkt found:%u left:%u\n", nb_pkt_found, nb_pkt_left);

return nb_pkt_found;
}
Expand Down
50 changes: 32 additions & 18 deletions libloragw/src/loragw_sx1302.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ void sx1302_init(struct lgw_conf_timestamp_s *conf_ts) {
if (conf_ts != NULL) {
timestamp_counter_mode(conf_ts->enable_precision_ts, conf_ts->max_ts_metrics, conf_ts->nb_symbols);
}

/* Initialize RX buffer */
rx_buffer_new(&rx_buffer);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
Expand Down Expand Up @@ -1570,25 +1573,30 @@ int sx1302_arb_start(uint8_t version) {

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

int sx1302_fetch(uint16_t * nb_bytes) {
int sx1302_fetch(uint8_t * nb_pkt) {
int err;

/* Initialize RX buffer */
err = rx_buffer_new(&rx_buffer);
if (err != LGW_REG_SUCCESS) {
printf("ERROR: Failed to initialize RX buffer\n");
return LGW_REG_ERROR;
}
/* Fetch packets from sx1302 if no more left in RX buffer */
if (rx_buffer.buffer_pkt_nb == 0) {
/* Initialize RX buffer */
err = rx_buffer_new(&rx_buffer);
if (err != LGW_REG_SUCCESS) {
printf("ERROR: Failed to initialize RX buffer\n");
return LGW_REG_ERROR;
}

/* Fetch RX buffer if any data available */
err = rx_buffer_fetch(&rx_buffer);
if (err != LGW_REG_SUCCESS) {
printf("ERROR: Failed to fetch RX buffer\n");
return LGW_REG_ERROR;
/* Fetch RX buffer if any data available */
err = rx_buffer_fetch(&rx_buffer);
if (err != LGW_REG_SUCCESS) {
printf("ERROR: Failed to fetch RX buffer\n");
return LGW_REG_ERROR;
}
} else {
printf("Note: remaining %u packets in RX buffer, do not fetch sx1302 yet...\n", rx_buffer.buffer_pkt_nb);
}

/* Return the number of bytes fetched */
*nb_bytes = rx_buffer.buffer_size;
/* Return the number of packet fetched */
*nb_pkt = rx_buffer.buffer_pkt_nb;

return LGW_REG_SUCCESS;
}
Expand Down Expand Up @@ -1833,7 +1841,7 @@ uint16_t sx1302_lora_payload_crc(const uint8_t * data, uint8_t size) {

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

int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uint8_t modulation, uint8_t bandwidth) {
int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uint8_t modulation, uint8_t bandwidth, uint16_t * delay) {
uint16_t tx_start_delay = TX_START_DELAY_DEFAULT * 32;
uint16_t radio_bw_delay = 0;
uint16_t filter_delay = 0;
Expand All @@ -1842,6 +1850,8 @@ int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uin
int32_t val;
uint8_t chirp_low_pass = 0;

CHECK_NULL(delay);

/* Adjust with radio type and bandwidth */
switch (radio_type) {
case LGW_RADIO_TYPE_SX1250:
Expand Down Expand Up @@ -1896,6 +1906,9 @@ int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uin
lgw_reg_w(SX1302_REG_TX_TOP_TX_START_DELAY_MSB_TX_START_DELAY(rf_chain), (uint8_t)(tx_start_delay >> 8));
lgw_reg_w(SX1302_REG_TX_TOP_TX_START_DELAY_LSB_TX_START_DELAY(rf_chain), (uint8_t)(tx_start_delay >> 0));

/* return tx_start_delay */
*delay = tx_start_delay;

return LGW_REG_SUCCESS;
}

Expand Down Expand Up @@ -2013,6 +2026,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut,
uint8_t pow_index;
uint8_t mod_bw;
uint8_t pa_en;
uint16_t tx_start_delay;

/* CHeck input parameters */
CHECK_NULL(tx_lut);
Expand Down Expand Up @@ -2244,7 +2258,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut,
}

/* Set TX start delay */
sx1302_tx_set_start_delay(pkt_data->rf_chain, radio_type, pkt_data->modulation, pkt_data->bandwidth);
sx1302_tx_set_start_delay(pkt_data->rf_chain, radio_type, pkt_data->modulation, pkt_data->bandwidth, &tx_start_delay);

/* Write payload in transmit buffer */
lgw_reg_w(SX1302_REG_TX_TOP_TX_CTRL_WRITE_BUFFER(pkt_data->rf_chain), 0x01);
Expand All @@ -2265,8 +2279,8 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut,
lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_IMMEDIATE(pkt_data->rf_chain), 0x01);
break;
case TIMESTAMPED:
count_us = pkt_data->count_us * 32;
DEBUG_PRINTF("--> programming trig delay at %u (%u)\n", pkt_data->count_us, count_us);
count_us = pkt_data->count_us * 32 - tx_start_delay;
DEBUG_PRINTF("--> programming trig delay at %u (%u)\n", pkt_data->count_us - (tx_start_delay / 32), count_us);

lgw_reg_w(SX1302_REG_TX_TOP_TIMER_TRIG_BYTE0_TIMER_DELAYED_TRIG(pkt_data->rf_chain), (uint8_t)((count_us >> 0) & 0x000000FF));
lgw_reg_w(SX1302_REG_TX_TOP_TIMER_TRIG_BYTE1_TIMER_DELAYED_TRIG(pkt_data->rf_chain), (uint8_t)((count_us >> 8) & 0x000000FF));
Expand Down
Loading

0 comments on commit 5942224

Please sign in to comment.