Host driver/HAL to build a LoRa Picocell Gateway which communicates through USB with a concentrator board based on Semtech SX1308 multi-channel modem and SX1257/SX1255 RF transceivers.

Committer:
dgabino
Date:
Wed Apr 11 14:38:42 2018 +0000
Revision:
0:102b50f941d0
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgabino 0:102b50f941d0 1 /*
dgabino 0:102b50f941d0 2 / _____) _ | |
dgabino 0:102b50f941d0 3 ( (____ _____ ____ _| |_ _____ ____| |__
dgabino 0:102b50f941d0 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
dgabino 0:102b50f941d0 5 _____) ) ____| | | || |_| ____( (___| | | |
dgabino 0:102b50f941d0 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
dgabino 0:102b50f941d0 7 (C)2017 Semtech-Cycleo
dgabino 0:102b50f941d0 8
dgabino 0:102b50f941d0 9 Description:
dgabino 0:102b50f941d0 10 Wrapper to call MCU's HAL functions
dgabino 0:102b50f941d0 11
dgabino 0:102b50f941d0 12 License: Revised BSD License, see LICENSE.TXT file include in the project
dgabino 0:102b50f941d0 13 */
dgabino 0:102b50f941d0 14
dgabino 0:102b50f941d0 15
dgabino 0:102b50f941d0 16 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 17 /* --- DEPENDANCIES --------------------------------------------------------- */
dgabino 0:102b50f941d0 18
dgabino 0:102b50f941d0 19 #include <stdint.h> /* C99 types */
dgabino 0:102b50f941d0 20 #include <stdio.h> /* printf fprintf */
dgabino 0:102b50f941d0 21 #include <stdlib.h> /* malloc free */
dgabino 0:102b50f941d0 22 #include <unistd.h> /* lseek, close */
dgabino 0:102b50f941d0 23 #include <fcntl.h> /* open */
dgabino 0:102b50f941d0 24 #include <string.h> /* memset */
dgabino 0:102b50f941d0 25 #include <errno.h> /* Error number definitions */
dgabino 0:102b50f941d0 26 #include <termios.h> /* POSIX terminal control definitions */
dgabino 0:102b50f941d0 27 #include <sys/ioctl.h>
dgabino 0:102b50f941d0 28 #include <pthread.h>
dgabino 0:102b50f941d0 29 #include <time.h>
dgabino 0:102b50f941d0 30 #include <sys/select.h>
dgabino 0:102b50f941d0 31
dgabino 0:102b50f941d0 32 #include "loragw_com.h"
dgabino 0:102b50f941d0 33 #include "loragw_mcu.h"
dgabino 0:102b50f941d0 34 #include "loragw_aux.h"
dgabino 0:102b50f941d0 35
dgabino 0:102b50f941d0 36 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 37 /* --- PRIVATE MACROS ------------------------------------------------------- */
dgabino 0:102b50f941d0 38
dgabino 0:102b50f941d0 39 #if DEBUG_MCU == 1
dgabino 0:102b50f941d0 40 #define DEBUG_MSG(str) fprintf(stderr, str)
dgabino 0:102b50f941d0 41 #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
dgabino 0:102b50f941d0 42 #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_COM_ERROR;}
dgabino 0:102b50f941d0 43 #else
dgabino 0:102b50f941d0 44 #define DEBUG_MSG(str)
dgabino 0:102b50f941d0 45 #define DEBUG_PRINTF(fmt, args...)
dgabino 0:102b50f941d0 46 #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;}
dgabino 0:102b50f941d0 47 #endif
dgabino 0:102b50f941d0 48
dgabino 0:102b50f941d0 49 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 50 /* --- PRIVATE SHARED VARIABLES (GLOBAL) ------------------------------------ */
dgabino 0:102b50f941d0 51
dgabino 0:102b50f941d0 52 extern void *lgw_com_target; /*! generic pointer to the COM device */
dgabino 0:102b50f941d0 53
dgabino 0:102b50f941d0 54 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 55 /* --- PRIVATE CONSTANTS ---------------------------------------------------- */
dgabino 0:102b50f941d0 56
dgabino 0:102b50f941d0 57 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 58 /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
dgabino 0:102b50f941d0 59
dgabino 0:102b50f941d0 60 int lgw_mcu_board_setconf(struct lgw_conf_board_s conf) {
dgabino 0:102b50f941d0 61 int i, x;
dgabino 0:102b50f941d0 62 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 63 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 64 uint8_t PADDING = 0;
dgabino 0:102b50f941d0 65 uint8_t data[4];
dgabino 0:102b50f941d0 66 uint16_t size;
dgabino 0:102b50f941d0 67
dgabino 0:102b50f941d0 68 /* struct to byte array */
dgabino 0:102b50f941d0 69 data[0] = conf.lorawan_public;
dgabino 0:102b50f941d0 70 data[1] = conf.clksrc;
dgabino 0:102b50f941d0 71 data[2] = PADDING;
dgabino 0:102b50f941d0 72 data[3] = PADDING;
dgabino 0:102b50f941d0 73 size = sizeof(data) / sizeof(uint8_t);
dgabino 0:102b50f941d0 74
dgabino 0:102b50f941d0 75 /* prepare command */
dgabino 0:102b50f941d0 76 cmd.id = 'i';
dgabino 0:102b50f941d0 77 cmd.len_msb = (uint8_t)((size >> 8) & 0xFF);
dgabino 0:102b50f941d0 78 cmd.len_lsb = (uint8_t)((size >> 0) & 0xFF);
dgabino 0:102b50f941d0 79 cmd.address = 0;
dgabino 0:102b50f941d0 80 for (i = 0; i < size; i++) {
dgabino 0:102b50f941d0 81 cmd.cmd_data[i] = data[i];
dgabino 0:102b50f941d0 82 }
dgabino 0:102b50f941d0 83
dgabino 0:102b50f941d0 84 /* send command to MCU */
dgabino 0:102b50f941d0 85 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 86 if (x != LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 87 printf("ERROR: failed to configure board\n");
dgabino 0:102b50f941d0 88 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 89 }
dgabino 0:102b50f941d0 90
dgabino 0:102b50f941d0 91 /* check command acknoledge */
dgabino 0:102b50f941d0 92 if (ans.status != ACK_OK) {
dgabino 0:102b50f941d0 93 printf("ERROR: failed to configure board, ACK failed\n");
dgabino 0:102b50f941d0 94 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 95 }
dgabino 0:102b50f941d0 96
dgabino 0:102b50f941d0 97 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 98 }
dgabino 0:102b50f941d0 99
dgabino 0:102b50f941d0 100 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 101
dgabino 0:102b50f941d0 102 int lgw_mcu_rxrf_setconf(uint8_t rfchain, struct lgw_conf_rxrf_s conf) {
dgabino 0:102b50f941d0 103 int i, x;
dgabino 0:102b50f941d0 104 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 105 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 106 uint8_t PADDING = 0;
dgabino 0:102b50f941d0 107 uint8_t data[20];
dgabino 0:102b50f941d0 108 uint16_t size;
dgabino 0:102b50f941d0 109
dgabino 0:102b50f941d0 110 /* struct to byte array */
dgabino 0:102b50f941d0 111 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 112 data[0] = conf.enable;
dgabino 0:102b50f941d0 113 data[1] = PADDING;
dgabino 0:102b50f941d0 114 data[2] = PADDING;
dgabino 0:102b50f941d0 115 data[3] = PADDING;
dgabino 0:102b50f941d0 116 data[4] = *(((uint8_t *)(&conf.freq_hz)));
dgabino 0:102b50f941d0 117 data[5] = *(((uint8_t *)(&conf.freq_hz)) + 1);
dgabino 0:102b50f941d0 118 data[6] = *(((uint8_t *)(&conf.freq_hz)) + 2);
dgabino 0:102b50f941d0 119 data[7] = *(((uint8_t *)(&conf.freq_hz)) + 3);
dgabino 0:102b50f941d0 120 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 121 data[8] = *(((uint8_t *)(&conf.rssi_offset)));
dgabino 0:102b50f941d0 122 data[9] = *(((uint8_t *)(&conf.rssi_offset)) + 1);
dgabino 0:102b50f941d0 123 data[10] = *(((uint8_t *)(&conf.rssi_offset)) + 2);
dgabino 0:102b50f941d0 124 data[11] = *(((uint8_t *)(&conf.rssi_offset)) + 3);
dgabino 0:102b50f941d0 125 data[12] = *(((uint8_t *)(&conf.type)));
dgabino 0:102b50f941d0 126 data[13] = PADDING;
dgabino 0:102b50f941d0 127 data[14] = PADDING;
dgabino 0:102b50f941d0 128 data[15] = PADDING;
dgabino 0:102b50f941d0 129 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 130 data[16] = *(((uint8_t *)(&conf.tx_enable)));
dgabino 0:102b50f941d0 131 data[17] = *(((uint8_t *)(&conf.tx_enable)) + 1);
dgabino 0:102b50f941d0 132 data[18] = *(((uint8_t *)(&conf.tx_enable)) + 2);
dgabino 0:102b50f941d0 133 data[19] = *(((uint8_t *)(&conf.tx_enable)) + 3);
dgabino 0:102b50f941d0 134 size = sizeof(data) / sizeof(uint8_t);
dgabino 0:102b50f941d0 135
dgabino 0:102b50f941d0 136 /* prepare command */
dgabino 0:102b50f941d0 137 cmd.id = 'c';
dgabino 0:102b50f941d0 138 cmd.len_msb = (uint8_t)((size >> 8) & 0xFF);
dgabino 0:102b50f941d0 139 cmd.len_lsb = (uint8_t)((size >> 0) & 0xFF);
dgabino 0:102b50f941d0 140 cmd.address = rfchain;
dgabino 0:102b50f941d0 141 for (i = 0; i < size; i++) {
dgabino 0:102b50f941d0 142 cmd.cmd_data[i] = data[i];
dgabino 0:102b50f941d0 143 }
dgabino 0:102b50f941d0 144
dgabino 0:102b50f941d0 145 /* send command to MCU */
dgabino 0:102b50f941d0 146 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 147 if (x != LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 148 printf("ERROR: failed to send rxrf configuration\n");
dgabino 0:102b50f941d0 149 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 150 }
dgabino 0:102b50f941d0 151
dgabino 0:102b50f941d0 152 /* check command acknoledge */
dgabino 0:102b50f941d0 153 if (ans.status != ACK_OK) {
dgabino 0:102b50f941d0 154 printf("ERROR: rxrf configuration, ACK failed\n");
dgabino 0:102b50f941d0 155 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 156 }
dgabino 0:102b50f941d0 157
dgabino 0:102b50f941d0 158 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 159 }
dgabino 0:102b50f941d0 160
dgabino 0:102b50f941d0 161 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 162
dgabino 0:102b50f941d0 163 int lgw_mcu_rxif_setconf(uint8_t ifchain, struct lgw_conf_rxif_s conf) {
dgabino 0:102b50f941d0 164 int i, x;
dgabino 0:102b50f941d0 165 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 166 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 167 uint8_t PADDING = 0;
dgabino 0:102b50f941d0 168 uint8_t data[32];
dgabino 0:102b50f941d0 169 uint16_t size;
dgabino 0:102b50f941d0 170
dgabino 0:102b50f941d0 171 /* struct to byte array */
dgabino 0:102b50f941d0 172 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 173 data[0] = conf.enable;
dgabino 0:102b50f941d0 174 data[1] = *(((uint8_t *)(&conf.rf_chain)));
dgabino 0:102b50f941d0 175 data[2] = PADDING;
dgabino 0:102b50f941d0 176 data[3] = PADDING;
dgabino 0:102b50f941d0 177 data[4] = *(((uint8_t *)(&conf.freq_hz)));
dgabino 0:102b50f941d0 178 data[5] = *(((uint8_t *)(&conf.freq_hz)) + 1);
dgabino 0:102b50f941d0 179 data[6] = *(((uint8_t *)(&conf.freq_hz)) + 2);
dgabino 0:102b50f941d0 180 data[7] = *(((uint8_t *)(&conf.freq_hz)) + 3);
dgabino 0:102b50f941d0 181 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 182 data[8] = *(((uint8_t *)(&conf.bandwidth)));
dgabino 0:102b50f941d0 183 data[9] = PADDING;
dgabino 0:102b50f941d0 184 data[10] = PADDING;
dgabino 0:102b50f941d0 185 data[11] = PADDING;
dgabino 0:102b50f941d0 186 data[12] = *(((uint8_t *)(&conf.datarate)));
dgabino 0:102b50f941d0 187 data[13] = *(((uint8_t *)(&conf.datarate)) + 1);
dgabino 0:102b50f941d0 188 data[14] = *(((uint8_t *)(&conf.datarate)) + 2);
dgabino 0:102b50f941d0 189 data[15] = *(((uint8_t *)(&conf.datarate)) + 3);
dgabino 0:102b50f941d0 190 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 191 data[16] = *(((uint8_t *)(&conf.sync_word_size)));
dgabino 0:102b50f941d0 192 data[17] = PADDING;
dgabino 0:102b50f941d0 193 data[18] = PADDING;
dgabino 0:102b50f941d0 194 data[19] = PADDING;
dgabino 0:102b50f941d0 195 data[20] = PADDING;
dgabino 0:102b50f941d0 196 data[21] = PADDING;
dgabino 0:102b50f941d0 197 data[22] = PADDING;
dgabino 0:102b50f941d0 198 data[23] = PADDING;
dgabino 0:102b50f941d0 199 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 200 data[24] = *(((uint8_t *)(&conf.sync_word)));
dgabino 0:102b50f941d0 201 data[25] = *(((uint8_t *)(&conf.sync_word)) + 1);
dgabino 0:102b50f941d0 202 data[26] = *(((uint8_t *)(&conf.sync_word)) + 2);
dgabino 0:102b50f941d0 203 data[27] = *(((uint8_t *)(&conf.sync_word)) + 3);
dgabino 0:102b50f941d0 204 data[28] = *(((uint8_t *)(&conf.sync_word)) + 4);
dgabino 0:102b50f941d0 205 data[29] = *(((uint8_t *)(&conf.sync_word)) + 5);
dgabino 0:102b50f941d0 206 data[30] = *(((uint8_t *)(&conf.sync_word)) + 6);
dgabino 0:102b50f941d0 207 data[31] = *(((uint8_t *)(&conf.sync_word)) + 7);
dgabino 0:102b50f941d0 208 size = sizeof(data) / sizeof(uint8_t);
dgabino 0:102b50f941d0 209
dgabino 0:102b50f941d0 210 /* prepare command */
dgabino 0:102b50f941d0 211 cmd.id = 'd';
dgabino 0:102b50f941d0 212 cmd.len_msb = (uint8_t)((size >> 8) & 0xFF);
dgabino 0:102b50f941d0 213 cmd.len_lsb = (uint8_t)((size >> 0) & 0xFF);
dgabino 0:102b50f941d0 214 cmd.address = ifchain;
dgabino 0:102b50f941d0 215 for (i = 0; i < size; i++) {
dgabino 0:102b50f941d0 216 cmd.cmd_data[i] = data[i];
dgabino 0:102b50f941d0 217 }
dgabino 0:102b50f941d0 218
dgabino 0:102b50f941d0 219 /* send command to MCU */
dgabino 0:102b50f941d0 220 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 221 if (x != LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 222 printf("ERROR: failed to send rxif configuration\n");
dgabino 0:102b50f941d0 223 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 224 }
dgabino 0:102b50f941d0 225
dgabino 0:102b50f941d0 226 /* check command acknoledge */
dgabino 0:102b50f941d0 227 if (ans.status != ACK_OK) {
dgabino 0:102b50f941d0 228 printf("ERROR: rxif configuration, ACK failed\n");
dgabino 0:102b50f941d0 229 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 230 }
dgabino 0:102b50f941d0 231
dgabino 0:102b50f941d0 232 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 233 }
dgabino 0:102b50f941d0 234
dgabino 0:102b50f941d0 235 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 236
dgabino 0:102b50f941d0 237 int lgw_mcu_txgain_setconf(struct lgw_tx_gain_lut_s *conf) {
dgabino 0:102b50f941d0 238 int i, x;
dgabino 0:102b50f941d0 239 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 240 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 241 uint32_t u = 0;
dgabino 0:102b50f941d0 242 uint8_t data[(LGW_MULTI_NB * TX_GAIN_LUT_SIZE_MAX) + 4];
dgabino 0:102b50f941d0 243 uint16_t size;
dgabino 0:102b50f941d0 244
dgabino 0:102b50f941d0 245 /* struct to byte array */
dgabino 0:102b50f941d0 246 for (u = 0; u < TX_GAIN_LUT_SIZE_MAX; u++) {
dgabino 0:102b50f941d0 247 data[0 + (5 * u)] = 0;
dgabino 0:102b50f941d0 248 data[1 + (5 * u)] = 0;
dgabino 0:102b50f941d0 249 data[2 + (5 * u)] = 0;
dgabino 0:102b50f941d0 250 data[3 + (5 * u)] = 0;
dgabino 0:102b50f941d0 251 data[4 + (5 * u)] = 0;
dgabino 0:102b50f941d0 252 }
dgabino 0:102b50f941d0 253
dgabino 0:102b50f941d0 254 for (u = 0; u < conf->size; u++) {
dgabino 0:102b50f941d0 255 data[0 + (5 * u)] = conf->lut[u].dig_gain;
dgabino 0:102b50f941d0 256 data[1 + (5 * u)] = conf->lut[u].pa_gain;
dgabino 0:102b50f941d0 257 data[2 + (5 * u)] = conf->lut[u].dac_gain;
dgabino 0:102b50f941d0 258 data[3 + (5 * u)] = conf->lut[u].mix_gain;
dgabino 0:102b50f941d0 259 data[4 + (5 * u)] = conf->lut[u].rf_power;
dgabino 0:102b50f941d0 260 }
dgabino 0:102b50f941d0 261 data[(TX_GAIN_LUT_SIZE_MAX) * 5] = conf->size;
dgabino 0:102b50f941d0 262 size = ((TX_GAIN_LUT_SIZE_MAX) * 5) + 1;
dgabino 0:102b50f941d0 263
dgabino 0:102b50f941d0 264 /* prepare command */
dgabino 0:102b50f941d0 265 cmd.id = 'h';
dgabino 0:102b50f941d0 266 cmd.len_msb = (uint8_t)((size >> 8) & 0xFF);
dgabino 0:102b50f941d0 267 cmd.len_lsb = (uint8_t)((size >> 0) & 0xFF);
dgabino 0:102b50f941d0 268 cmd.address = 0;
dgabino 0:102b50f941d0 269 for (i = 0; i < size; i++) {
dgabino 0:102b50f941d0 270 cmd.cmd_data[i] = data[i];
dgabino 0:102b50f941d0 271 }
dgabino 0:102b50f941d0 272
dgabino 0:102b50f941d0 273 /* send command to MCU */
dgabino 0:102b50f941d0 274 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 275 if (x != LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 276 printf("ERROR: failed to send tx gain configuration\n");
dgabino 0:102b50f941d0 277 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 278 }
dgabino 0:102b50f941d0 279
dgabino 0:102b50f941d0 280 /* check command acknoledge */
dgabino 0:102b50f941d0 281 if (ans.status != ACK_OK) {
dgabino 0:102b50f941d0 282 printf("ERROR: tx gain configuration, ACK failed\n");
dgabino 0:102b50f941d0 283 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 284 }
dgabino 0:102b50f941d0 285
dgabino 0:102b50f941d0 286 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 287 }
dgabino 0:102b50f941d0 288
dgabino 0:102b50f941d0 289 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 290
dgabino 0:102b50f941d0 291 int lgw_mcu_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {
dgabino 0:102b50f941d0 292 int i, j, x;
dgabino 0:102b50f941d0 293 int cptalc = 0;
dgabino 0:102b50f941d0 294 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 295 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 296 int nb_packet ;
dgabino 0:102b50f941d0 297 uint8_t data[LGW_PKT_RX_STRUCT_SIZE_ALIGNED * max_pkt];
dgabino 0:102b50f941d0 298 uint16_t pkt_size;
dgabino 0:102b50f941d0 299
dgabino 0:102b50f941d0 300 /* check input variables */
dgabino 0:102b50f941d0 301 CHECK_NULL(pkt_data);
dgabino 0:102b50f941d0 302
dgabino 0:102b50f941d0 303 /* Prepare command for fetching packets */
dgabino 0:102b50f941d0 304 cmd.id = 'b';
dgabino 0:102b50f941d0 305 cmd.len_msb = 0;
dgabino 0:102b50f941d0 306 cmd.len_lsb = 1;
dgabino 0:102b50f941d0 307 cmd.address = 0;
dgabino 0:102b50f941d0 308 cmd.cmd_data[0] = max_pkt;
dgabino 0:102b50f941d0 309
dgabino 0:102b50f941d0 310 /* send command to MCU */
dgabino 0:102b50f941d0 311 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 312 if ((x != LGW_COM_SUCCESS) || (ans.status != ACK_OK)) {
dgabino 0:102b50f941d0 313 DEBUG_MSG("ERROR: failed to receive packets from concentrator\n");
dgabino 0:102b50f941d0 314 return 0;
dgabino 0:102b50f941d0 315 }
dgabino 0:102b50f941d0 316
dgabino 0:102b50f941d0 317 /* check nb_packet variables */
dgabino 0:102b50f941d0 318 nb_packet = ans.ans_data[0];
dgabino 0:102b50f941d0 319 if ((nb_packet > LGW_PKT_FIFO_SIZE) || (nb_packet < 0)) {
dgabino 0:102b50f941d0 320 DEBUG_PRINTF("ERROR: NOT A VALID NUMBER OF RECEIVED PACKET (%d)\n", nb_packet);
dgabino 0:102b50f941d0 321 return 0;
dgabino 0:102b50f941d0 322 }
dgabino 0:102b50f941d0 323
dgabino 0:102b50f941d0 324 //DEBUG_PRINTF("NOTE: Available packet %d %d\n", nb_packet, (ans.len_msb << 8) + ans.len_lsb);
dgabino 0:102b50f941d0 325
dgabino 0:102b50f941d0 326 /* over the number of packets */
dgabino 0:102b50f941d0 327 for (i = 0; i < nb_packet; i++) {
dgabino 0:102b50f941d0 328 /* for each packet */
dgabino 0:102b50f941d0 329 pkt_size = (uint16_t)((uint8_t)(ans.ans_data[cptalc + 42] << 8) | (uint8_t)ans.ans_data[cptalc + 43]);
dgabino 0:102b50f941d0 330 for (j = 0; j < (LGW_PKT_RX_METADATA_SIZE_ALIGNED + pkt_size); j++) {
dgabino 0:102b50f941d0 331 data[(i * LGW_PKT_RX_STRUCT_SIZE_ALIGNED) + j] = ans.ans_data[j + cptalc + 1]; /* +1 because ans.ans_data[0] is nb_packet */
dgabino 0:102b50f941d0 332 }
dgabino 0:102b50f941d0 333 cptalc += j;
dgabino 0:102b50f941d0 334 }
dgabino 0:102b50f941d0 335
dgabino 0:102b50f941d0 336 /* byte array to struct - the following code is done to work both with 32 or 64 bits host */
dgabino 0:102b50f941d0 337 #pragma GCC diagnostic push
dgabino 0:102b50f941d0 338 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
dgabino 0:102b50f941d0 339 for (i = 0; i < nb_packet; i++) {
dgabino 0:102b50f941d0 340 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 341 pkt_data[i].freq_hz = *((uint32_t*)(&data[0 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 342 pkt_data[i].if_chain = *((uint8_t*)(&data[4 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 343 pkt_data[i].status = *((uint8_t*)(&data[5 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 344 /* 1 BYTE PADDING FOR 64-bits ALIGNMENT */
dgabino 0:102b50f941d0 345 /* 1 BYTE PADDING FOR 64-bits ALIGNMENT */
dgabino 0:102b50f941d0 346 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 347 pkt_data[i].count_us = *((uint32_t*)(&data[8 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 348 pkt_data[i].rf_chain = *((uint8_t*)(&data[12 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 349 pkt_data[i].modulation = *((uint8_t*)(&data[13 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 350 pkt_data[i].bandwidth = *((uint8_t*)(&data[14 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 351 /* 1 BYTE PADDING FOR 64-bits ALIGNMENT */
dgabino 0:102b50f941d0 352 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 353 pkt_data[i].datarate = *((uint32_t*)(&data[16 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 354 pkt_data[i].coderate = *((uint8_t*)(&data[20 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 355 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 356 pkt_data[i].rssi = *((float*)(&data[24 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 357 pkt_data[i].snr = *((float*)(&data[28 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 358 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 359 pkt_data[i].snr_min = *((float*)(&data[32 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 360 pkt_data[i].snr_max = *((float*)(&data[36 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 361 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 362 pkt_data[i].crc = *((uint16_t*)(&data[40 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 363 pkt_data[i].size = *((uint16_t*)(&data[42 + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 364 /* NO PADDING NEEDED HERE, END OF ARRAY */
dgabino 0:102b50f941d0 365 for (j = 0; j < 256; j++) {
dgabino 0:102b50f941d0 366 (pkt_data[i].payload[j]) = *((uint8_t*)(&data[LGW_PKT_RX_METADATA_SIZE_ALIGNED + j + LGW_PKT_RX_STRUCT_SIZE_ALIGNED * i]));
dgabino 0:102b50f941d0 367 }
dgabino 0:102b50f941d0 368 }
dgabino 0:102b50f941d0 369 #pragma GCC diagnostic pop
dgabino 0:102b50f941d0 370
dgabino 0:102b50f941d0 371 return nb_packet;
dgabino 0:102b50f941d0 372 }
dgabino 0:102b50f941d0 373
dgabino 0:102b50f941d0 374 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 375
dgabino 0:102b50f941d0 376 int lgw_mcu_send(struct lgw_pkt_tx_s pkt_data) {
dgabino 0:102b50f941d0 377 int i, x;
dgabino 0:102b50f941d0 378 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 379 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 380 uint8_t PADDING = 0;
dgabino 0:102b50f941d0 381 uint8_t data[LGW_PKT_TX_STRUCT_SIZE_ALIGNED];
dgabino 0:102b50f941d0 382 uint16_t size;
dgabino 0:102b50f941d0 383
dgabino 0:102b50f941d0 384 /* struct to byte array */
dgabino 0:102b50f941d0 385 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 386 data[0] = *(((uint8_t *)(&pkt_data.freq_hz)));
dgabino 0:102b50f941d0 387 data[1] = *(((uint8_t *)(&pkt_data.freq_hz)) + 1);
dgabino 0:102b50f941d0 388 data[2] = *(((uint8_t *)(&pkt_data.freq_hz)) + 2);
dgabino 0:102b50f941d0 389 data[3] = *(((uint8_t *)(&pkt_data.freq_hz)) + 3);
dgabino 0:102b50f941d0 390 data[4] = *(((uint8_t *)(&pkt_data.tx_mode)));
dgabino 0:102b50f941d0 391 data[5] = PADDING;
dgabino 0:102b50f941d0 392 data[6] = PADDING;
dgabino 0:102b50f941d0 393 data[7] = PADDING;
dgabino 0:102b50f941d0 394 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 395 data[8] = *(((uint8_t *)(&pkt_data.count_us)));
dgabino 0:102b50f941d0 396 data[9] = *(((uint8_t *)(&pkt_data.count_us)) + 1);
dgabino 0:102b50f941d0 397 data[10] = *(((uint8_t *)(&pkt_data.count_us)) + 2);
dgabino 0:102b50f941d0 398 data[11] = *(((uint8_t *)(&pkt_data.count_us)) + 3);
dgabino 0:102b50f941d0 399 data[12] = *(((uint8_t *)(&pkt_data.rf_chain)));
dgabino 0:102b50f941d0 400 data[13] = *(((uint8_t *)(&pkt_data.rf_power)));
dgabino 0:102b50f941d0 401 data[14] = *(((uint8_t *)(&pkt_data.modulation)));
dgabino 0:102b50f941d0 402 data[15] = *(((uint8_t *)(&pkt_data.bandwidth)));
dgabino 0:102b50f941d0 403 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 404 data[16] = *(((uint8_t *)(&pkt_data.datarate)));
dgabino 0:102b50f941d0 405 data[17] = *(((uint8_t *)(&pkt_data.datarate)) + 1);
dgabino 0:102b50f941d0 406 data[18] = *(((uint8_t *)(&pkt_data.datarate)) + 2);
dgabino 0:102b50f941d0 407 data[19] = *(((uint8_t *)(&pkt_data.datarate)) + 3);
dgabino 0:102b50f941d0 408 data[20] = *(((uint8_t *)(&pkt_data.coderate)));
dgabino 0:102b50f941d0 409 data[21] = *(((uint8_t *)(&pkt_data.invert_pol)));
dgabino 0:102b50f941d0 410 data[22] = *(((uint8_t *)(&pkt_data.f_dev)));
dgabino 0:102b50f941d0 411 data[23] = PADDING;
dgabino 0:102b50f941d0 412 /* --- 64-bits start --- */
dgabino 0:102b50f941d0 413 data[24] = *(((uint8_t *)(&pkt_data.preamble)));
dgabino 0:102b50f941d0 414 data[25] = *(((uint8_t *)(&pkt_data.preamble)) + 1);
dgabino 0:102b50f941d0 415 data[26] = *(((uint8_t *)(&pkt_data.no_crc)));
dgabino 0:102b50f941d0 416 data[27] = *(((uint8_t *)(&pkt_data.no_header)));
dgabino 0:102b50f941d0 417 data[28] = *(((uint8_t *)(&pkt_data.size)));
dgabino 0:102b50f941d0 418 data[29] = *(((uint8_t *)(&pkt_data.size)) + 1);
dgabino 0:102b50f941d0 419 /* NO PADDING NEEDED HERE, END OF ARRAY */
dgabino 0:102b50f941d0 420 for (i = 0; i < 256; i++) {
dgabino 0:102b50f941d0 421 data[i + LGW_PKT_TX_METADATA_SIZE_ALIGNED] = *(((uint8_t *)(&pkt_data.payload)) + i);
dgabino 0:102b50f941d0 422 }
dgabino 0:102b50f941d0 423 size = sizeof(data) / sizeof(uint8_t);
dgabino 0:102b50f941d0 424
dgabino 0:102b50f941d0 425 /* prepare command */
dgabino 0:102b50f941d0 426 cmd.id = 'f';
dgabino 0:102b50f941d0 427 cmd.len_msb = (uint8_t)((size >> 8) & 0xFF);
dgabino 0:102b50f941d0 428 cmd.len_lsb = (uint8_t)((size >> 0) & 0xFF);
dgabino 0:102b50f941d0 429 cmd.address = 0;
dgabino 0:102b50f941d0 430 for (i = 0; i < size; i++) {
dgabino 0:102b50f941d0 431 cmd.cmd_data[i] = data[i];
dgabino 0:102b50f941d0 432 }
dgabino 0:102b50f941d0 433
dgabino 0:102b50f941d0 434 /* send command to MCU */
dgabino 0:102b50f941d0 435 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 436 if (x != LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 437 printf("ERROR: failed to send packet\n");
dgabino 0:102b50f941d0 438 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 439 }
dgabino 0:102b50f941d0 440
dgabino 0:102b50f941d0 441 /* check command acknoledge */
dgabino 0:102b50f941d0 442 if (ans.status != ACK_OK) {
dgabino 0:102b50f941d0 443 printf("ERROR: failed to send packet, ACK failed\n");
dgabino 0:102b50f941d0 444 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 445 }
dgabino 0:102b50f941d0 446
dgabino 0:102b50f941d0 447 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 448 }
dgabino 0:102b50f941d0 449
dgabino 0:102b50f941d0 450 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 451
dgabino 0:102b50f941d0 452 int lgw_mcu_get_trigcnt(uint32_t *data) {
dgabino 0:102b50f941d0 453 int x;
dgabino 0:102b50f941d0 454 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 455 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 456
dgabino 0:102b50f941d0 457 /* check input variables */
dgabino 0:102b50f941d0 458 CHECK_NULL(data);
dgabino 0:102b50f941d0 459
dgabino 0:102b50f941d0 460 /* prepare command */
dgabino 0:102b50f941d0 461 cmd.id = 'q';
dgabino 0:102b50f941d0 462 cmd.len_msb = 0;
dgabino 0:102b50f941d0 463 cmd.len_lsb = 0;
dgabino 0:102b50f941d0 464 cmd.address = 0;
dgabino 0:102b50f941d0 465
dgabino 0:102b50f941d0 466 /* send command to MCU */
dgabino 0:102b50f941d0 467 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 468 if ((x != LGW_COM_SUCCESS) || (ans.status != ACK_OK)) {
dgabino 0:102b50f941d0 469 DEBUG_MSG("ERROR: failed to get concentrator internal counter\n");
dgabino 0:102b50f941d0 470 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 471 }
dgabino 0:102b50f941d0 472
dgabino 0:102b50f941d0 473 *data = (ans.ans_data[0] << 24) + (ans.ans_data[1] << 16) + (ans.ans_data[2] << 8) + (ans.ans_data[3]);
dgabino 0:102b50f941d0 474 DEBUG_PRINTF("Note: sx1301 counter %u\n", *data);
dgabino 0:102b50f941d0 475
dgabino 0:102b50f941d0 476 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 477 }
dgabino 0:102b50f941d0 478
dgabino 0:102b50f941d0 479 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 480
dgabino 0:102b50f941d0 481 int lgw_mcu_commit_radio_calibration(uint8_t idx_start, uint8_t idx_nb) {
dgabino 0:102b50f941d0 482 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 483 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 484
dgabino 0:102b50f941d0 485 /* prepare command */
dgabino 0:102b50f941d0 486 cmd.id = 'j';
dgabino 0:102b50f941d0 487 cmd.len_msb = 0;
dgabino 0:102b50f941d0 488 cmd.len_lsb = 2;
dgabino 0:102b50f941d0 489 cmd.address = 0;
dgabino 0:102b50f941d0 490 cmd.cmd_data[0] = idx_start;
dgabino 0:102b50f941d0 491 cmd.cmd_data[1] = idx_nb;
dgabino 0:102b50f941d0 492
dgabino 0:102b50f941d0 493 /* send command to MCU */
dgabino 0:102b50f941d0 494 return lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 495 }
dgabino 0:102b50f941d0 496
dgabino 0:102b50f941d0 497 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 498
dgabino 0:102b50f941d0 499 int lgw_mcu_reset(void) {
dgabino 0:102b50f941d0 500 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 501 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 502
dgabino 0:102b50f941d0 503 /* prepare command */
dgabino 0:102b50f941d0 504 cmd.id = 'm';
dgabino 0:102b50f941d0 505 cmd.len_msb = 0;
dgabino 0:102b50f941d0 506 cmd.len_lsb = 0;
dgabino 0:102b50f941d0 507 cmd.address = 0;
dgabino 0:102b50f941d0 508
dgabino 0:102b50f941d0 509 /* send command to MCU */
dgabino 0:102b50f941d0 510 return lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 511 }
dgabino 0:102b50f941d0 512
dgabino 0:102b50f941d0 513 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 514
dgabino 0:102b50f941d0 515 int lgw_mcu_get_unique_id(uint8_t *uid) {
dgabino 0:102b50f941d0 516 int i, x;
dgabino 0:102b50f941d0 517 int fwversion = STM32FWVERSION;
dgabino 0:102b50f941d0 518 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 519 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 520
dgabino 0:102b50f941d0 521 /* prepare command */
dgabino 0:102b50f941d0 522 cmd.id = 'l';
dgabino 0:102b50f941d0 523 cmd.len_msb = 0;
dgabino 0:102b50f941d0 524 cmd.len_lsb = 4;
dgabino 0:102b50f941d0 525 cmd.address = 0;
dgabino 0:102b50f941d0 526 cmd.cmd_data[0] = (uint8_t)((fwversion >> 24) & (0x000000ff));
dgabino 0:102b50f941d0 527 cmd.cmd_data[1] = (uint8_t)((fwversion >> 16) & (0x000000ff));
dgabino 0:102b50f941d0 528 cmd.cmd_data[2] = (uint8_t)((fwversion >> 8) & (0x000000ff));
dgabino 0:102b50f941d0 529 cmd.cmd_data[3] = (uint8_t)((fwversion) & (0x000000ff));
dgabino 0:102b50f941d0 530
dgabino 0:102b50f941d0 531 /* send command to MCU */
dgabino 0:102b50f941d0 532 x = lgw_com_send_command(lgw_com_target, cmd, &ans);
dgabino 0:102b50f941d0 533 if (x != LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 534 DEBUG_MSG("ERROR: Failed to get MCU unique ID\n");
dgabino 0:102b50f941d0 535 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 536 }
dgabino 0:102b50f941d0 537
dgabino 0:102b50f941d0 538 /* Check MCU FW version */
dgabino 0:102b50f941d0 539 if (ans.status == ACK_KO) {
dgabino 0:102b50f941d0 540 DEBUG_MSG("ERROR: Invalid MCU firmware version\n");
dgabino 0:102b50f941d0 541 return LGW_MCU_ERROR;
dgabino 0:102b50f941d0 542 }
dgabino 0:102b50f941d0 543
dgabino 0:102b50f941d0 544 /* Get MCU unique ID */
dgabino 0:102b50f941d0 545 for (i = 0; i <= 7; i++) {
dgabino 0:102b50f941d0 546 uid[i] = ans.ans_data[i];
dgabino 0:102b50f941d0 547 }
dgabino 0:102b50f941d0 548
dgabino 0:102b50f941d0 549 return LGW_MCU_SUCCESS;
dgabino 0:102b50f941d0 550 }
dgabino 0:102b50f941d0 551
dgabino 0:102b50f941d0 552 /* --- EOF ------------------------------------------------------------------ */