loragw_sx1250.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2019 Semtech
  8. Description:
  9. Functions used to handle LoRa concentrator SX1250 radios.
  10. License: Revised BSD License, see LICENSE.TXT file include in the project
  11. */
  12. /* -------------------------------------------------------------------------- */
  13. /* --- DEPENDANCIES --------------------------------------------------------- */
  14. #include <stdint.h> /* C99 types */
  15. #include <stdio.h> /* printf fprintf */
  16. #include "loragw_sx1250.h"
  17. #include "loragw_com.h"
  18. #include "loragw_aux.h"
  19. #include "loragw_reg.h"
  20. #include "loragw_hal.h"
  21. #include "sx1250_com.h"
  22. /* -------------------------------------------------------------------------- */
  23. /* --- PRIVATE MACROS ------------------------------------------------------- */
  24. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  25. #if DEBUG_RAD == 1
  26. #define DEBUG_MSG(str) fprintf(stdout, str)
  27. #define DEBUG_PRINTF(fmt, args...) fprintf(stdout,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
  28. #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_REG_ERROR;}
  29. #else
  30. #define DEBUG_MSG(str)
  31. #define DEBUG_PRINTF(fmt, args...)
  32. #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;}
  33. #endif
  34. /* -------------------------------------------------------------------------- */
  35. /* --- PRIVATE CONSTANTS ---------------------------------------------------- */
  36. /* -------------------------------------------------------------------------- */
  37. /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
  38. int sx1250_reg_w(sx1250_op_code_t op_code, uint8_t *data, uint16_t size, uint8_t rf_chain) {
  39. int com_stat;
  40. /* checking input parameters */
  41. if (rf_chain >= LGW_RF_CHAIN_NB) {
  42. DEBUG_MSG("ERROR: INVALID RF_CHAIN\n");
  43. return LGW_REG_ERROR;
  44. }
  45. com_stat = sx1250_com_w(lgw_com_type(), lgw_com_target(), ((rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB), op_code, data, size);
  46. if (com_stat != LGW_COM_SUCCESS) {
  47. DEBUG_MSG("ERROR: COM ERROR DURING RADIO REGISTER WRITE\n");
  48. return LGW_REG_ERROR;
  49. } else {
  50. return LGW_REG_SUCCESS;
  51. }
  52. }
  53. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  54. int sx1250_reg_r(sx1250_op_code_t op_code, uint8_t *data, uint16_t size, uint8_t rf_chain) {
  55. int com_stat;
  56. /* checking input parameters */
  57. if (rf_chain >= LGW_RF_CHAIN_NB) {
  58. DEBUG_MSG("ERROR: INVALID RF_CHAIN\n");
  59. return LGW_REG_ERROR;
  60. }
  61. com_stat = sx1250_com_r(lgw_com_type(), lgw_com_target(), ((rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB), op_code, data, size);
  62. if (com_stat != LGW_COM_SUCCESS) {
  63. DEBUG_MSG("ERROR: COM ERROR DURING RADIO REGISTER READ\n");
  64. return LGW_REG_ERROR;
  65. } else {
  66. return LGW_REG_SUCCESS;
  67. }
  68. }
  69. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  70. int sx1250_calibrate(uint8_t rf_chain, uint32_t freq_hz) {
  71. int err = LGW_REG_SUCCESS;
  72. uint8_t buff[16];
  73. buff[0] = 0x00;
  74. err |= sx1250_reg_r(GET_STATUS, buff, 1, rf_chain);
  75. /* Run calibration */
  76. if ((freq_hz > 430E6) && (freq_hz < 440E6)) {
  77. buff[0] = 0x6B;
  78. buff[1] = 0x6F;
  79. } else if ((freq_hz > 470E6) && (freq_hz < 510E6)) {
  80. buff[0] = 0x75;
  81. buff[1] = 0x81;
  82. } else if ((freq_hz > 779E6) && (freq_hz < 787E6)) {
  83. buff[0] = 0xC1;
  84. buff[1] = 0xC5;
  85. } else if ((freq_hz > 863E6) && (freq_hz < 870E6)) {
  86. buff[0] = 0xD7;
  87. buff[1] = 0xDB;
  88. } else if ((freq_hz > 902E6) && (freq_hz < 928E6)) {
  89. buff[0] = 0xE1;
  90. buff[1] = 0xE9;
  91. } else {
  92. printf("ERROR: failed to calibrate sx1250 radio, frequency range not supported (%u)\n", freq_hz);
  93. return LGW_REG_ERROR;
  94. }
  95. err |= sx1250_reg_w(CALIBRATE_IMAGE, buff, 2, rf_chain);
  96. /* Wait for calibration to complete */
  97. wait_ms(10);
  98. buff[0] = 0x00;
  99. buff[1] = 0x00;
  100. buff[2] = 0x00;
  101. err |= sx1250_reg_r(GET_DEVICE_ERRORS, buff, 3, rf_chain);
  102. if (TAKE_N_BITS_FROM(buff[2], 4, 1) != 0) {
  103. printf("ERROR: sx1250 Image Calibration Error\n");
  104. return LGW_REG_ERROR;
  105. }
  106. return err;
  107. }
  108. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  109. int sx1250_setup(uint8_t rf_chain, uint32_t freq_hz, bool single_input_mode) {
  110. int32_t freq_reg;
  111. uint8_t buff[16];
  112. int err = LGW_REG_SUCCESS;
  113. /* Set Radio in Standby for calibrations */
  114. buff[0] = (uint8_t)STDBY_RC;
  115. err |= sx1250_reg_w(SET_STANDBY, buff, 1, rf_chain);
  116. wait_ms(10);
  117. /* Get status to check Standby mode has been properly set */
  118. buff[0] = 0x00;
  119. err |= sx1250_reg_r(GET_STATUS, buff, 1, rf_chain);
  120. if ((uint8_t)(TAKE_N_BITS_FROM(buff[0], 4, 3)) != 0x02) {
  121. printf("ERROR: Failed to set SX1250_%u in STANDBY_RC mode\n", rf_chain);
  122. return LGW_REG_ERROR;
  123. }
  124. /* Run all calibrations (TCXO) */
  125. buff[0] = 0x7F;
  126. err |= sx1250_reg_w(CALIBRATE, buff, 1, rf_chain);
  127. wait_ms(10);
  128. /* Set Radio in Standby with XOSC ON */
  129. buff[0] = (uint8_t)STDBY_XOSC;
  130. err |= sx1250_reg_w(SET_STANDBY, buff, 1, rf_chain);
  131. wait_ms(10);
  132. /* Get status to check Standby mode has been properly set */
  133. buff[0] = 0x00;
  134. err |= sx1250_reg_r(GET_STATUS, buff, 1, rf_chain);
  135. if ((uint8_t)(TAKE_N_BITS_FROM(buff[0], 4, 3)) != 0x03) {
  136. printf("ERROR: Failed to set SX1250_%u in STANDBY_XOSC mode\n", rf_chain);
  137. return LGW_REG_ERROR;
  138. }
  139. /* Set Bitrate to maximum (to lower TX to FS switch time) */
  140. buff[0] = 0x06;
  141. buff[1] = 0xA1;
  142. buff[2] = 0x01;
  143. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain);
  144. buff[0] = 0x06;
  145. buff[1] = 0xA2;
  146. buff[2] = 0x00;
  147. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain);
  148. buff[0] = 0x06;
  149. buff[1] = 0xA3;
  150. buff[2] = 0x00;
  151. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain);
  152. /* Configure DIO for Rx */
  153. buff[0] = 0x05;
  154. buff[1] = 0x82;
  155. buff[2] = 0x00;
  156. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain); /* Drive strength to min */
  157. buff[0] = 0x05;
  158. buff[1] = 0x83;
  159. buff[2] = 0x00;
  160. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain); /* Input enable, all disabled */
  161. buff[0] = 0x05;
  162. buff[1] = 0x84;
  163. buff[2] = 0x00;
  164. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain); /* No pull up */
  165. buff[0] = 0x05;
  166. buff[1] = 0x85;
  167. buff[2] = 0x00;
  168. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain); /* No pull down */
  169. buff[0] = 0x05;
  170. buff[1] = 0x80;
  171. buff[2] = 0x00;
  172. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain); /* Output enable, all enabled */
  173. /* Set fix gain (??) */
  174. buff[0] = 0x08;
  175. buff[1] = 0xB6;
  176. buff[2] = 0x2A;
  177. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain);
  178. /* Set frequency */
  179. freq_reg = SX1250_FREQ_TO_REG(freq_hz);
  180. buff[0] = (uint8_t)(freq_reg >> 24);
  181. buff[1] = (uint8_t)(freq_reg >> 16);
  182. buff[2] = (uint8_t)(freq_reg >> 8);
  183. buff[3] = (uint8_t)(freq_reg >> 0);
  184. err |= sx1250_reg_w(SET_RF_FREQUENCY, buff, 4, rf_chain);
  185. /* Set frequency offset to 0 */
  186. buff[0] = 0x08;
  187. buff[1] = 0x8F;
  188. buff[2] = 0x00;
  189. buff[3] = 0x00;
  190. buff[4] = 0x00;
  191. err |= sx1250_reg_w(WRITE_REGISTER, buff, 5, rf_chain);
  192. /* Set Radio in Rx mode, necessary to give a clock to SX1302 */
  193. buff[0] = 0xFF;
  194. buff[1] = 0xFF;
  195. buff[2] = 0xFF;
  196. err |= sx1250_reg_w(SET_RX, buff, 3, rf_chain); /* Rx Continuous */
  197. /* Select single input or differential input mode */
  198. if (single_input_mode == true) {
  199. printf("INFO: Configuring SX1250_%u in single input mode\n", rf_chain);
  200. buff[0] = 0x08;
  201. buff[1] = 0xE2;
  202. buff[2] = 0x0D;
  203. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain);
  204. }
  205. buff[0] = 0x05;
  206. buff[1] = 0x87;
  207. buff[2] = 0x0B;
  208. err |= sx1250_reg_w(WRITE_REGISTER, buff, 3, rf_chain); /* FPGA_MODE_RX */
  209. /* Check if something went wrong */
  210. if (err != LGW_REG_SUCCESS) {
  211. printf("ERROR: failed to setup SX1250_%u radio\n", rf_chain);
  212. return LGW_REG_ERROR;
  213. }
  214. return LGW_REG_SUCCESS;
  215. }
  216. /* --- EOF ------------------------------------------------------------------ */