loragw_lbt.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2020 Semtech
  8. Description:
  9. LoRa concentrator Listen-Before-Talk functions
  10. License: Revised BSD License, see LICENSE.TXT file include in the project
  11. */
  12. /* -------------------------------------------------------------------------- */
  13. /* --- DEPENDANCIES --------------------------------------------------------- */
  14. /* fix an issue between POSIX and C99 */
  15. #if __STDC_VERSION__ >= 199901L
  16. #define _XOPEN_SOURCE 600
  17. #else
  18. #define _XOPEN_SOURCE 500
  19. #endif
  20. #include <stdio.h> /* printf */
  21. #include <stdlib.h> /* llabs */
  22. #include "loragw_aux.h"
  23. #include "loragw_lbt.h"
  24. #include "loragw_sx1261.h"
  25. #include "loragw_sx1302.h"
  26. #include "loragw_hal.h"
  27. /* -------------------------------------------------------------------------- */
  28. /* --- PRIVATE MACROS ------------------------------------------------------- */
  29. #if DEBUG_LBT == 1
  30. #define DEBUG_MSG(str) fprintf(stdout, str)
  31. #define DEBUG_PRINTF(fmt, args...) fprintf(stdout,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
  32. #else
  33. #define DEBUG_MSG(str)
  34. #define DEBUG_PRINTF(fmt, args...)
  35. #endif
  36. /* -------------------------------------------------------------------------- */
  37. /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
  38. /* As given frequencies have been converted from float to integer, some aliasing
  39. issues can appear, so we can't simply check for equality, but have to take some
  40. margin */
  41. static bool is_equal_freq(uint32_t a, uint32_t b) {
  42. int64_t diff;
  43. int64_t a64 = (int64_t)a;
  44. int64_t b64 = (int64_t)b;
  45. /* Calculate the difference */
  46. diff = llabs(a64 - b64);
  47. /* Check for acceptable diff range */
  48. return ((diff <= 10000) ? true : false);
  49. }
  50. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  51. static int is_lbt_channel(const struct lgw_conf_lbt_s * lbt_context, uint32_t freq_hz, uint8_t bandwidth) {
  52. int i;
  53. int lbt_channel_match = -1;
  54. for (i = 0; i < lbt_context->nb_channel; i++) {
  55. if ((is_equal_freq(freq_hz, lbt_context->channels[i].freq_hz) == true) && (bandwidth == lbt_context->channels[i].bandwidth)) {
  56. DEBUG_PRINTF("LBT: select channel %d (freq:%u Hz, bw:0x%02X)\n", i, lbt_context->channels[i].freq_hz, lbt_context->channels[i].bandwidth);
  57. lbt_channel_match = i;
  58. break;
  59. }
  60. }
  61. /* Return the index of the LBT channel which matched */
  62. return lbt_channel_match;
  63. }
  64. /* -------------------------------------------------------------------------- */
  65. /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
  66. int lgw_lbt_start(const struct lgw_conf_sx1261_s * sx1261_context, const struct lgw_pkt_tx_s * pkt) {
  67. int err;
  68. int lbt_channel_selected;
  69. uint32_t toa_ms;
  70. /* performances variables */
  71. struct timeval tm;
  72. /* Record function start time */
  73. _meas_time_start(&tm);
  74. /* Check if we have a LBT channel for this transmit frequency */
  75. lbt_channel_selected = is_lbt_channel(&(sx1261_context->lbt_conf), pkt->freq_hz, pkt->bandwidth);
  76. if (lbt_channel_selected == -1) {
  77. printf("ERROR: Cannot start LBT - wrong channel\n");
  78. return -1;
  79. }
  80. /* Check if the packet Time On Air exceeds the maximum allowed transmit time on this channel */
  81. /* Channel sensing is checked 1.5ms before the packet departure time, so need to take this into account */
  82. if (sx1261_context->lbt_conf.channels[lbt_channel_selected].transmit_time_ms * 1000 <= 1500) {
  83. printf("ERROR: Cannot start LBT - channel transmit_time_ms must be > 1.5ms\n");
  84. return -1;
  85. }
  86. toa_ms = lgw_time_on_air(pkt);
  87. if ((toa_ms * 1000) > (uint32_t)(sx1261_context->lbt_conf.channels[lbt_channel_selected].transmit_time_ms * 1000 - 1500)) {
  88. printf("ERROR: Cannot start LBT - packet time on air exceeds allowed transmit time (toa:%ums, max:%ums)\n", toa_ms, sx1261_context->lbt_conf.channels[lbt_channel_selected].transmit_time_ms);
  89. return -1;
  90. }
  91. /* Set LBT scan frequency */
  92. err = sx1261_set_rx_params(pkt->freq_hz, pkt->bandwidth);
  93. if (err != 0) {
  94. printf("ERROR: Cannot start LBT - unable to set sx1261 RX parameters\n");
  95. return -1;
  96. }
  97. /* Start LBT */
  98. err = sx1261_lbt_start(sx1261_context->lbt_conf.channels[lbt_channel_selected].scan_time_us, sx1261_context->lbt_conf.rssi_target + sx1261_context->rssi_offset);
  99. if (err != 0) {
  100. printf("ERROR: Cannot start LBT - sx1261 LBT start\n");
  101. return -1;
  102. }
  103. _meas_time_stop(3, tm, __FUNCTION__);
  104. return 0;
  105. }
  106. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  107. int lgw_lbt_tx_status(uint8_t rf_chain, bool * tx_ok) {
  108. int err;
  109. uint8_t status;
  110. bool tx_timeout = false;
  111. struct timeval tm_start;
  112. /* performances variables */
  113. struct timeval tm;
  114. /* Record function start time */
  115. _meas_time_start(&tm);
  116. /* Wait for transmit to be initiated */
  117. /* Bit 0 in status: TX has been initiated on Radio A */
  118. /* Bit 1 in status: TX has been initiated on Radio B */
  119. timeout_start(&tm_start);
  120. do {
  121. /* handle timeout */
  122. if (timeout_check(tm_start, 500) != 0) {
  123. printf("ERROR: %s: TIMEOUT on TX start, not started\n", __FUNCTION__);
  124. tx_timeout = true;
  125. /* we'll still perform the AGC clear status and return an error to upper layer */
  126. break;
  127. }
  128. /* get tx status */
  129. err = sx1302_agc_status(&status);
  130. if (err != 0) {
  131. printf("ERROR: %s: failed to get AGC status\n", __FUNCTION__);
  132. return -1;
  133. }
  134. wait_ms(1);
  135. } while ((status & (1 << rf_chain)) == 0x00);
  136. if (tx_timeout == false) {
  137. /* Check if the packet has been transmitted or blocked by LBT */
  138. /* Bit 6 in status: Radio A is not allowed to transmit */
  139. /* Bit 7 in status: Radio B is not allowed to transmit */
  140. if (TAKE_N_BITS_FROM(status, ((rf_chain == 0) ? 6 : 7), 1) == 0) {
  141. *tx_ok = true;
  142. } else {
  143. *tx_ok = false;
  144. }
  145. }
  146. /* Clear AGC transmit status */
  147. sx1302_agc_mailbox_write(0, 0xFF);
  148. /* Wait for transmit status to be cleared */
  149. timeout_start(&tm_start);
  150. do {
  151. /* handle timeout */
  152. if (timeout_check(tm_start, 500) != 0) {
  153. printf("ERROR: %s: TIMEOUT on TX start (AGC clear status)\n", __FUNCTION__);
  154. tx_timeout = true;
  155. break;
  156. }
  157. /* get tx status */
  158. err = sx1302_agc_status(&status);
  159. if (err != 0) {
  160. printf("ERROR: %s: failed to get AGC status\n", __FUNCTION__);
  161. return -1;
  162. }
  163. wait_ms(1);
  164. } while (status != 0x00);
  165. /* Acknoledge */
  166. sx1302_agc_mailbox_write(0, 0x00);
  167. _meas_time_stop(3, tm, __FUNCTION__);
  168. if (tx_timeout == true) {
  169. return -1;
  170. } else {
  171. return 0;
  172. }
  173. }
  174. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  175. int lgw_lbt_stop(void) {
  176. int err;
  177. /* performances variables */
  178. struct timeval tm;
  179. /* Record function start time */
  180. _meas_time_start(&tm);
  181. err = sx1261_lbt_stop();
  182. if (err != 0) {
  183. printf("ERROR: Cannot stop LBT - failed\n");
  184. return -1;
  185. }
  186. _meas_time_stop(3, tm, __FUNCTION__);
  187. return 0;
  188. }
  189. /* --- EOF ------------------------------------------------------------------ */