> #### Updates

The fine timestamping feature has been fully validated with this release.

> #### Changes

* HAL: Adjusted the freq_offset field of received packets, to take into account
the channel IF resolution error.
* HAL: Refined the fine timestamp offset compared to Gateway v2, by taking into
account the frequency offset of the received packet.
* HAL: Fixed the preamble length for FSK downlinks
* MCU: Removed the binary compiled in debug mode.
* util_spectral_scan: actually use the nb_scan input argument which was ignored.
This commit is contained in:
Michael Coracin 2020-12-18 11:11:19 +01:00
commit 05416800cd
7 changed files with 49 additions and 11 deletions

View file

@ -1 +1 @@
2.0.0 2.0.1

View file

@ -141,7 +141,7 @@ int timestamp_counter_mode(bool ftime_enable);
@param result_ftime A pointer to store the resulting fine timestamp @param result_ftime A pointer to store the resulting fine timestamp
@return 0 if success, -1 otherwise @return 0 if success, -1 otherwise
*/ */
int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics, uint32_t pkt_coarse_tmst, uint8_t sf, int32_t if_freq_hz, uint32_t * result_ftime); int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics, uint32_t pkt_coarse_tmst, uint8_t sf, int32_t if_freq_hz, double pkt_freq_error, uint32_t * result_ftime);
#endif #endif

View file

@ -49,7 +49,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
#endif #endif
#define CHECK_ERR(a) if(a==-1){return LGW_REG_ERROR;} #define CHECK_ERR(a) if(a==-1){return LGW_REG_ERROR;}
#define IF_HZ_TO_REG(f) ((f << 5) / 15625) #define IF_HZ_TO_REG(f) ((f * 32) / 15625)
#define SX1302_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 18) / 32000000U) #define SX1302_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 18) / 32000000U)
@ -1897,6 +1897,9 @@ int sx1302_fetch(uint8_t * nb_pkt) {
int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) { int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) {
int err; int err;
int ifmod; /* type of if_chain/modem a packet was received by */ int ifmod; /* type of if_chain/modem a packet was received by */
int32_t if_freq_hz;
int32_t if_freq_error;
double pkt_freq_error;
uint16_t payload_crc16_calc; uint16_t payload_crc16_calc;
uint8_t cr; uint8_t cr;
int32_t timestamp_correction; int32_t timestamp_correction;
@ -2065,14 +2068,32 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) {
break; break;
} }
/* Adjust the frequency offset with channel IF frequency error:
When the channel IF frequency has been configured, a precision error may have been introduced
due to the register precision. We calculate this error here, and adjust the returned frequency error
accordingly. */
if_freq_hz = context->if_chain_cfg[p->if_chain].freq_hz; /* The IF frequency set in the registers, is the offset from the zero IF. */
if_freq_error = if_freq_hz - (IF_HZ_TO_REG(if_freq_hz) * 15625 / 32); /* The error corresponds to how many Hz are missing to get to actual 0 IF. */
/* Example to better understand what we get here:
- For a channel set to IF 400000Hz
- The IF frequency register will actually be set to 399902Hz due to its resolution
- This means that the modem, to shift to 0 IF, will apply -399902, instead of -400000.
- This means that the modem will be centered +98hz above the real 0 IF
- As the freq_offset given is supposed to be relative to the 0 IF, we add this resolution error to it */
p->freq_offset += if_freq_error;
/* Get timestamp correction to be applied to count_us */ /* Get timestamp correction to be applied to count_us */
timestamp_correction = timestamp_counter_correction(context, p->bandwidth, p->datarate, p->coderate, pkt.crc_en, pkt.rxbytenb_modem, RX_DFT_PEAK_MODE_AUTO); timestamp_correction = timestamp_counter_correction(context, p->bandwidth, p->datarate, p->coderate, pkt.crc_en, pkt.rxbytenb_modem, RX_DFT_PEAK_MODE_AUTO);
/* Compute fine timestmap for packets coming from the modem optimized for fine timestamping, if CRC is OK */ /* Compute fine timestamp for packets coming from the modem optimized for fine timestamping, if CRC is OK */
p->ftime_received = false; p->ftime_received = false;
p->ftime = 0; p->ftime = 0;
if ((pkt.num_ts_metrics_stored > 0) && (pkt.timing_set == true) && (p->status == STAT_CRC_OK)) { if ((pkt.num_ts_metrics_stored > 0) && (pkt.timing_set == true) && (p->status == STAT_CRC_OK)) {
err = precise_timestamp_calculate(pkt.num_ts_metrics_stored, &pkt.timestamp_avg[0], pkt.timestamp_cnt, pkt.rx_rate_sf, context->if_chain_cfg[p->if_chain].freq_hz, &(p->ftime)); /* The actual packet frequency error compared to the channel frequency, need to compute the ftime */
pkt_freq_error = ((double)(p->freq_hz + p->freq_offset) / (double)(p->freq_hz)) - 1.0;
/* Compute the fine timestamp */
err = precise_timestamp_calculate(pkt.num_ts_metrics_stored, &pkt.timestamp_avg[0], pkt.timestamp_cnt, pkt.rx_rate_sf, context->if_chain_cfg[p->if_chain].freq_hz, pkt_freq_error, &(p->ftime));
if (err == 0) { if (err == 0) {
p->ftime_received = true; p->ftime_received = true;
} }
@ -2691,7 +2712,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut,
DEBUG_MSG("Note: preamble length adjusted to respect minimum FSK preamble size\n"); DEBUG_MSG("Note: preamble length adjusted to respect minimum FSK preamble size\n");
} }
buff[0] = (uint8_t)(pkt_data->preamble >> 8); buff[0] = (uint8_t)(pkt_data->preamble >> 8);
buff[1] = (uint8_t)(pkt_data->preamble >> 8); buff[1] = (uint8_t)(pkt_data->preamble >> 0);
err = lgw_reg_wb(SX1302_REG_TX_TOP_FSK_PREAMBLE_SIZE_MSB_PREAMBLE_SIZE(pkt_data->rf_chain), buff, 2); err = lgw_reg_wb(SX1302_REG_TX_TOP_FSK_PREAMBLE_SIZE_MSB_PREAMBLE_SIZE(pkt_data->rf_chain), buff, 2);
CHECK_ERR(err); CHECK_ERR(err);
@ -2798,8 +2819,6 @@ double sx1302_dc_notch_delay(double if_freq_khz) {
delay = 1.7e-6 * pow(if_freq_khz, 4) + 2.4e-6 * pow(if_freq_khz, 3) - 0.0101 * pow(if_freq_khz, 2) - 0.01275 * if_freq_khz + 10.2922; delay = 1.7e-6 * pow(if_freq_khz, 4) + 2.4e-6 * pow(if_freq_khz, 3) - 0.0101 * pow(if_freq_khz, 2) - 0.01275 * if_freq_khz + 10.2922;
} }
printf("SX1302: DC notch filter delay : %f\n", delay);
/* Number of 32MHz clock cycles */ /* Number of 32MHz clock cycles */
return delay; return delay;
} }

View file

@ -475,7 +475,7 @@ int32_t timestamp_counter_correction(lgw_context_t * context, uint8_t bandwidth,
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics, uint32_t timestamp_cnt, uint8_t sf, int32_t if_freq_hz, uint32_t * result_ftime) { int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics, uint32_t timestamp_cnt, uint8_t sf, int32_t if_freq_hz, double pkt_freq_error, uint32_t * result_ftime) {
int i, x, timestamp_pps_idx, timestamp_pps_idx_next, timestamp_pps_idx_prev; int i, x, timestamp_pps_idx, timestamp_pps_idx_next, timestamp_pps_idx_prev;
int32_t ftime_sum; int32_t ftime_sum;
int32_t ftime[256]; int32_t ftime[256];
@ -504,6 +504,9 @@ int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics
offset_preamble_hdr = 256 * (1 << sf) * (8 + 4 + (((sf == 5) || (sf == 6)) ? 2 : 0)) + offset_preamble_hdr = 256 * (1 << sf) * (8 + 4 + (((sf == 5) || (sf == 6)) ? 2 : 0)) +
256 * ((1 << sf) / 4 - 1); /* 32e6 / 125e3 = 256 */ 256 * ((1 << sf) / 4 - 1); /* 32e6 / 125e3 = 256 */
/* Take the packet frequency error in account in the offset */
offset_preamble_hdr += ((double)offset_preamble_hdr * pkt_freq_error + 0.5);
timestamp_cnt_end_of_preamble = timestamp_cnt - offset_preamble_hdr + 2138; /* 2138 is the number of 32MHz clock cycle offset b/w GW_V2 and SX1303 decimation/filtering group delay */ timestamp_cnt_end_of_preamble = timestamp_cnt - offset_preamble_hdr + 2138; /* 2138 is the number of 32MHz clock cycle offset b/w GW_V2 and SX1303 decimation/filtering group delay */
/* Shift the packet coarse timestamp which is used to get ref PPS counter */ /* Shift the packet coarse timestamp which is used to get ref PPS counter */

Binary file not shown.

View file

@ -26,7 +26,7 @@ more details.
Those programs are included in the project to provide examples on how to use Those programs are included in the project to provide examples on how to use
the HAL library, and to help the system builder test different parts of it. the HAL library, and to help the system builder test different parts of it.
### 2.1. packet_frowarder ### ### 2.1. packet_forwarder ###
The packet forwarder is a program running on the host of a Lora gateway that The packet forwarder is a program running on the host of a Lora gateway that
forwards RF packets receive by the concentrator to a server through a IP/UDP forwards RF packets receive by the concentrator to a server through a IP/UDP
@ -191,6 +191,22 @@ found in the `libtools` directory.
## 7. Changelog ## 7. Changelog
### v2.0.1 ###
> #### Updates
The fine timestamping feature has been fully validated with this release.
> #### Changes
* HAL: Adjusted the freq_offset field of received packets, to take into account
the channel IF resolution error.
* HAL: Refined the fine timestamp offset compared to Gateway v2, by taking into
account the frequency offset of the received packet.
* HAL: Fixed the preamble length for FSK downlinks
* MCU: Removed the binary compiled in debug mode.
* util_spectral_scan: actually use the nb_scan input argument which was ignored.
### v2.0.0 ### ### v2.0.0 ###
> #### New features > #### New features

View file

@ -285,7 +285,7 @@ int main(int argc, char **argv)
/* Launch Spectral Scan on each channels */ /* Launch Spectral Scan on each channels */
for (j = 0; j < nb_channels; j++) { for (j = 0; j < nb_channels; j++) {
x = lgw_spectral_scan_start(freq_hz, 2000); x = lgw_spectral_scan_start(freq_hz, nb_scan);
if (x != 0) { if (x != 0) {
printf("ERROR: spectral scan start failed\n"); printf("ERROR: spectral scan start failed\n");
continue; continue;