loragw_hal.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2019 Semtech
  8. Description:
  9. LoRa concentrator Hardware Abstraction Layer
  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. #define _GNU_SOURCE /* needed for qsort_r to be defined */
  21. #include <stdlib.h> /* qsort_r */
  22. #include <stdint.h> /* C99 types */
  23. #include <stdbool.h> /* bool type */
  24. #include <stdio.h> /* printf fprintf */
  25. #include <string.h> /* memcpy */
  26. #include <unistd.h> /* symlink, unlink */
  27. #include <inttypes.h>
  28. #include "loragw_reg.h"
  29. #include "loragw_hal.h"
  30. #include "loragw_aux.h"
  31. #include "loragw_com.h"
  32. #include "loragw_i2c.h"
  33. #include "loragw_lbt.h"
  34. #include "loragw_sx1250.h"
  35. #include "loragw_sx125x.h"
  36. #include "loragw_sx1261.h"
  37. #include "loragw_sx1302.h"
  38. #include "loragw_sx1302_timestamp.h"
  39. #include "loragw_stts751.h"
  40. #include "loragw_ad5338r.h"
  41. #include "loragw_debug.h"
  42. /* -------------------------------------------------------------------------- */
  43. /* --- DEBUG CONSTANTS ------------------------------------------------------ */
  44. #define HAL_DEBUG_FILE_LOG 0
  45. /* -------------------------------------------------------------------------- */
  46. /* --- PRIVATE MACROS ------------------------------------------------------- */
  47. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  48. #if DEBUG_HAL == 1
  49. #define DEBUG_MSG(str) fprintf(stdout, str)
  50. #define DEBUG_PRINTF(fmt, args...) fprintf(stdout,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
  51. #define DEBUG_ARRAY(a,b,c) for(a=0;a<b;++a) fprintf(stdout,"%x.",c[a]);fprintf(stdout,"end\n")
  52. #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_HAL_ERROR;}
  53. #else
  54. #define DEBUG_MSG(str)
  55. #define DEBUG_PRINTF(fmt, args...)
  56. #define DEBUG_ARRAY(a,b,c) for(a=0;a!=0;){}
  57. #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;}
  58. #endif
  59. #define TRACE() fprintf(stderr, "@ %s %d\n", __FUNCTION__, __LINE__);
  60. #define CONTEXT_STARTED lgw_context.is_started
  61. #define CONTEXT_COM_TYPE lgw_context.board_cfg.com_type
  62. #define CONTEXT_COM_PATH lgw_context.board_cfg.com_path
  63. #define CONTEXT_LWAN_PUBLIC lgw_context.board_cfg.lorawan_public
  64. #define CONTEXT_BOARD lgw_context.board_cfg
  65. #define CONTEXT_RF_CHAIN lgw_context.rf_chain_cfg
  66. #define CONTEXT_IF_CHAIN lgw_context.if_chain_cfg
  67. #define CONTEXT_DEMOD lgw_context.demod_cfg
  68. #define CONTEXT_LORA_SERVICE lgw_context.lora_service_cfg
  69. #define CONTEXT_FSK lgw_context.fsk_cfg
  70. #define CONTEXT_TX_GAIN_LUT lgw_context.tx_gain_lut
  71. #define CONTEXT_FINE_TIMESTAMP lgw_context.ftime_cfg
  72. #define CONTEXT_SX1261 lgw_context.sx1261_cfg
  73. #define CONTEXT_DEBUG lgw_context.debug_cfg
  74. /* -------------------------------------------------------------------------- */
  75. /* --- PRIVATE CONSTANTS & TYPES -------------------------------------------- */
  76. #define FW_VERSION_AGC_SX1250 10 /* Expected version of AGC firmware for sx1250 based gateway */
  77. /* v10 is same as v6 with improved channel check time for LBT */
  78. #define FW_VERSION_AGC_SX125X 6 /* Expected version of AGC firmware for sx1255/sx1257 based gateway */
  79. #define FW_VERSION_ARB 2 /* Expected version of arbiter firmware */
  80. /* Useful bandwidth of SX125x radios to consider depending on channel bandwidth */
  81. /* Note: the below values come from lab measurements. For any question, please contact Semtech support */
  82. #define LGW_RF_RX_BANDWIDTH_125KHZ 1600000 /* for 125KHz channels */
  83. #define LGW_RF_RX_BANDWIDTH_250KHZ 1600000 /* for 250KHz channels */
  84. #define LGW_RF_RX_BANDWIDTH_500KHZ 1600000 /* for 500KHz channels */
  85. #define LGW_RF_RX_FREQ_MIN 100E6
  86. #define LGW_RF_RX_FREQ_MAX 1E9
  87. /* Version string, used to identify the library version/options once compiled */
  88. const char lgw_version_string[] = "Version: " LIBLORAGW_VERSION ";";
  89. /* -------------------------------------------------------------------------- */
  90. /* --- PRIVATE VARIABLES ---------------------------------------------------- */
  91. #include "arb_fw.var" /* text_arb_sx1302_13_Nov_3 */
  92. #include "agc_fw_sx1250.var" /* text_agc_sx1250_05_Juillet_2019_3 */
  93. #include "agc_fw_sx1257.var" /* text_agc_sx1257_19_Nov_1 */
  94. /*
  95. The following static variable holds the gateway configuration provided by the
  96. user that need to be propagated in the drivers.
  97. Parameters validity and coherency is verified by the _setconf functions and
  98. the _start and _send functions assume they are valid.
  99. */
  100. static lgw_context_t lgw_context = {
  101. .is_started = false,
  102. .board_cfg.com_type = LGW_COM_SPI,
  103. .board_cfg.com_path = "/dev/spidev0.0",
  104. .board_cfg.lorawan_public = true,
  105. .board_cfg.clksrc = 0,
  106. .board_cfg.full_duplex = false,//i2c设备 PA放大
  107. .rf_chain_cfg = {{0}},
  108. .if_chain_cfg = {{0}},
  109. .demod_cfg = {
  110. .multisf_datarate = LGW_MULTI_SF_EN
  111. },
  112. .lora_service_cfg = {
  113. .enable = 0, /* not used, handled by if_chain_cfg */
  114. .rf_chain = 0, /* not used, handled by if_chain_cfg */
  115. .freq_hz = 0, /* not used, handled by if_chain_cfg */
  116. .bandwidth = BW_250KHZ,
  117. .datarate = DR_LORA_SF7,
  118. .implicit_hdr = false,
  119. .implicit_payload_length = 0,
  120. .implicit_crc_en = 0,
  121. .implicit_coderate = 0
  122. },
  123. .fsk_cfg = {
  124. .enable = 0, /* not used, handled by if_chain_cfg */
  125. .rf_chain = 0, /* not used, handled by if_chain_cfg */
  126. .freq_hz = 0, /* not used, handled by if_chain_cfg */
  127. .bandwidth = BW_125KHZ,
  128. .datarate = 50000,
  129. .sync_word_size = 3,
  130. .sync_word = 0xC194C1
  131. },
  132. .tx_gain_lut = {
  133. {
  134. .size = 1,
  135. .lut[0] = {
  136. .rf_power = 14,
  137. .dig_gain = 0,
  138. .pa_gain = 2,
  139. .dac_gain = 3,
  140. .mix_gain = 10,
  141. .offset_i = 0,
  142. .offset_q = 0,
  143. .pwr_idx = 0
  144. }
  145. },{
  146. .size = 1,
  147. .lut[0] = {
  148. .rf_power = 14,
  149. .dig_gain = 0,
  150. .pa_gain = 2,
  151. .dac_gain = 3,
  152. .mix_gain = 10,
  153. .offset_i = 0,
  154. .offset_q = 0,
  155. .pwr_idx = 0
  156. }
  157. }
  158. },
  159. .ftime_cfg = {
  160. .enable = false,
  161. .mode = LGW_FTIME_MODE_ALL_SF
  162. },
  163. .sx1261_cfg = {
  164. .enable = false,
  165. .spi_path = "/dev/spidev0.1",
  166. .rssi_offset = 0,
  167. .lbt_conf = {
  168. .rssi_target = 0,
  169. .nb_channel = 0,
  170. .channels = {{ 0 }}
  171. }
  172. },
  173. .debug_cfg = {
  174. .nb_ref_payload = 0,
  175. .log_file_name = "loragw_hal.log"
  176. }
  177. };
  178. /* File handle to write debug logs */
  179. FILE * log_file = NULL;
  180. /* I2C temperature sensor handles */
  181. static int ts_fd = -1;
  182. static uint8_t ts_addr = 0xFF;
  183. /* I2C AD5338 handles */
  184. static int ad_fd = -1;
  185. /* -------------------------------------------------------------------------- */
  186. /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
  187. int32_t lgw_sf_getval(int x);
  188. int32_t lgw_bw_getval(int x);
  189. static bool is_same_pkt(struct lgw_pkt_rx_s *p1, struct lgw_pkt_rx_s *p2);
  190. static int remove_pkt(struct lgw_pkt_rx_s * p, uint8_t * nb_pkt, uint8_t pkt_index);
  191. static int merge_packets(struct lgw_pkt_rx_s * p, uint8_t * nb_pkt);
  192. /* -------------------------------------------------------------------------- */
  193. /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
  194. int32_t lgw_bw_getval(int x) {
  195. switch (x) {
  196. case BW_500KHZ: return 500000;
  197. case BW_250KHZ: return 250000;
  198. case BW_125KHZ: return 125000;
  199. default: return -1;
  200. }
  201. }
  202. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  203. int32_t lgw_sf_getval(int x) {
  204. switch (x) {
  205. case DR_LORA_SF5: return 5;
  206. case DR_LORA_SF6: return 6;
  207. case DR_LORA_SF7: return 7;
  208. case DR_LORA_SF8: return 8;
  209. case DR_LORA_SF9: return 9;
  210. case DR_LORA_SF10: return 10;
  211. case DR_LORA_SF11: return 11;
  212. case DR_LORA_SF12: return 12;
  213. default: return -1;
  214. }
  215. }
  216. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  217. static bool is_same_pkt(struct lgw_pkt_rx_s *p1, struct lgw_pkt_rx_s *p2) {
  218. if ((p1 != NULL) && (p2 != NULL)) {
  219. /* Criterias to determine if packets are identical:
  220. -- count_us should be equal or can have up to 24µs of difference (3 samples)
  221. -- channel should be same
  222. -- datarate should be same
  223. -- payload should be same
  224. */
  225. if ((abs(p1->count_us - p2->count_us) <= 24) &&
  226. (p1->if_chain == p2->if_chain) &&
  227. (p1->datarate == p2->datarate) &&
  228. (p1->size == p2->size) &&
  229. (memcmp(p1->payload, p2->payload, p1->size) == 0)) {
  230. return true;
  231. }
  232. }
  233. return false;
  234. }
  235. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  236. static int remove_pkt(struct lgw_pkt_rx_s * p, uint8_t * nb_pkt, uint8_t pkt_index) {
  237. /* Check input parameters */
  238. CHECK_NULL(p);
  239. CHECK_NULL(nb_pkt);
  240. if (pkt_index > ((*nb_pkt) - 1)) {
  241. printf("ERROR: failed to remove packet index %u\n", pkt_index);
  242. return -1;
  243. }
  244. /* Remove pkt from array, by replacing it with last packet of array */
  245. if (pkt_index == ((*nb_pkt) - 1)) {
  246. /* If we remove last element, just decrement nb packet counter */
  247. /* Do nothing */
  248. } else {
  249. /* Copy last packet onto the packet to be removed */
  250. memcpy(p + pkt_index, p + (*nb_pkt) - 1, sizeof(struct lgw_pkt_rx_s));
  251. }
  252. *nb_pkt -= 1;
  253. return 0;
  254. }
  255. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  256. int compare_pkt_tmst(const void *a, const void *b, void *arg)
  257. {
  258. struct lgw_pkt_rx_s *p = (struct lgw_pkt_rx_s *)a;
  259. struct lgw_pkt_rx_s *q = (struct lgw_pkt_rx_s *)b;
  260. int *counter = (int *)arg;
  261. int p_count, q_count;
  262. p_count = p->count_us;
  263. q_count = q->count_us;
  264. if (p_count > q_count) {
  265. *counter = *counter + 1;
  266. }
  267. return (p_count - q_count);
  268. }
  269. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  270. static int merge_packets(struct lgw_pkt_rx_s * p, uint8_t * nb_pkt) {
  271. uint8_t cpt;
  272. int j, k, pkt_dup_idx, x;
  273. #if DEBUG_HAL == 1
  274. int pkt_idx;
  275. #endif
  276. bool dup_restart = false;
  277. int counter_qsort_swap = 0;
  278. /* Check input parameters */
  279. CHECK_NULL(p);
  280. CHECK_NULL(nb_pkt);
  281. /* Init number of packets in array before merge */
  282. cpt = *nb_pkt;
  283. /* --------------------------------------------- */
  284. /* ---------- For Debug only - START ----------- */
  285. if (cpt > 0) {
  286. DEBUG_MSG("<----- Searching for DUPLICATEs ------\n");
  287. }
  288. for (j = 0; j < cpt; j++) {
  289. DEBUG_PRINTF(" %d: tmst=%u SF=%u CRC_status=%d freq=%u chan=%u", j, p[j].count_us, p[j].datarate, p[j].status, p[j].freq_hz, p[j].if_chain);
  290. if (p[j].ftime_received == true) {
  291. DEBUG_PRINTF(" ftime=%u\n", p[j].ftime);
  292. } else {
  293. DEBUG_MSG (" ftime=NONE\n");
  294. }
  295. }
  296. /* ---------- For Debug only - END ------------- */
  297. /* --------------------------------------------- */
  298. /* Remove duplicates */
  299. j = 0;
  300. while (j < cpt) {
  301. for (k = (j+1); k < cpt; k++) {
  302. /* Searching for duplicated packets:
  303. -- count_us should be equal or can have up to 24µs of difference (3 samples)
  304. -- channel should be same
  305. -- datarate should be same
  306. -- payload should be same
  307. */
  308. if (is_same_pkt( &p[j], &p[k])) {
  309. /* We keep the packet which has CRC checked */
  310. if ((p[j].status == STAT_CRC_OK) && (p[k].status == STAT_CRC_BAD)) {
  311. pkt_dup_idx = k;
  312. #if DEBUG_HAL == 1
  313. pkt_idx = j;
  314. #endif
  315. } else if ((p[j].status == STAT_CRC_BAD) && (p[k].status == STAT_CRC_OK)) {
  316. pkt_dup_idx = j;
  317. #if DEBUG_HAL == 1
  318. pkt_idx = k;
  319. #endif
  320. } else {
  321. /* we keep the packet which has a fine timestamp */
  322. if (p[j].ftime_received == true) {
  323. pkt_dup_idx = k;
  324. #if DEBUG_HAL == 1
  325. pkt_idx = j;
  326. #endif
  327. } else {
  328. pkt_dup_idx = j;
  329. #if DEBUG_HAL == 1
  330. pkt_idx = k;
  331. #endif
  332. }
  333. /* sanity check */
  334. if (((p[j].ftime_received == true) && (p[k].ftime_received == true)) ||
  335. ((p[j].ftime_received == false) && (p[k].ftime_received == false))) {
  336. DEBUG_MSG("WARNING: both duplicates have fine timestamps, or none has ? TBC\n");
  337. }
  338. }
  339. /* pkt_dup_idx contains the index to be deleted */
  340. DEBUG_PRINTF("duplicate found %d:%d, deleting %d\n", pkt_idx, pkt_dup_idx, pkt_dup_idx);
  341. /* Remove duplicated packet from packet array */
  342. x = remove_pkt(p, &cpt, pkt_dup_idx);
  343. if (x != 0) {
  344. printf("ERROR: failed to remove packet from array (%d)\n", x);
  345. }
  346. dup_restart = true;
  347. break;
  348. }
  349. }
  350. if (dup_restart == true) {
  351. /* Duplicate found, restart searching for duplicate from first element */
  352. j = 0;
  353. dup_restart = false;
  354. #if 0
  355. printf( "restarting search for duplicate\n" ); /* Too verbose */
  356. #endif
  357. } else {
  358. /* No duplicate found, continue... */
  359. j += 1;
  360. #if 0
  361. printf( "no duplicate found\n" ); /* Too verbose */
  362. #endif
  363. }
  364. }
  365. /* Sort the packet array by ascending counter_us value */
  366. qsort_r(p, cpt, sizeof(p[0]), compare_pkt_tmst, &counter_qsort_swap);
  367. DEBUG_PRINTF("%d elements swapped during sorting...\n", counter_qsort_swap);
  368. /* --------------------------------------------- */
  369. /* ---------- For Debug only - START ----------- */
  370. if (cpt > 0) {
  371. DEBUG_MSG("--\n");
  372. }
  373. for (j = 0; j < cpt; j++) {
  374. DEBUG_PRINTF(" %d: tmst=%u SF=%d CRC_status=%d freq=%u chan=%u", j, p[j].count_us, p[j].datarate, p[j].status, p[j].freq_hz, p[j].if_chain);
  375. if (p[j].ftime_received == true) {
  376. DEBUG_PRINTF(" ftime=%u\n", p[j].ftime);
  377. } else {
  378. DEBUG_MSG (" ftime=NONE\n");
  379. }
  380. }
  381. if (cpt > 0) {
  382. DEBUG_MSG( " ------------------------------------>\n\n" );
  383. }
  384. /* ---------- For Debug only - END ------------- */
  385. /* --------------------------------------------- */
  386. /* Update number of packets contained in packet array */
  387. *nb_pkt = cpt;
  388. return 0;
  389. }
  390. /* -------------------------------------------------------------------------- */
  391. /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
  392. int lgw_board_setconf(struct lgw_conf_board_s * conf) {
  393. CHECK_NULL(conf);
  394. /* check if the concentrator is running */
  395. if (CONTEXT_STARTED == true) {
  396. DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n");
  397. return LGW_HAL_ERROR;
  398. }
  399. /* Check input parameters */
  400. if ((conf->com_type != LGW_COM_SPI) && (conf->com_type != LGW_COM_USB)) {
  401. DEBUG_MSG("ERROR: WRONG COM TYPE\n");
  402. return LGW_HAL_ERROR;
  403. }
  404. /* set internal config according to parameters */
  405. CONTEXT_LWAN_PUBLIC = conf->lorawan_public;
  406. CONTEXT_BOARD.clksrc = conf->clksrc;
  407. CONTEXT_BOARD.full_duplex = conf->full_duplex;
  408. CONTEXT_COM_TYPE = conf->com_type;
  409. strncpy(CONTEXT_COM_PATH, conf->com_path, sizeof CONTEXT_COM_PATH);
  410. CONTEXT_COM_PATH[sizeof CONTEXT_COM_PATH - 1] = '\0'; /* ensure string termination */
  411. DEBUG_PRINTF("Note: board configuration: com_type: %s, com_path: %s, lorawan_public:%d, clksrc:%d, full_duplex:%d\n", (CONTEXT_COM_TYPE == LGW_COM_SPI) ? "SPI" : "USB",
  412. CONTEXT_COM_PATH,
  413. CONTEXT_LWAN_PUBLIC,
  414. CONTEXT_BOARD.clksrc,
  415. CONTEXT_BOARD.full_duplex);
  416. return LGW_HAL_SUCCESS;
  417. }
  418. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  419. int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s * conf) {
  420. CHECK_NULL(conf);
  421. /* check if the concentrator is running */
  422. if (CONTEXT_STARTED == true) {
  423. DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n");
  424. return LGW_HAL_ERROR;
  425. }
  426. if (conf->enable == false) {
  427. /* nothing to do */
  428. DEBUG_PRINTF("Note: rf_chain %d disabled\n", rf_chain);
  429. return LGW_HAL_SUCCESS;
  430. }
  431. /* check input range (segfault prevention) */
  432. if (rf_chain >= LGW_RF_CHAIN_NB) {
  433. DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n");
  434. return LGW_HAL_ERROR;
  435. }
  436. /* check if radio type is supported */
  437. if ((conf->type != LGW_RADIO_TYPE_SX1255) && (conf->type != LGW_RADIO_TYPE_SX1257) && (conf->type != LGW_RADIO_TYPE_SX1250)) {
  438. DEBUG_PRINTF("ERROR: NOT A VALID RADIO TYPE (%d)\n", conf->type);
  439. return LGW_HAL_ERROR;
  440. }
  441. /* check if the radio central frequency is valid */
  442. if ((conf->freq_hz < LGW_RF_RX_FREQ_MIN) || (conf->freq_hz > LGW_RF_RX_FREQ_MAX)) {
  443. DEBUG_PRINTF("ERROR: NOT A VALID RADIO CENTER FREQUENCY, PLEASE CHECK IF IT HAS BEEN GIVEN IN HZ (%u)\n", conf->freq_hz);
  444. return LGW_HAL_ERROR;
  445. }
  446. /* set internal config according to parameters */
  447. CONTEXT_RF_CHAIN[rf_chain].enable = conf->enable;
  448. CONTEXT_RF_CHAIN[rf_chain].freq_hz = conf->freq_hz;
  449. CONTEXT_RF_CHAIN[rf_chain].rssi_offset = conf->rssi_offset;
  450. CONTEXT_RF_CHAIN[rf_chain].rssi_tcomp.coeff_a = conf->rssi_tcomp.coeff_a;
  451. CONTEXT_RF_CHAIN[rf_chain].rssi_tcomp.coeff_b = conf->rssi_tcomp.coeff_b;
  452. CONTEXT_RF_CHAIN[rf_chain].rssi_tcomp.coeff_c = conf->rssi_tcomp.coeff_c;
  453. CONTEXT_RF_CHAIN[rf_chain].rssi_tcomp.coeff_d = conf->rssi_tcomp.coeff_d;
  454. CONTEXT_RF_CHAIN[rf_chain].rssi_tcomp.coeff_e = conf->rssi_tcomp.coeff_e;
  455. CONTEXT_RF_CHAIN[rf_chain].type = conf->type;
  456. CONTEXT_RF_CHAIN[rf_chain].tx_enable = conf->tx_enable;
  457. CONTEXT_RF_CHAIN[rf_chain].single_input_mode = conf->single_input_mode;
  458. DEBUG_PRINTF("Note: rf_chain %d configuration; en:%d freq:%d rssi_offset:%f radio_type:%d tx_enable:%d single_input_mode:%d\n", rf_chain,
  459. CONTEXT_RF_CHAIN[rf_chain].enable,
  460. CONTEXT_RF_CHAIN[rf_chain].freq_hz,
  461. CONTEXT_RF_CHAIN[rf_chain].rssi_offset,
  462. CONTEXT_RF_CHAIN[rf_chain].type,
  463. CONTEXT_RF_CHAIN[rf_chain].tx_enable,
  464. CONTEXT_RF_CHAIN[rf_chain].single_input_mode);
  465. return LGW_HAL_SUCCESS;
  466. }
  467. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  468. int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) {
  469. int32_t bw_hz;
  470. uint32_t rf_rx_bandwidth;
  471. CHECK_NULL(conf);
  472. /* check if the concentrator is running */
  473. if (CONTEXT_STARTED == true) {
  474. DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n");
  475. return LGW_HAL_ERROR;
  476. }
  477. /* check input range (segfault prevention) */
  478. if (if_chain >= LGW_IF_CHAIN_NB) {
  479. DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain);
  480. return LGW_HAL_ERROR;
  481. }
  482. /* if chain is disabled, don't care about most parameters */
  483. if (conf->enable == false) {
  484. CONTEXT_IF_CHAIN[if_chain].enable = false;
  485. CONTEXT_IF_CHAIN[if_chain].freq_hz = 0;
  486. DEBUG_PRINTF("Note: if_chain %d disabled\n", if_chain);
  487. return LGW_HAL_SUCCESS;
  488. }
  489. /* check 'general' parameters */
  490. if (sx1302_get_ifmod_config(if_chain) == IF_UNDEFINED) {
  491. DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain);
  492. }
  493. if (conf->rf_chain >= LGW_RF_CHAIN_NB) {
  494. DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n");
  495. return LGW_HAL_ERROR;
  496. }
  497. /* check if IF frequency is optimal based on channel and radio bandwidths */
  498. switch (conf->bandwidth) {
  499. case BW_250KHZ:
  500. rf_rx_bandwidth = LGW_RF_RX_BANDWIDTH_250KHZ; /* radio bandwidth */
  501. break;
  502. case BW_500KHZ:
  503. rf_rx_bandwidth = LGW_RF_RX_BANDWIDTH_500KHZ; /* radio bandwidth */
  504. break;
  505. default:
  506. /* For 125KHz and below */
  507. rf_rx_bandwidth = LGW_RF_RX_BANDWIDTH_125KHZ; /* radio bandwidth */
  508. break;
  509. }
  510. bw_hz = lgw_bw_getval(conf->bandwidth); /* channel bandwidth */
  511. if ((conf->freq_hz + ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) > ((int32_t)rf_rx_bandwidth/2)) {
  512. DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf->freq_hz);
  513. return LGW_HAL_ERROR;
  514. } else if ((conf->freq_hz - ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) < -((int32_t)rf_rx_bandwidth/2)) {
  515. DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf->freq_hz);
  516. return LGW_HAL_ERROR;
  517. }
  518. /* check parameters according to the type of IF chain + modem,
  519. fill default if necessary, and commit configuration if everything is OK */
  520. switch (sx1302_get_ifmod_config(if_chain)) {
  521. case IF_LORA_STD:
  522. /* fill default parameters if needed */
  523. if (conf->bandwidth == BW_UNDEFINED) {
  524. conf->bandwidth = BW_250KHZ;
  525. }
  526. if (conf->datarate == DR_UNDEFINED) {
  527. conf->datarate = DR_LORA_SF7;
  528. }
  529. /* check BW & DR */
  530. if (!IS_LORA_BW(conf->bandwidth)) {
  531. DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n");
  532. return LGW_HAL_ERROR;
  533. }
  534. if (!IS_LORA_DR(conf->datarate)) {
  535. DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n");
  536. return LGW_HAL_ERROR;
  537. }
  538. /* set internal configuration */
  539. CONTEXT_IF_CHAIN[if_chain].enable = conf->enable;
  540. CONTEXT_IF_CHAIN[if_chain].rf_chain = conf->rf_chain;
  541. CONTEXT_IF_CHAIN[if_chain].freq_hz = conf->freq_hz;
  542. CONTEXT_LORA_SERVICE.bandwidth = conf->bandwidth;
  543. CONTEXT_LORA_SERVICE.datarate = conf->datarate;
  544. CONTEXT_LORA_SERVICE.implicit_hdr = conf->implicit_hdr;
  545. CONTEXT_LORA_SERVICE.implicit_payload_length = conf->implicit_payload_length;
  546. CONTEXT_LORA_SERVICE.implicit_crc_en = conf->implicit_crc_en;
  547. CONTEXT_LORA_SERVICE.implicit_coderate = conf->implicit_coderate;
  548. DEBUG_PRINTF("Note: LoRa 'std' if_chain %d configuration; en:%d freq:%d bw:%d dr:%d\n", if_chain,
  549. CONTEXT_IF_CHAIN[if_chain].enable,
  550. CONTEXT_IF_CHAIN[if_chain].freq_hz,
  551. CONTEXT_LORA_SERVICE.bandwidth,
  552. CONTEXT_LORA_SERVICE.datarate);
  553. break;
  554. case IF_LORA_MULTI:
  555. /* fill default parameters if needed */
  556. if (conf->bandwidth == BW_UNDEFINED) {
  557. conf->bandwidth = BW_125KHZ;
  558. }
  559. if (conf->datarate == DR_UNDEFINED) {
  560. conf->datarate = DR_LORA_SF7;
  561. }
  562. /* check BW & DR */
  563. if (conf->bandwidth != BW_125KHZ) {
  564. DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n");
  565. return LGW_HAL_ERROR;
  566. }
  567. if (!IS_LORA_DR(conf->datarate)) {
  568. DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n");
  569. return LGW_HAL_ERROR;
  570. }
  571. /* set internal configuration */
  572. CONTEXT_IF_CHAIN[if_chain].enable = conf->enable;
  573. CONTEXT_IF_CHAIN[if_chain].rf_chain = conf->rf_chain;
  574. CONTEXT_IF_CHAIN[if_chain].freq_hz = conf->freq_hz;
  575. DEBUG_PRINTF("Note: LoRa 'multi' if_chain %d configuration; en:%d freq:%d\n", if_chain,
  576. CONTEXT_IF_CHAIN[if_chain].enable,
  577. CONTEXT_IF_CHAIN[if_chain].freq_hz);
  578. break;
  579. case IF_FSK_STD:
  580. /* fill default parameters if needed */
  581. if (conf->bandwidth == BW_UNDEFINED) {
  582. conf->bandwidth = BW_250KHZ;
  583. }
  584. if (conf->datarate == DR_UNDEFINED) {
  585. conf->datarate = 64000; /* default datarate */
  586. }
  587. /* check BW & DR */
  588. if(!IS_FSK_BW(conf->bandwidth)) {
  589. DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n");
  590. return LGW_HAL_ERROR;
  591. }
  592. if(!IS_FSK_DR(conf->datarate)) {
  593. DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n");
  594. return LGW_HAL_ERROR;
  595. }
  596. /* set internal configuration */
  597. CONTEXT_IF_CHAIN[if_chain].enable = conf->enable;
  598. CONTEXT_IF_CHAIN[if_chain].rf_chain = conf->rf_chain;
  599. CONTEXT_IF_CHAIN[if_chain].freq_hz = conf->freq_hz;
  600. CONTEXT_FSK.bandwidth = conf->bandwidth;
  601. CONTEXT_FSK.datarate = conf->datarate;
  602. if (conf->sync_word > 0) {
  603. CONTEXT_FSK.sync_word_size = conf->sync_word_size;
  604. CONTEXT_FSK.sync_word = conf->sync_word;
  605. }
  606. 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,
  607. CONTEXT_IF_CHAIN[if_chain].enable,
  608. CONTEXT_IF_CHAIN[if_chain].freq_hz,
  609. CONTEXT_FSK.bandwidth,
  610. CONTEXT_FSK.datarate,
  611. LGW_XTAL_FREQU/(LGW_XTAL_FREQU/CONTEXT_FSK.datarate),
  612. 2*CONTEXT_FSK.sync_word_size,
  613. CONTEXT_FSK.sync_word);
  614. break;
  615. default:
  616. DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain);
  617. return LGW_HAL_ERROR;
  618. }
  619. return LGW_HAL_SUCCESS;
  620. }
  621. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  622. int lgw_demod_setconf(struct lgw_conf_demod_s * conf) {
  623. CHECK_NULL(conf);
  624. CONTEXT_DEMOD.multisf_datarate = conf->multisf_datarate;
  625. return LGW_HAL_SUCCESS;
  626. }
  627. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  628. int lgw_txgain_setconf(uint8_t rf_chain, struct lgw_tx_gain_lut_s * conf) {
  629. int i;
  630. CHECK_NULL(conf);
  631. /* Check LUT size */
  632. if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) {
  633. DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX);
  634. return LGW_HAL_ERROR;
  635. }
  636. CONTEXT_TX_GAIN_LUT[rf_chain].size = conf->size;
  637. for (i = 0; i < CONTEXT_TX_GAIN_LUT[rf_chain].size; i++) {
  638. /* Check gain range */
  639. if (conf->lut[i].dig_gain > 3) {
  640. DEBUG_MSG("ERROR: TX gain LUT: SX1302 digital gain must be between 0 and 3\n");
  641. return LGW_HAL_ERROR;
  642. }
  643. if (conf->lut[i].dac_gain > 3) {
  644. DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains must not exceed 3\n");
  645. return LGW_HAL_ERROR;
  646. }
  647. if ((conf->lut[i].mix_gain < 5) || (conf->lut[i].mix_gain > 15)) {
  648. DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gain must be betwen [5..15]\n");
  649. return LGW_HAL_ERROR;
  650. }
  651. if (conf->lut[i].pa_gain > 3) {
  652. DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n");
  653. return LGW_HAL_ERROR;
  654. }
  655. if (conf->lut[i].pwr_idx > 22) {
  656. DEBUG_MSG("ERROR: TX gain LUT: SX1250 power index must not exceed 22\n");
  657. return LGW_HAL_ERROR;
  658. }
  659. /* Set internal LUT */
  660. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].rf_power = conf->lut[i].rf_power;
  661. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].dig_gain = conf->lut[i].dig_gain;
  662. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].pa_gain = conf->lut[i].pa_gain;
  663. /* sx125x */
  664. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].dac_gain = conf->lut[i].dac_gain;
  665. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].mix_gain = conf->lut[i].mix_gain;
  666. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].offset_i = 0; /* To be calibrated */
  667. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].offset_q = 0; /* To be calibrated */
  668. /* sx1250 */
  669. CONTEXT_TX_GAIN_LUT[rf_chain].lut[i].pwr_idx = conf->lut[i].pwr_idx;
  670. }
  671. return LGW_HAL_SUCCESS;
  672. }
  673. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  674. int lgw_ftime_setconf(struct lgw_conf_ftime_s * conf) {
  675. CHECK_NULL(conf);
  676. CONTEXT_FINE_TIMESTAMP.enable = conf->enable;
  677. CONTEXT_FINE_TIMESTAMP.mode = conf->mode;
  678. return LGW_HAL_SUCCESS;
  679. }
  680. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  681. int lgw_sx1261_setconf(struct lgw_conf_sx1261_s * conf) {
  682. int i;
  683. CHECK_NULL(conf);
  684. /* Set the SX1261 global conf */
  685. CONTEXT_SX1261.enable = conf->enable;
  686. strncpy(CONTEXT_SX1261.spi_path, conf->spi_path, sizeof CONTEXT_SX1261.spi_path);
  687. CONTEXT_SX1261.spi_path[sizeof CONTEXT_SX1261.spi_path - 1] = '\0'; /* ensure string termination */
  688. CONTEXT_SX1261.rssi_offset = conf->rssi_offset;
  689. /* Set the LBT conf */
  690. CONTEXT_SX1261.lbt_conf.enable = conf->lbt_conf.enable;
  691. CONTEXT_SX1261.lbt_conf.rssi_target = conf->lbt_conf.rssi_target;
  692. CONTEXT_SX1261.lbt_conf.nb_channel = conf->lbt_conf.nb_channel;
  693. for (i = 0; i < CONTEXT_SX1261.lbt_conf.nb_channel; i++) {
  694. if (conf->lbt_conf.channels[i].bandwidth != BW_125KHZ && conf->lbt_conf.channels[i].bandwidth != BW_250KHZ) {
  695. printf("ERROR: bandwidth not supported for LBT channel %d\n", i);
  696. return LGW_HAL_ERROR;
  697. }
  698. if (conf->lbt_conf.channels[i].scan_time_us != LGW_LBT_SCAN_TIME_128_US && conf->lbt_conf.channels[i].scan_time_us != LGW_LBT_SCAN_TIME_5000_US) {
  699. printf("ERROR: scan_time_us not supported for LBT channel %d\n", i);
  700. return LGW_HAL_ERROR;
  701. }
  702. CONTEXT_SX1261.lbt_conf.channels[i] = conf->lbt_conf.channels[i];
  703. }
  704. return LGW_HAL_SUCCESS;
  705. }
  706. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  707. int lgw_debug_setconf(struct lgw_conf_debug_s * conf) {
  708. int i;
  709. CHECK_NULL(conf);
  710. CONTEXT_DEBUG.nb_ref_payload = conf->nb_ref_payload;
  711. for (i = 0; i < CONTEXT_DEBUG.nb_ref_payload; i++) {
  712. /* Get user configuration */
  713. CONTEXT_DEBUG.ref_payload[i].id = conf->ref_payload[i].id;
  714. /* Initialize global context */
  715. CONTEXT_DEBUG.ref_payload[i].prev_cnt = 0;
  716. CONTEXT_DEBUG.ref_payload[i].payload[0] = (uint8_t)(CONTEXT_DEBUG.ref_payload[i].id >> 24);
  717. CONTEXT_DEBUG.ref_payload[i].payload[1] = (uint8_t)(CONTEXT_DEBUG.ref_payload[i].id >> 16);
  718. CONTEXT_DEBUG.ref_payload[i].payload[2] = (uint8_t)(CONTEXT_DEBUG.ref_payload[i].id >> 8);
  719. CONTEXT_DEBUG.ref_payload[i].payload[3] = (uint8_t)(CONTEXT_DEBUG.ref_payload[i].id >> 0);
  720. }
  721. if (conf->log_file_name != NULL) {
  722. strncpy(CONTEXT_DEBUG.log_file_name, conf->log_file_name, sizeof CONTEXT_DEBUG.log_file_name);
  723. CONTEXT_DEBUG.log_file_name[sizeof CONTEXT_DEBUG.log_file_name - 1] = '\0'; /* ensure string termination */
  724. }
  725. return LGW_HAL_SUCCESS;
  726. }
  727. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  728. int lgw_start(void) {
  729. int i, err;
  730. uint8_t fw_version_agc;
  731. DEBUG_PRINTF(" --- %s\n", "IN");
  732. if (CONTEXT_STARTED == true) {
  733. DEBUG_MSG("Note: LoRa concentrator already started, restarting it now\n");
  734. }
  735. err = lgw_connect(CONTEXT_COM_TYPE, CONTEXT_COM_PATH);
  736. if (err == LGW_REG_ERROR) {
  737. DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n");
  738. return LGW_HAL_ERROR;
  739. }
  740. /* Set all GPIOs to 0 */
  741. err = sx1302_set_gpio(0x00);
  742. if (err != LGW_REG_SUCCESS) {
  743. printf("ERROR: failed to set all GPIOs to 0\n");
  744. return LGW_HAL_ERROR;
  745. }
  746. /* Calibrate radios */
  747. err = sx1302_radio_calibrate(&CONTEXT_RF_CHAIN[0], CONTEXT_BOARD.clksrc, &CONTEXT_TX_GAIN_LUT[0]);
  748. if (err != LGW_REG_SUCCESS) {
  749. printf("ERROR: radio calibration failed\n");
  750. return LGW_HAL_ERROR;
  751. }
  752. /* Setup radios for RX */
  753. for (i = 0; i < LGW_RF_CHAIN_NB; i++) {
  754. if (CONTEXT_RF_CHAIN[i].enable == true) {
  755. /* Reset the radio */
  756. err = sx1302_radio_reset(i, CONTEXT_RF_CHAIN[i].type);
  757. if (err != LGW_REG_SUCCESS) {
  758. printf("ERROR: failed to reset radio %d\n", i);
  759. return LGW_HAL_ERROR;
  760. }
  761. /* Setup the radio */
  762. switch (CONTEXT_RF_CHAIN[i].type) {
  763. case LGW_RADIO_TYPE_SX1250:
  764. err = sx1250_setup(i, CONTEXT_RF_CHAIN[i].freq_hz, CONTEXT_RF_CHAIN[i].single_input_mode);
  765. break;
  766. case LGW_RADIO_TYPE_SX1255:
  767. case LGW_RADIO_TYPE_SX1257:
  768. err = sx125x_setup(i, CONTEXT_BOARD.clksrc, true, CONTEXT_RF_CHAIN[i].type, CONTEXT_RF_CHAIN[i].freq_hz);
  769. break;
  770. default:
  771. printf("ERROR: RADIO TYPE NOT SUPPORTED (RF_CHAIN %d)\n", i);
  772. return LGW_HAL_ERROR;
  773. }
  774. if (err != LGW_REG_SUCCESS) {
  775. printf("ERROR: failed to setup radio %d\n", i);
  776. return LGW_HAL_ERROR;
  777. }
  778. /* Set radio mode */
  779. err = sx1302_radio_set_mode(i, CONTEXT_RF_CHAIN[i].type);
  780. if (err != LGW_REG_SUCCESS) {
  781. printf("ERROR: failed to set mode for radio %d\n", i);
  782. return LGW_HAL_ERROR;
  783. }
  784. }
  785. }
  786. /* Select the radio which provides the clock to the sx1302 */
  787. err = sx1302_radio_clock_select(CONTEXT_BOARD.clksrc);
  788. if (err != LGW_REG_SUCCESS) {
  789. printf("ERROR: failed to get clock from radio %u\n", CONTEXT_BOARD.clksrc);
  790. return LGW_HAL_ERROR;
  791. }
  792. /* Release host control on radio (will be controlled by AGC) */
  793. err = sx1302_radio_host_ctrl(false);
  794. if (err != LGW_REG_SUCCESS) {
  795. printf("ERROR: failed to release control over radios\n");
  796. return LGW_HAL_ERROR;
  797. }
  798. /* Basic initialization of the sx1302 */
  799. err = sx1302_init(&CONTEXT_FINE_TIMESTAMP);
  800. if (err != LGW_REG_SUCCESS) {
  801. printf("ERROR: failed to initialize SX1302\n");
  802. return LGW_HAL_ERROR;
  803. }
  804. /* Configure PA/LNA LUTs */
  805. err = sx1302_pa_lna_lut_configure(&CONTEXT_BOARD);
  806. if (err != LGW_REG_SUCCESS) {
  807. printf("ERROR: failed to configure SX1302 PA/LNA LUT\n");
  808. return LGW_HAL_ERROR;
  809. }
  810. /* Configure Radio FE */
  811. err = sx1302_radio_fe_configure();
  812. if (err != LGW_REG_SUCCESS) {
  813. printf("ERROR: failed to configure SX1302 radio frontend\n");
  814. return LGW_HAL_ERROR;
  815. }
  816. /* Configure the Channelizer */
  817. err = sx1302_channelizer_configure(CONTEXT_IF_CHAIN, false);
  818. if (err != LGW_REG_SUCCESS) {
  819. printf("ERROR: failed to configure SX1302 channelizer\n");
  820. return LGW_HAL_ERROR;
  821. }
  822. /* configure LoRa 'multi-sf' modems */
  823. err = sx1302_lora_correlator_configure(CONTEXT_IF_CHAIN, &(CONTEXT_DEMOD));
  824. if (err != LGW_REG_SUCCESS) {
  825. printf("ERROR: failed to configure SX1302 LoRa modem correlators\n");
  826. return LGW_HAL_ERROR;
  827. }
  828. err = sx1302_lora_modem_configure(CONTEXT_RF_CHAIN[0].freq_hz);
  829. if (err != LGW_REG_SUCCESS) {
  830. printf("ERROR: failed to configure SX1302 LoRa modems\n");
  831. return LGW_HAL_ERROR;
  832. }
  833. /* configure LoRa 'single-sf' modem */
  834. if (CONTEXT_IF_CHAIN[8].enable == true) {
  835. err = sx1302_lora_service_correlator_configure(&(CONTEXT_LORA_SERVICE));
  836. if (err != LGW_REG_SUCCESS) {
  837. printf("ERROR: failed to configure SX1302 LoRa Service modem correlators\n");
  838. return LGW_HAL_ERROR;
  839. }
  840. err = sx1302_lora_service_modem_configure(&(CONTEXT_LORA_SERVICE), CONTEXT_RF_CHAIN[0].freq_hz);
  841. if (err != LGW_REG_SUCCESS) {
  842. printf("ERROR: failed to configure SX1302 LoRa Service modem\n");
  843. return LGW_HAL_ERROR;
  844. }
  845. }
  846. /* configure FSK modem */
  847. if (CONTEXT_IF_CHAIN[9].enable == true) {
  848. err = sx1302_fsk_configure(&(CONTEXT_FSK));
  849. if (err != LGW_REG_SUCCESS) {
  850. printf("ERROR: failed to configure SX1302 FSK modem\n");
  851. return LGW_HAL_ERROR;
  852. }
  853. }
  854. /* configure syncword */
  855. err = sx1302_lora_syncword(CONTEXT_LWAN_PUBLIC, CONTEXT_LORA_SERVICE.datarate);
  856. if (err != LGW_REG_SUCCESS) {
  857. printf("ERROR: failed to configure SX1302 LoRa syncword\n");
  858. return LGW_HAL_ERROR;
  859. }
  860. /* enable demodulators - to be done before starting AGC/ARB */
  861. err = sx1302_modem_enable();
  862. if (err != LGW_REG_SUCCESS) {
  863. printf("ERROR: failed to enable SX1302 modems\n");
  864. return LGW_HAL_ERROR;
  865. }
  866. /* Load AGC firmware */
  867. switch (CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type) {
  868. case LGW_RADIO_TYPE_SX1250:
  869. DEBUG_MSG("Loading AGC fw for sx1250\n");
  870. err = sx1302_agc_load_firmware(agc_firmware_sx1250);
  871. if (err != LGW_REG_SUCCESS) {
  872. printf("ERROR: failed to load AGC firmware for sx1250\n");
  873. return LGW_HAL_ERROR;
  874. }
  875. fw_version_agc = FW_VERSION_AGC_SX1250;
  876. break;
  877. case LGW_RADIO_TYPE_SX1255:
  878. case LGW_RADIO_TYPE_SX1257:
  879. DEBUG_MSG("Loading AGC fw for sx125x\n");
  880. err = sx1302_agc_load_firmware(agc_firmware_sx125x);
  881. if (err != LGW_REG_SUCCESS) {
  882. printf("ERROR: failed to load AGC firmware for sx125x\n");
  883. return LGW_HAL_ERROR;
  884. }
  885. fw_version_agc = FW_VERSION_AGC_SX125X;
  886. break;
  887. default:
  888. printf("ERROR: failed to load AGC firmware, radio type not supported (%d)\n", CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type);
  889. return LGW_HAL_ERROR;
  890. }
  891. err = sx1302_agc_start(fw_version_agc, CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type, SX1302_AGC_RADIO_GAIN_AUTO, SX1302_AGC_RADIO_GAIN_AUTO, CONTEXT_BOARD.full_duplex, CONTEXT_SX1261.lbt_conf.enable);
  892. if (err != LGW_REG_SUCCESS) {
  893. printf("ERROR: failed to start AGC firmware\n");
  894. return LGW_HAL_ERROR;
  895. }
  896. /* Load ARB firmware */
  897. DEBUG_MSG("Loading ARB fw\n");
  898. err = sx1302_arb_load_firmware(arb_firmware);
  899. if (err != LGW_REG_SUCCESS) {
  900. printf("ERROR: failed to load ARB firmware\n");
  901. return LGW_HAL_ERROR;
  902. }
  903. err = sx1302_arb_start(FW_VERSION_ARB, &CONTEXT_FINE_TIMESTAMP);
  904. if (err != LGW_REG_SUCCESS) {
  905. printf("ERROR: failed to start ARB firmware\n");
  906. return LGW_HAL_ERROR;
  907. }
  908. /* static TX configuration */
  909. err = sx1302_tx_configure(CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type);
  910. if (err != LGW_REG_SUCCESS) {
  911. printf("ERROR: failed to configure SX1302 TX path\n");
  912. return LGW_HAL_ERROR;
  913. }
  914. /* enable GPS */
  915. err = sx1302_gps_enable(true);
  916. if (err != LGW_REG_SUCCESS) {
  917. printf("ERROR: failed to enable GPS on sx1302\n");
  918. return LGW_HAL_ERROR;
  919. }
  920. /* For debug logging */
  921. #if HAL_DEBUG_FILE_LOG
  922. char timestamp_str[40];
  923. struct tm *timenow;
  924. /* Append current time to log file name */
  925. time_t now = time(NULL);
  926. timenow = gmtime(&now);
  927. strftime(timestamp_str, sizeof(timestamp_str), ".%Y-%m-%d_%H%M%S", timenow);
  928. strncat(CONTEXT_DEBUG.log_file_name, timestamp_str, sizeof CONTEXT_DEBUG.log_file_name);
  929. /* Open the file for writting */
  930. log_file = fopen(CONTEXT_DEBUG.log_file_name, "w+"); /* create log file, overwrite if file already exist */
  931. if (log_file == NULL) {
  932. printf("ERROR: impossible to create log file %s\n", CONTEXT_DEBUG.log_file_name);
  933. return LGW_HAL_ERROR;
  934. } else {
  935. printf("INFO: %s file opened for debug log\n", CONTEXT_DEBUG.log_file_name);
  936. /* Create "pktlog.csv" symlink to simplify user life */
  937. unlink("loragw_hal.log");
  938. i = symlink(CONTEXT_DEBUG.log_file_name, "loragw_hal.log");
  939. if (i < 0) {
  940. printf("ERROR: impossible to create symlink to log file %s\n", CONTEXT_DEBUG.log_file_name);
  941. }
  942. }
  943. #endif
  944. /* Configure the pseudo-random generator (For Debug) */
  945. dbg_init_random();
  946. if (CONTEXT_COM_TYPE == LGW_COM_SPI) {
  947. /* Find the temperature sensor on the known supported ports */
  948. for (i = 0; i < (int)(sizeof I2C_PORT_TEMP_SENSOR); i++) {
  949. ts_addr = I2C_PORT_TEMP_SENSOR[i];
  950. err = i2c_linuxdev_open(I2C_DEVICE, ts_addr, &ts_fd);
  951. if (err != LGW_I2C_SUCCESS) {
  952. printf("ERROR: failed to open I2C for temperature sensor on port 0x%02X\n", ts_addr);
  953. return LGW_HAL_ERROR;
  954. }
  955. err = stts751_configure(ts_fd, ts_addr);
  956. if (err != LGW_I2C_SUCCESS) {
  957. printf("INFO: no temperature sensor found on port 0x%02X\n", ts_addr);
  958. i2c_linuxdev_close(ts_fd);
  959. ts_fd = -1;
  960. } else {
  961. printf("INFO: found temperature sensor on port 0x%02X\n", ts_addr);
  962. break;
  963. }
  964. }
  965. if (i == sizeof I2C_PORT_TEMP_SENSOR) {
  966. printf("ERROR: no temperature sensor found.\n");
  967. return LGW_HAL_ERROR;
  968. }
  969. /* Configure ADC AD338R for full duplex (CN490 reference design) */
  970. if (CONTEXT_BOARD.full_duplex == true) {
  971. err = i2c_linuxdev_open(I2C_DEVICE, I2C_PORT_DAC_AD5338R, &ad_fd);
  972. if (err != LGW_I2C_SUCCESS) {
  973. printf("ERROR: failed to open I2C for ad5338r\n");
  974. return LGW_HAL_ERROR;
  975. }
  976. err = ad5338r_configure(ad_fd, I2C_PORT_DAC_AD5338R);
  977. if (err != LGW_I2C_SUCCESS) {
  978. printf("ERROR: failed to configure ad5338r\n");
  979. i2c_linuxdev_close(ad_fd);
  980. ad_fd = -1;
  981. return LGW_HAL_ERROR;
  982. }
  983. /* Turn off the PA: set DAC output to 0V */
  984. uint8_t volt_val[AD5338R_CMD_SIZE] = { 0x39, (uint8_t)VOLTAGE2HEX_H(0), (uint8_t)VOLTAGE2HEX_L(0) };
  985. err = ad5338r_write(ad_fd, I2C_PORT_DAC_AD5338R, volt_val);
  986. if (err != LGW_I2C_SUCCESS) {
  987. printf("ERROR: AD5338R: failed to set DAC output to 0V\n");
  988. return LGW_HAL_ERROR;
  989. }
  990. printf("INFO: AD5338R: Set DAC output to 0x%02X 0x%02X\n", (uint8_t)VOLTAGE2HEX_H(0), (uint8_t)VOLTAGE2HEX_L(0));
  991. }
  992. }
  993. /* Connect to the external sx1261 for LBT or Spectral Scan */
  994. if (CONTEXT_SX1261.enable == true) {
  995. err = sx1261_connect(CONTEXT_COM_TYPE, (CONTEXT_COM_TYPE == LGW_COM_SPI) ? CONTEXT_SX1261.spi_path : NULL);
  996. if (err != LGW_REG_SUCCESS) {
  997. printf("ERROR: failed to connect to the sx1261 radio (LBT/Spectral Scan)\n");
  998. return LGW_HAL_ERROR;
  999. }
  1000. err = sx1261_load_pram();
  1001. if (err != LGW_REG_SUCCESS) {
  1002. printf("ERROR: failed to patch sx1261 radio for LBT/Spectral Scan\n");
  1003. return LGW_HAL_ERROR;
  1004. }
  1005. err = sx1261_calibrate(CONTEXT_RF_CHAIN[0].freq_hz);
  1006. if (err != LGW_REG_SUCCESS) {
  1007. printf("ERROR: failed to calibrate sx1261 radio\n");
  1008. return LGW_HAL_ERROR;
  1009. }
  1010. err = sx1261_setup();
  1011. if (err != LGW_REG_SUCCESS) {
  1012. printf("ERROR: failed to setup sx1261 radio\n");
  1013. return LGW_HAL_ERROR;
  1014. }
  1015. }
  1016. /* Set CONFIG_DONE GPIO to 1 (turn on the corresponding LED) */
  1017. err = sx1302_set_gpio(0x01);
  1018. if (err != LGW_REG_SUCCESS) {
  1019. printf("ERROR: failed to set CONFIG_DONE GPIO\n");
  1020. return LGW_HAL_ERROR;
  1021. }
  1022. /* set hal state */
  1023. CONTEXT_STARTED = true;
  1024. DEBUG_PRINTF(" --- %s\n", "OUT");
  1025. return LGW_HAL_SUCCESS;
  1026. }
  1027. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1028. int lgw_stop(void) {
  1029. int i, x, err = LGW_HAL_SUCCESS;
  1030. DEBUG_PRINTF(" --- %s\n", "IN");
  1031. if (CONTEXT_STARTED == false) {
  1032. DEBUG_MSG("Note: LoRa concentrator was not started...\n");
  1033. return LGW_HAL_SUCCESS;
  1034. }
  1035. /* Abort current TX if needed */
  1036. for (i = 0; i < LGW_RF_CHAIN_NB; i++) {
  1037. DEBUG_PRINTF("INFO: aborting TX on chain %u\n", i);
  1038. x = lgw_abort_tx(i);
  1039. if (x != LGW_HAL_SUCCESS) {
  1040. printf("WARNING: failed to get abort TX on chain %u\n", i);
  1041. err = LGW_HAL_ERROR;
  1042. }
  1043. }
  1044. /* Close log file */
  1045. if (log_file != NULL) {
  1046. fclose(log_file);
  1047. log_file = NULL;
  1048. }
  1049. DEBUG_MSG("INFO: Disconnecting\n");
  1050. x = lgw_disconnect();
  1051. if (x != LGW_HAL_SUCCESS) {
  1052. printf("ERROR: failed to disconnect concentrator\n");
  1053. err = LGW_HAL_ERROR;
  1054. }
  1055. if (CONTEXT_COM_TYPE == LGW_COM_SPI) {
  1056. DEBUG_MSG("INFO: Closing I2C for temperature sensor\n");
  1057. x = i2c_linuxdev_close(ts_fd);
  1058. if (x != 0) {
  1059. printf("ERROR: failed to close I2C temperature sensor device (err=%i)\n", x);
  1060. err = LGW_HAL_ERROR;
  1061. }
  1062. if (CONTEXT_BOARD.full_duplex == true) {
  1063. DEBUG_MSG("INFO: Closing I2C for AD5338R\n");
  1064. x = i2c_linuxdev_close(ad_fd);
  1065. if (x != 0) {
  1066. printf("ERROR: failed to close I2C AD5338R device (err=%i)\n", x);
  1067. err = LGW_HAL_ERROR;
  1068. }
  1069. }
  1070. }
  1071. CONTEXT_STARTED = false;
  1072. DEBUG_PRINTF(" --- %s\n", "OUT");
  1073. return err;
  1074. }
  1075. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1076. int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {
  1077. int res;
  1078. uint8_t nb_pkt_fetched = 0;
  1079. uint8_t nb_pkt_found = 0;
  1080. uint8_t nb_pkt_left = 0;
  1081. float current_temperature = 0.0, rssi_temperature_offset = 0.0;
  1082. /* performances variables */
  1083. struct timeval tm;
  1084. DEBUG_PRINTF(" --- %s\n", "IN");
  1085. /* Record function start time */
  1086. _meas_time_start(&tm);
  1087. /* Get packets from SX1302, if any */
  1088. res = sx1302_fetch(&nb_pkt_fetched);
  1089. if (res != LGW_REG_SUCCESS) {
  1090. printf("ERROR: failed to fetch packets from SX1302\n");
  1091. return LGW_HAL_ERROR;
  1092. }
  1093. /* Update internal counter */
  1094. /* WARNING: this needs to be called regularly by the upper layer */
  1095. res = sx1302_update();
  1096. if (res != LGW_REG_SUCCESS) {
  1097. return LGW_HAL_ERROR;
  1098. }
  1099. /* Exit now if no packet fetched */
  1100. if (nb_pkt_fetched == 0) {
  1101. _meas_time_stop(1, tm, __FUNCTION__);
  1102. return 0;
  1103. }
  1104. if (nb_pkt_fetched > max_pkt) {
  1105. nb_pkt_left = nb_pkt_fetched - max_pkt;
  1106. printf("WARNING: not enough space allocated, fetched %d packet(s), %d will be left in RX buffer\n", nb_pkt_fetched, nb_pkt_left);
  1107. }
  1108. /* Apply RSSI temperature compensation */
  1109. res = lgw_get_temperature(&current_temperature);
  1110. if (res != LGW_I2C_SUCCESS) {
  1111. printf("ERROR: failed to get current temperature\n");
  1112. return LGW_HAL_ERROR;
  1113. }
  1114. /* Iterate on the RX buffer to get parsed packets */
  1115. for (nb_pkt_found = 0; nb_pkt_found < ((nb_pkt_fetched <= max_pkt) ? nb_pkt_fetched : max_pkt); nb_pkt_found++) {
  1116. /* Get packet and move to next one */
  1117. res = sx1302_parse(&lgw_context, &pkt_data[nb_pkt_found]);
  1118. if (res == LGW_REG_WARNING) {
  1119. printf("WARNING: parsing error on packet %d, discarding fetched packets\n", nb_pkt_found);
  1120. return LGW_HAL_SUCCESS;
  1121. } else if (res == LGW_REG_ERROR) {
  1122. printf("ERROR: fatal parsing error on packet %d, aborting...\n", nb_pkt_found);
  1123. return LGW_HAL_ERROR;
  1124. }
  1125. /* Appli RSSI offset calibrated for the board */
  1126. pkt_data[nb_pkt_found].rssic += CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_offset;
  1127. pkt_data[nb_pkt_found].rssis += CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_offset;
  1128. rssi_temperature_offset = sx1302_rssi_get_temperature_offset(&CONTEXT_RF_CHAIN[pkt_data[nb_pkt_found].rf_chain].rssi_tcomp, current_temperature);
  1129. pkt_data[nb_pkt_found].rssic += rssi_temperature_offset;
  1130. pkt_data[nb_pkt_found].rssis += rssi_temperature_offset;
  1131. DEBUG_PRINTF("INFO: RSSI temperature offset applied: %.3f dB (current temperature %.1f C)\n", rssi_temperature_offset, current_temperature);
  1132. }
  1133. DEBUG_PRINTF("INFO: nb pkt found:%u left:%u\n", nb_pkt_found, nb_pkt_left);
  1134. /* Remove duplicated packets generated by double demod when precision timestamp is enabled */
  1135. if ((nb_pkt_found > 0) && (CONTEXT_FINE_TIMESTAMP.enable == true)) {
  1136. res = merge_packets(pkt_data, &nb_pkt_found);
  1137. if (res != 0) {
  1138. printf("WARNING: failed to remove duplicated packets\n");
  1139. }
  1140. DEBUG_PRINTF("INFO: nb pkt found:%u (after de-duplicating)\n", nb_pkt_found);
  1141. }
  1142. _meas_time_stop(1, tm, __FUNCTION__);
  1143. DEBUG_PRINTF(" --- %s\n", "OUT");
  1144. return nb_pkt_found;
  1145. }
  1146. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1147. int lgw_send(struct lgw_pkt_tx_s * pkt_data) {
  1148. int err;
  1149. bool lbt_tx_allowed;
  1150. /* performances variables */
  1151. struct timeval tm;
  1152. DEBUG_PRINTF(" --- %s\n", "IN");
  1153. /* Record function start time */
  1154. _meas_time_start(&tm);
  1155. /* check if the concentrator is running */
  1156. if (CONTEXT_STARTED == false) {
  1157. printf("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n");
  1158. return LGW_HAL_ERROR;
  1159. }
  1160. CHECK_NULL(pkt_data);
  1161. /* check input range (segfault prevention) */
  1162. if (pkt_data->rf_chain >= LGW_RF_CHAIN_NB) {
  1163. printf("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n");
  1164. return LGW_HAL_ERROR;
  1165. }
  1166. /* check input variables */
  1167. if (CONTEXT_RF_CHAIN[pkt_data->rf_chain].tx_enable == false) {
  1168. printf("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n");
  1169. return LGW_HAL_ERROR;
  1170. }
  1171. if (CONTEXT_RF_CHAIN[pkt_data->rf_chain].enable == false) {
  1172. printf("ERROR: SELECTED RF_CHAIN IS DISABLED\n");
  1173. return LGW_HAL_ERROR;
  1174. }
  1175. if (!IS_TX_MODE(pkt_data->tx_mode)) {
  1176. printf("ERROR: TX_MODE NOT SUPPORTED\n");
  1177. return LGW_HAL_ERROR;
  1178. }
  1179. if (pkt_data->modulation == MOD_LORA) {
  1180. if (!IS_LORA_BW(pkt_data->bandwidth)) {
  1181. printf("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n");
  1182. return LGW_HAL_ERROR;
  1183. }
  1184. if (!IS_LORA_DR(pkt_data->datarate)) {
  1185. printf("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n");
  1186. return LGW_HAL_ERROR;
  1187. }
  1188. if (!IS_LORA_CR(pkt_data->coderate)) {
  1189. printf("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n");
  1190. return LGW_HAL_ERROR;
  1191. }
  1192. if (pkt_data->size > 255) {
  1193. printf("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n");
  1194. return LGW_HAL_ERROR;
  1195. }
  1196. } else if (pkt_data->modulation == MOD_FSK) {
  1197. if((pkt_data->f_dev < 1) || (pkt_data->f_dev > 200)) {
  1198. printf("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n");
  1199. return LGW_HAL_ERROR;
  1200. }
  1201. if(!IS_FSK_DR(pkt_data->datarate)) {
  1202. printf("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n");
  1203. return LGW_HAL_ERROR;
  1204. }
  1205. if (pkt_data->size > 255) {
  1206. printf("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n");
  1207. return LGW_HAL_ERROR;
  1208. }
  1209. } else if (pkt_data->modulation == MOD_CW) {
  1210. /* do nothing */
  1211. } else {
  1212. printf("ERROR: INVALID TX MODULATION\n");
  1213. return LGW_HAL_ERROR;
  1214. }
  1215. /* Set PA gain with AD5338R when using full duplex CN490 ref design */
  1216. if (CONTEXT_BOARD.full_duplex == true) {
  1217. uint8_t volt_val[AD5338R_CMD_SIZE] = {0x39, VOLTAGE2HEX_H(2.51), VOLTAGE2HEX_L(2.51)}; /* set to 2.51V */
  1218. err = ad5338r_write(ad_fd, I2C_PORT_DAC_AD5338R, volt_val);
  1219. if (err != LGW_I2C_SUCCESS) {
  1220. printf("ERROR: failed to set voltage by ad5338r\n");
  1221. return LGW_HAL_ERROR;
  1222. }
  1223. printf("INFO: AD5338R: Set DAC output to 0x%02X 0x%02X\n", (uint8_t)VOLTAGE2HEX_H(2.51), (uint8_t)VOLTAGE2HEX_L(2.51));
  1224. }
  1225. //依赖于外设sx1261进行扫描,也无用
  1226. /* Start Listen-Before-Talk */
  1227. if (CONTEXT_SX1261.lbt_conf.enable == true) {
  1228. err = lgw_lbt_start(&CONTEXT_SX1261, pkt_data);
  1229. if (err != 0) {
  1230. printf("ERROR: failed to start LBT\n");
  1231. return LGW_HAL_ERROR;
  1232. }
  1233. }
  1234. /* Send the TX request to the concentrator */
  1235. err = sx1302_send(CONTEXT_RF_CHAIN[pkt_data->rf_chain].type, &CONTEXT_TX_GAIN_LUT[pkt_data->rf_chain], CONTEXT_LWAN_PUBLIC, &CONTEXT_FSK, pkt_data);
  1236. if (err != LGW_REG_SUCCESS) {
  1237. printf("ERROR: %s: Failed to send packet\n", __FUNCTION__);
  1238. if (CONTEXT_SX1261.lbt_conf.enable == true) {
  1239. err = lgw_lbt_stop();
  1240. if (err != 0) {
  1241. printf("ERROR: %s: Failed to stop LBT\n", __FUNCTION__);
  1242. }
  1243. }
  1244. return LGW_HAL_ERROR;
  1245. }
  1246. _meas_time_stop(1, tm, __FUNCTION__);
  1247. /* Stop Listen-Before-Talk */
  1248. if (CONTEXT_SX1261.lbt_conf.enable == true) {
  1249. err = lgw_lbt_tx_status(pkt_data->rf_chain, &lbt_tx_allowed);
  1250. if (err != 0) {
  1251. printf("ERROR: %s: Failed to get LBT TX status, TX aborted\n", __FUNCTION__);
  1252. err = sx1302_tx_abort(pkt_data->rf_chain);
  1253. if (err != 0) {
  1254. printf("ERROR: %s: Failed to abort TX\n", __FUNCTION__);
  1255. }
  1256. err = lgw_lbt_stop();
  1257. if (err != 0) {
  1258. printf("ERROR: %s: Failed to stop LBT\n", __FUNCTION__);
  1259. }
  1260. return LGW_HAL_ERROR;
  1261. }
  1262. if (lbt_tx_allowed == true) {
  1263. printf("LBT: packet is allowed to be transmitted\n");
  1264. } else {
  1265. printf("LBT: (ERROR) packet is NOT allowed to be transmitted\n");
  1266. }
  1267. err = lgw_lbt_stop();
  1268. if (err != 0) {
  1269. printf("ERROR: %s: Failed to stop LBT\n", __FUNCTION__);
  1270. return LGW_HAL_ERROR;
  1271. }
  1272. }
  1273. DEBUG_PRINTF(" --- %s\n", "OUT");
  1274. if (CONTEXT_SX1261.lbt_conf.enable == true && lbt_tx_allowed == false) {
  1275. return LGW_LBT_NOT_ALLOWED;
  1276. } else {
  1277. return LGW_HAL_SUCCESS;
  1278. }
  1279. }
  1280. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1281. int lgw_status(uint8_t rf_chain, uint8_t select, uint8_t *code) {
  1282. DEBUG_PRINTF(" --- %s\n", "IN");
  1283. /* check input variables */
  1284. CHECK_NULL(code);
  1285. if (rf_chain >= LGW_RF_CHAIN_NB) {
  1286. DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n");
  1287. return LGW_HAL_ERROR;
  1288. }
  1289. /* Get status */
  1290. if (select == TX_STATUS) {
  1291. if (CONTEXT_STARTED == false) {
  1292. *code = TX_OFF;
  1293. } else {
  1294. *code = sx1302_tx_status(rf_chain);
  1295. }
  1296. } else if (select == RX_STATUS) {
  1297. if (CONTEXT_STARTED == false) {
  1298. *code = RX_OFF;
  1299. } else {
  1300. *code = sx1302_rx_status(rf_chain);
  1301. }
  1302. } else {
  1303. DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n");
  1304. return LGW_HAL_ERROR;
  1305. }
  1306. DEBUG_PRINTF(" --- %s\n", "OUT");
  1307. //DEBUG_PRINTF("INFO: STATUS %u\n", *code);
  1308. return LGW_HAL_SUCCESS;
  1309. }
  1310. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1311. int lgw_abort_tx(uint8_t rf_chain) {
  1312. int err;
  1313. DEBUG_PRINTF(" --- %s\n", "IN");
  1314. /* check input variables */
  1315. if (rf_chain >= LGW_RF_CHAIN_NB) {
  1316. DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n");
  1317. return LGW_HAL_ERROR;
  1318. }
  1319. /* Abort current TX */
  1320. err = sx1302_tx_abort(rf_chain);
  1321. DEBUG_PRINTF(" --- %s\n", "OUT");
  1322. return err;
  1323. }
  1324. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1325. int lgw_get_trigcnt(uint32_t* trig_cnt_us) {
  1326. DEBUG_PRINTF(" --- %s\n", "IN");
  1327. CHECK_NULL(trig_cnt_us);
  1328. *trig_cnt_us = sx1302_timestamp_counter(true);
  1329. DEBUG_PRINTF(" --- %s\n", "OUT");
  1330. return LGW_HAL_SUCCESS;
  1331. }
  1332. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1333. int lgw_get_instcnt(uint32_t* inst_cnt_us) {
  1334. DEBUG_PRINTF(" --- %s\n", "IN");
  1335. CHECK_NULL(inst_cnt_us);
  1336. *inst_cnt_us = sx1302_timestamp_counter(false);
  1337. DEBUG_PRINTF(" --- %s\n", "OUT");
  1338. return LGW_HAL_SUCCESS;
  1339. }
  1340. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1341. int lgw_get_eui(uint64_t* eui) {
  1342. DEBUG_PRINTF(" --- %s\n", "IN");
  1343. CHECK_NULL(eui);
  1344. if (sx1302_get_eui(eui) != LGW_REG_SUCCESS) {
  1345. return LGW_HAL_ERROR;
  1346. }
  1347. DEBUG_PRINTF(" --- %s\n", "OUT");
  1348. return LGW_HAL_SUCCESS;
  1349. }
  1350. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1351. int lgw_get_temperature(float* temperature) {
  1352. int err = LGW_HAL_ERROR;
  1353. DEBUG_PRINTF(" --- %s\n", "IN");
  1354. CHECK_NULL(temperature);
  1355. switch (CONTEXT_COM_TYPE) {
  1356. case LGW_COM_SPI:
  1357. err = stts751_get_temperature(ts_fd, ts_addr, temperature);
  1358. break;
  1359. case LGW_COM_USB:
  1360. err = lgw_com_get_temperature(temperature);
  1361. break;
  1362. default:
  1363. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  1364. break;
  1365. }
  1366. DEBUG_PRINTF(" --- %s\n", "OUT");
  1367. return err;
  1368. }
  1369. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1370. const char* lgw_version_info() {
  1371. return lgw_version_string;
  1372. }
  1373. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1374. uint32_t lgw_time_on_air(const struct lgw_pkt_tx_s *packet) {
  1375. double t_fsk;
  1376. uint32_t toa_ms, toa_us;
  1377. DEBUG_PRINTF(" --- %s\n", "IN");
  1378. if (packet == NULL) {
  1379. printf("ERROR: Failed to compute time on air, wrong parameter\n");
  1380. return 0;
  1381. }
  1382. if (packet->modulation == MOD_LORA) {
  1383. toa_us = lora_packet_time_on_air(packet->bandwidth, packet->datarate, packet->coderate, packet->preamble, packet->no_header, packet->no_crc, packet->size, NULL, NULL, NULL);
  1384. toa_ms = (uint32_t)( (double)toa_us / 1000.0 + 0.5 );
  1385. DEBUG_PRINTF("INFO: LoRa packet ToA: %u ms\n", toa_ms);
  1386. } else if (packet->modulation == MOD_FSK) {
  1387. /* PREAMBLE + SYNC_WORD + PKT_LEN + PKT_PAYLOAD + CRC
  1388. PREAMBLE: default 5 bytes
  1389. SYNC_WORD: default 3 bytes
  1390. PKT_LEN: 1 byte (variable length mode)
  1391. PKT_PAYLOAD: x bytes
  1392. CRC: 0 or 2 bytes
  1393. */
  1394. t_fsk = (8 * (double)(packet->preamble + CONTEXT_FSK.sync_word_size + 1 + packet->size + ((packet->no_crc == true) ? 0 : 2)) / (double)packet->datarate) * 1E3;
  1395. /* Duration of packet */
  1396. toa_ms = (uint32_t)t_fsk + 1; /* add margin for rounding */
  1397. } else {
  1398. toa_ms = 0;
  1399. printf("ERROR: Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation);
  1400. }
  1401. DEBUG_PRINTF(" --- %s\n", "OUT");
  1402. return toa_ms;
  1403. }
  1404. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1405. int lgw_spectral_scan_start(uint32_t freq_hz, uint16_t nb_scan) {
  1406. int err;
  1407. if (CONTEXT_SX1261.enable != true) {
  1408. printf("ERROR: sx1261 is not enabled, no spectral scan\n");
  1409. return LGW_HAL_ERROR;
  1410. }
  1411. err = sx1261_set_rx_params(freq_hz, BW_125KHZ);
  1412. if (err != LGW_REG_SUCCESS) {
  1413. printf("ERROR: Failed to set RX params for Spectral Scan\n");
  1414. return LGW_HAL_ERROR;
  1415. }
  1416. err = sx1261_spectral_scan_start(nb_scan);
  1417. if (err != LGW_REG_SUCCESS) {
  1418. printf("ERROR: start spectral scan failed\n");
  1419. return LGW_HAL_ERROR;
  1420. }
  1421. return LGW_HAL_SUCCESS;
  1422. }
  1423. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1424. int lgw_spectral_scan_get_status(lgw_spectral_scan_status_t * status) {
  1425. return sx1261_spectral_scan_status(status);
  1426. }
  1427. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1428. int lgw_spectral_scan_get_results(int16_t levels_dbm[static LGW_SPECTRAL_SCAN_RESULT_SIZE], uint16_t results[static LGW_SPECTRAL_SCAN_RESULT_SIZE]) {
  1429. return sx1261_spectral_scan_get_results(CONTEXT_SX1261.rssi_offset, levels_dbm, results);
  1430. }
  1431. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  1432. int lgw_spectral_scan_abort() {
  1433. return sx1261_spectral_scan_abort();
  1434. }
  1435. /* --- EOF ------------------------------------------------------------------ */