loragw_com.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2020 Semtech
  8. Description:
  9. Functions to abstract the communication interface used to communicate with
  10. the concentrator.
  11. Single-byte read/write and burst read/write.
  12. License: Revised BSD License, see LICENSE.TXT file include in the project
  13. */
  14. /* -------------------------------------------------------------------------- */
  15. /* --- DEPENDANCIES --------------------------------------------------------- */
  16. #include <stdint.h> /* C99 types */
  17. #include <stdio.h> /* printf fprintf */
  18. #include "loragw_com.h"
  19. #include "loragw_usb.h"
  20. #include "loragw_spi.h"
  21. #include "loragw_aux.h"
  22. /* -------------------------------------------------------------------------- */
  23. /* --- PRIVATE MACROS ------------------------------------------------------- */
  24. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  25. #if DEBUG_COM == 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_COM_ERROR;}
  29. #else
  30. #define DEBUG_MSG(str)
  31. #define DEBUG_PRINTF(fmt, args...)
  32. #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;}
  33. #endif
  34. /* -------------------------------------------------------------------------- */
  35. /* --- PRIVATE CONSTANTS ---------------------------------------------------- */
  36. /* -------------------------------------------------------------------------- */
  37. /* --- PRIVATE VARIABLES ---------------------------------------------------- */
  38. /**
  39. @brief The current communication type in use (SPI, USB)
  40. */
  41. static lgw_com_type_t _lgw_com_type = LGW_COM_UNKNOWN;
  42. /**
  43. @brief A generic pointer to the COM device (file descriptor)
  44. */
  45. static void* _lgw_com_target = NULL;
  46. /* -------------------------------------------------------------------------- */
  47. /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
  48. int lgw_com_open(lgw_com_type_t com_type, const char * com_path) {
  49. int com_stat;
  50. /* Check input parameters */
  51. CHECK_NULL(com_path);
  52. if ((com_type != LGW_COM_SPI) && (com_type != LGW_COM_USB)) {
  53. DEBUG_MSG("ERROR: COMMUNICATION INTERFACE TYPE IS NOT SUPPORTED\n");
  54. return LGW_COM_ERROR;
  55. }
  56. if (_lgw_com_target != NULL) {
  57. DEBUG_MSG("WARNING: CONCENTRATOR WAS ALREADY CONNECTED\n");
  58. lgw_com_close();
  59. }
  60. /* set current com type */
  61. _lgw_com_type = com_type;
  62. switch (com_type) {
  63. case LGW_COM_SPI:
  64. printf("Opening SPI communication interface\n");
  65. com_stat = lgw_spi_open(com_path, &_lgw_com_target);
  66. break;
  67. case LGW_COM_USB:
  68. printf("Opening USB communication interface\n");
  69. com_stat = lgw_usb_open(com_path, &_lgw_com_target);
  70. break;
  71. default:
  72. com_stat = LGW_COM_ERROR;
  73. break;
  74. }
  75. return com_stat;
  76. }
  77. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  78. /* SPI release */
  79. int lgw_com_close(void) {
  80. int com_stat;
  81. if (_lgw_com_target == NULL) {
  82. printf("ERROR: concentrator is not connected\n");
  83. return -1;
  84. }
  85. switch (_lgw_com_type) {
  86. case LGW_COM_SPI:
  87. printf("Closing SPI communication interface\n");
  88. com_stat = lgw_spi_close(_lgw_com_target);
  89. break;
  90. case LGW_COM_USB:
  91. printf("Closing USB communication interface\n");
  92. com_stat = lgw_usb_close(_lgw_com_target);
  93. break;
  94. default:
  95. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  96. com_stat = LGW_COM_ERROR;
  97. break;
  98. }
  99. _lgw_com_target = NULL;
  100. return com_stat;
  101. }
  102. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  103. /* Simple write */
  104. int lgw_com_w(uint8_t spi_mux_target, uint16_t address, uint8_t data) {
  105. int com_stat;
  106. /* performances variables */
  107. struct timeval tm;
  108. /* Record function start time */
  109. _meas_time_start(&tm);
  110. /* Check input parameters */
  111. CHECK_NULL(_lgw_com_target);
  112. switch (_lgw_com_type) {
  113. case LGW_COM_SPI:
  114. com_stat = lgw_spi_w(_lgw_com_target, spi_mux_target, address, data);
  115. break;
  116. case LGW_COM_USB:
  117. com_stat = lgw_usb_w(_lgw_com_target, spi_mux_target, address, data);
  118. break;
  119. default:
  120. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  121. com_stat = LGW_COM_ERROR;
  122. break;
  123. }
  124. /* Compute time spent in this function */
  125. _meas_time_stop(5, tm, __FUNCTION__);
  126. return com_stat;
  127. }
  128. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  129. /* Simple read */
  130. int lgw_com_r(uint8_t spi_mux_target, uint16_t address, uint8_t *data) {
  131. int com_stat;
  132. /* performances variables */
  133. struct timeval tm;
  134. /* Record function start time */
  135. _meas_time_start(&tm);
  136. /* Check input parameters */
  137. CHECK_NULL(_lgw_com_target);
  138. CHECK_NULL(data);
  139. switch (_lgw_com_type) {
  140. case LGW_COM_SPI:
  141. com_stat = lgw_spi_r(_lgw_com_target, spi_mux_target, address, data);
  142. break;
  143. case LGW_COM_USB:
  144. com_stat = lgw_usb_r(_lgw_com_target, spi_mux_target, address, data);
  145. break;
  146. default:
  147. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  148. com_stat = LGW_COM_ERROR;
  149. break;
  150. }
  151. /* Compute time spent in this function */
  152. _meas_time_stop(5, tm, __FUNCTION__);
  153. return com_stat;
  154. }
  155. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  156. int lgw_com_rmw(uint8_t spi_mux_target, uint16_t address, uint8_t offs, uint8_t leng, uint8_t data) {
  157. int com_stat;
  158. /* performances variables */
  159. struct timeval tm;
  160. /* Record function start time */
  161. _meas_time_start(&tm);
  162. /* Check input parameters */
  163. CHECK_NULL(_lgw_com_target);
  164. switch (_lgw_com_type) {
  165. case LGW_COM_SPI:
  166. com_stat = lgw_spi_rmw(_lgw_com_target, spi_mux_target, address, offs, leng, data);
  167. break;
  168. case LGW_COM_USB:
  169. com_stat = lgw_usb_rmw(_lgw_com_target, address, offs, leng, data);
  170. break;
  171. default:
  172. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  173. com_stat = LGW_COM_ERROR;
  174. break;
  175. }
  176. /* Compute time spent in this function */
  177. _meas_time_stop(5, tm, __FUNCTION__);
  178. return com_stat;
  179. }
  180. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  181. /* Burst (multiple-byte) write */
  182. int lgw_com_wb(uint8_t spi_mux_target, uint16_t address, const uint8_t *data, uint16_t size) {
  183. int com_stat;
  184. /* performances variables */
  185. struct timeval tm;
  186. /* Record function start time */
  187. _meas_time_start(&tm);
  188. /* Check input parameters */
  189. CHECK_NULL(_lgw_com_target);
  190. CHECK_NULL(data);
  191. switch (_lgw_com_type) {
  192. case LGW_COM_SPI:
  193. com_stat = lgw_spi_wb(_lgw_com_target, spi_mux_target, address, data, size);
  194. break;
  195. case LGW_COM_USB:
  196. com_stat = lgw_usb_wb(_lgw_com_target, spi_mux_target, address, data, size);
  197. break;
  198. default:
  199. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  200. com_stat = LGW_COM_ERROR;
  201. break;
  202. }
  203. /* Compute time spent in this function */
  204. _meas_time_stop(5, tm, __FUNCTION__);
  205. return com_stat;
  206. }
  207. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  208. /* Burst (multiple-byte) read */
  209. int lgw_com_rb(uint8_t spi_mux_target, uint16_t address, uint8_t *data, uint16_t size) {
  210. int com_stat;
  211. /* performances variables */
  212. struct timeval tm;
  213. /* Record function start time */
  214. _meas_time_start(&tm);
  215. /* Check input parameters */
  216. CHECK_NULL(_lgw_com_target);
  217. CHECK_NULL(data);
  218. switch (_lgw_com_type) {
  219. case LGW_COM_SPI:
  220. com_stat = lgw_spi_rb(_lgw_com_target, spi_mux_target, address, data, size);
  221. break;
  222. case LGW_COM_USB:
  223. com_stat = lgw_usb_rb(_lgw_com_target, spi_mux_target, address, data, size);
  224. break;
  225. default:
  226. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  227. com_stat = LGW_COM_ERROR;
  228. break;
  229. }
  230. /* Compute time spent in this function */
  231. _meas_time_stop(5, tm, __FUNCTION__);
  232. return com_stat;
  233. }
  234. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  235. int lgw_com_set_write_mode(lgw_com_write_mode_t write_mode) {
  236. int com_stat = LGW_COM_SUCCESS;
  237. switch (_lgw_com_type) {
  238. case LGW_COM_SPI:
  239. /* Do nothing: only single mode is supported on SPI */
  240. break;
  241. case LGW_COM_USB:
  242. com_stat = lgw_usb_set_write_mode(write_mode);
  243. break;
  244. default:
  245. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  246. com_stat = LGW_COM_ERROR;
  247. break;
  248. }
  249. return com_stat;
  250. }
  251. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  252. int lgw_com_flush(void) {
  253. int com_stat = LGW_COM_SUCCESS;
  254. switch (_lgw_com_type) {
  255. case LGW_COM_SPI:
  256. /* Do nothing: only single mode is supported on SPI */
  257. break;
  258. case LGW_COM_USB:
  259. com_stat = lgw_usb_flush(_lgw_com_target);
  260. break;
  261. default:
  262. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  263. com_stat = LGW_COM_ERROR;
  264. break;
  265. }
  266. return com_stat;
  267. }
  268. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  269. uint16_t lgw_com_chunk_size(void) {
  270. switch (_lgw_com_type) {
  271. case LGW_COM_SPI:
  272. return lgw_spi_chunk_size();
  273. case LGW_COM_USB:
  274. return lgw_usb_chunk_size();
  275. break;
  276. default:
  277. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  278. return 0;
  279. }
  280. }
  281. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  282. int lgw_com_get_temperature(float * temperature) {
  283. /* Check input parameters */
  284. CHECK_NULL(_lgw_com_target);
  285. CHECK_NULL(temperature);
  286. switch (_lgw_com_type) {
  287. case LGW_COM_SPI:
  288. printf("ERROR(%s:%d): not supported for SPI com\n", __FUNCTION__, __LINE__);
  289. return -1;
  290. case LGW_COM_USB:
  291. return lgw_usb_get_temperature(_lgw_com_target, temperature);
  292. default:
  293. printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__);
  294. return LGW_COM_ERROR;
  295. }
  296. }
  297. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  298. void* lgw_com_target(void) {
  299. return _lgw_com_target;
  300. }
  301. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  302. lgw_com_type_t lgw_com_type(void) {
  303. return _lgw_com_type;
  304. }
  305. /* --- EOF ------------------------------------------------------------------ */