Scan example on D7-LoRa

Dependencies:   modem_ref_helper DebouncedInterrupt

Committer:
Jeej
Date:
Tue Jun 12 15:15:54 2018 +0000
Revision:
1:27716ee59ca4
Parent:
0:6703784ff93e
Child:
2:de388004dca6
Possibility to choose between D7 LoRa and D7 FSK.; Possibility to disable Duty Cycle limit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 0:6703784ff93e 1 // @autor: jeremie@wizzilab.com
Jeej 0:6703784ff93e 2 // @date: 2017-05-02
Jeej 0:6703784ff93e 3
Jeej 0:6703784ff93e 4 #include "DebouncedInterrupt.h"
Jeej 0:6703784ff93e 5 #include "modem_ref_helper.h"
Jeej 0:6703784ff93e 6 #include "modem_callbacks.h"
Jeej 0:6703784ff93e 7
Jeej 1:27716ee59ca4 8 #if 1
Jeej 1:27716ee59ca4 9 // Use D7 LoRa
Jeej 1:27716ee59ca4 10 #define XCL_DL d7lora_dl_xcl
Jeej 1:27716ee59ca4 11 #define XCL_UL d7lora_ul_xcl
Jeej 1:27716ee59ca4 12 #else
Jeej 1:27716ee59ca4 13 // Use D7 FSK
Jeej 1:27716ee59ca4 14 #define XCL_DL d7fsk_dl_xcl
Jeej 1:27716ee59ca4 15 #define XCL_UL d7fsk_ul_xcl
Jeej 1:27716ee59ca4 16 #endif
Jeej 1:27716ee59ca4 17
Jeej 1:27716ee59ca4 18 #if 1
Jeej 1:27716ee59ca4 19 // Disable Duty Cycle
Jeej 1:27716ee59ca4 20 #define DUTY 255
Jeej 1:27716ee59ca4 21 #else
Jeej 1:27716ee59ca4 22 // Use default Duty Cycle
Jeej 1:27716ee59ca4 23 #define DUTY D7A_CTF_ENCODE(31)
Jeej 1:27716ee59ca4 24 #endif
Jeej 1:27716ee59ca4 25
Jeej 0:6703784ff93e 26 #define MY_POLICY_IDX 0
Jeej 0:6703784ff93e 27
Jeej 0:6703784ff93e 28 Semaphore button_user(0);
Jeej 0:6703784ff93e 29 Semaphore modem_ready(0);
Jeej 0:6703784ff93e 30 Queue<void, 8> modem_resp;
Jeej 0:6703784ff93e 31
Jeej 0:6703784ff93e 32 enum {
Jeej 0:6703784ff93e 33 MODEM_RESP_NO,
Jeej 0:6703784ff93e 34 MODEM_RESP_TERMINAL,
Jeej 0:6703784ff93e 35 MODEM_RESP_DONE,
Jeej 0:6703784ff93e 36 };
Jeej 0:6703784ff93e 37
Jeej 1:27716ee59ca4 38 // This discribes the retry policy of the stack for each packet
Jeej 1:27716ee59ca4 39 // Do not modify uncommented parameters
Jeej 0:6703784ff93e 40 alp_retry_policy_t my_policy = {
Jeej 0:6703784ff93e 41 .meta.procedure = 0,
Jeej 0:6703784ff93e 42 .meta.respond = true,
Jeej 0:6703784ff93e 43 .meta.persistant = false,
Jeej 0:6703784ff93e 44 .meta.bulk = false,
Jeej 0:6703784ff93e 45 .depth = 1,
Jeej 1:27716ee59ca4 46 .retries = 0, // The stack will retry x times (each packet will be sent a maximum of x+1 times)
Jeej 1:27716ee59ca4 47 .slot_time = 0 // Interval between retries in seconds
Jeej 0:6703784ff93e 48 };
Jeej 0:6703784ff93e 49
Jeej 1:27716ee59ca4 50 uint8_t g_main_id;
Jeej 1:27716ee59ca4 51
Jeej 1:27716ee59ca4 52 d7a_xcl_t d7fsk_dl_xcl = { .bf.s = 0, .bf.m = 1 };
Jeej 1:27716ee59ca4 53 d7a_xcl_t d7fsk_ul_xcl = { .bf.s = 2, .bf.m = 1 };
Jeej 1:27716ee59ca4 54
Jeej 1:27716ee59ca4 55 d7a_xcl_t d7lora_dl_xcl = { .bf.s = 8, .bf.m = 1 };
Jeej 1:27716ee59ca4 56 d7a_xcl_t d7lora_ul_xcl = { .bf.s = 9, .bf.m = 1 };
Jeej 1:27716ee59ca4 57
Jeej 0:6703784ff93e 58 alp_d7a_itf_t my_itf = {
Jeej 0:6703784ff93e 59 .type = ALP_ITF_TYPE_D7A,
Jeej 0:6703784ff93e 60 .cfg.to = 0,
Jeej 0:6703784ff93e 61 .cfg.te = 0,
Jeej 0:6703784ff93e 62 .cfg.qos.bf.resp = D7A_RESP_ALL,
Jeej 0:6703784ff93e 63 .cfg.qos.bf.retry = MY_POLICY_IDX,
Jeej 0:6703784ff93e 64 .cfg.addressee.ctrl.bf.nls = D7A_NLS_AES_CCM_64,
Jeej 0:6703784ff93e 65 .cfg.addressee.ctrl.bf.idf = D7A_ID_NBID,
Jeej 1:27716ee59ca4 66 .cfg.addressee.xcl = XCL_UL,
Jeej 0:6703784ff93e 67 .cfg.addressee.id[0] = D7A_CTF_VAL(4,0),
Jeej 0:6703784ff93e 68 };
Jeej 0:6703784ff93e 69
Jeej 0:6703784ff93e 70 void print_status(int status)
Jeej 0:6703784ff93e 71 {
Jeej 0:6703784ff93e 72 switch (status)
Jeej 0:6703784ff93e 73 {
Jeej 0:6703784ff93e 74 case ALP_ERR_NONE:
Jeej 0:6703784ff93e 75 //PRINT("Status: OK\n");
Jeej 0:6703784ff93e 76 break;
Jeej 0:6703784ff93e 77 case ALP_ERR_FILE_EXIST:
Jeej 0:6703784ff93e 78 PRINT("Status: Already registered\n");
Jeej 0:6703784ff93e 79 break;
Jeej 0:6703784ff93e 80 default:
Jeej 0:6703784ff93e 81 PRINT("Status: error %d\n", status);
Jeej 0:6703784ff93e 82 break;
Jeej 0:6703784ff93e 83 }
Jeej 0:6703784ff93e 84 }
Jeej 0:6703784ff93e 85
Jeej 0:6703784ff93e 86 void print_resp(int status)
Jeej 0:6703784ff93e 87 {
Jeej 0:6703784ff93e 88 switch (status)
Jeej 0:6703784ff93e 89 {
Jeej 0:6703784ff93e 90 case ALP_ERR_NONE:
Jeej 0:6703784ff93e 91 //PRINT("Resp: OK\n");
Jeej 0:6703784ff93e 92 break;
Jeej 0:6703784ff93e 93 case ALP_ERR_FILE_EXIST:
Jeej 0:6703784ff93e 94 PRINT("Resp: Already registered\n");
Jeej 0:6703784ff93e 95 break;
Jeej 0:6703784ff93e 96 default:
Jeej 0:6703784ff93e 97 PRINT("Resp: error %d\n", status);
Jeej 0:6703784ff93e 98 break;
Jeej 0:6703784ff93e 99 }
Jeej 0:6703784ff93e 100 }
Jeej 0:6703784ff93e 101
Jeej 0:6703784ff93e 102 // Callback for broadcast read
Jeej 0:6703784ff93e 103 void my_read_response_callback(uint8_t terminal, int8_t err, uint8_t id)
Jeej 0:6703784ff93e 104 {
Jeej 0:6703784ff93e 105 (void)id;
Jeej 0:6703784ff93e 106
Jeej 0:6703784ff93e 107 if (terminal)
Jeej 0:6703784ff93e 108 {
Jeej 0:6703784ff93e 109 print_status(err);
Jeej 0:6703784ff93e 110 modem_resp.put((void*)MODEM_RESP_TERMINAL);
Jeej 0:6703784ff93e 111 }
Jeej 0:6703784ff93e 112 else
Jeej 0:6703784ff93e 113 {
Jeej 0:6703784ff93e 114 print_resp(err);
Jeej 0:6703784ff93e 115 if (ALP_ERR_NONE == err)
Jeej 0:6703784ff93e 116 {
Jeej 0:6703784ff93e 117 modem_resp.put((void*)MODEM_RESP_DONE);
Jeej 0:6703784ff93e 118 }
Jeej 0:6703784ff93e 119 }
Jeej 0:6703784ff93e 120 }
Jeej 0:6703784ff93e 121
Jeej 0:6703784ff93e 122 // Interrupt Service Routine on button press.
Jeej 0:6703784ff93e 123 void button_push_isr( void )
Jeej 0:6703784ff93e 124 {
Jeej 0:6703784ff93e 125 button_user.release();
Jeej 0:6703784ff93e 126 }
Jeej 0:6703784ff93e 127
Jeej 0:6703784ff93e 128 void button_user_thread()
Jeej 0:6703784ff93e 129 {
Jeej 0:6703784ff93e 130 FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:6703784ff93e 131
Jeej 0:6703784ff93e 132 osEvent evt;
Jeej 0:6703784ff93e 133 uint32_t resp;
Jeej 0:6703784ff93e 134 d7a_sp_res_t istat;
Jeej 0:6703784ff93e 135 fw_version_t fw_ver;
Jeej 0:6703784ff93e 136 uint8_t nb = 0;
Jeej 0:6703784ff93e 137
Jeej 0:6703784ff93e 138 uint8_t my_user_id = modem_get_id(my_read_response_callback);
Jeej 0:6703784ff93e 139
Jeej 1:27716ee59ca4 140 uint8_t scan_xcl[] = { XCL_DL.byte, XCL_UL.byte };
Jeej 0:6703784ff93e 141
Jeej 0:6703784ff93e 142 memset(&istat, 0, sizeof(d7a_sp_res_t));
Jeej 0:6703784ff93e 143 memset(&fw_ver, 0, sizeof(fw_version_t));
Jeej 0:6703784ff93e 144
Jeej 0:6703784ff93e 145 while (true)
Jeej 0:6703784ff93e 146 {
Jeej 0:6703784ff93e 147 // Wait for button press
Jeej 0:6703784ff93e 148 PRINT("Press button to scan...\r\n");
Jeej 0:6703784ff93e 149 button_user.wait();
Jeej 0:6703784ff93e 150
Jeej 0:6703784ff93e 151 for (uint8_t i = 0; i < sizeof(scan_xcl); i++)
Jeej 0:6703784ff93e 152 {
Jeej 0:6703784ff93e 153 nb = 0;
Jeej 0:6703784ff93e 154 my_itf.cfg.addressee.xcl.byte = scan_xcl[i];
Jeej 0:6703784ff93e 155
Jeej 0:6703784ff93e 156 PRINT("Scanning XCL 0x%02X...\n", my_itf.cfg.addressee.xcl.byte);
Jeej 0:6703784ff93e 157
Jeej 0:6703784ff93e 158 modem_remote_read_file((uint8_t*)&my_itf, D7_ITF_SIZE(&my_itf), (void*)&istat, D7A_FID_FIRMWARE_VERSION, (void*)&fw_ver, 12, sizeof(fw_version_t), my_user_id);
Jeej 0:6703784ff93e 159
Jeej 0:6703784ff93e 160 do
Jeej 0:6703784ff93e 161 {
Jeej 0:6703784ff93e 162 evt = modem_resp.get();
Jeej 0:6703784ff93e 163 resp = (evt.status == osEventMessage)? (uint32_t)evt.value.p : MODEM_RESP_NO;
Jeej 0:6703784ff93e 164
Jeej 0:6703784ff93e 165 if (MODEM_RESP_DONE == resp)
Jeej 0:6703784ff93e 166 {
Jeej 0:6703784ff93e 167 nb++;
Jeej 0:6703784ff93e 168 PRINT("%d: XCL:%02X ", nb, istat.addressee.xcl.byte);
Jeej 0:6703784ff93e 169 PRINT_DATA("UID:", "%02X", istat.addressee.id, 8, " ");
Jeej 0:6703784ff93e 170 PRINT("snr:%d rxlev:%d lb:%d ", istat.snr, istat.rxlev, istat.lb);
Jeej 0:6703784ff93e 171 PRINT("v%d.%d.%d\n", fw_ver.major, fw_ver.minor, fw_ver.patch);
Jeej 0:6703784ff93e 172
Jeej 0:6703784ff93e 173 // Reset variables
Jeej 0:6703784ff93e 174 memset(&istat, 0, sizeof(d7a_sp_res_t));
Jeej 0:6703784ff93e 175 memset(&fw_ver, 0, sizeof(fw_version_t));
Jeej 0:6703784ff93e 176 }
Jeej 0:6703784ff93e 177
Jeej 0:6703784ff93e 178 } while (MODEM_RESP_TERMINAL != resp);
Jeej 0:6703784ff93e 179 }
Jeej 0:6703784ff93e 180
Jeej 0:6703784ff93e 181 PRINT("Done.\n");
Jeej 0:6703784ff93e 182 }
Jeej 0:6703784ff93e 183 }
Jeej 0:6703784ff93e 184
Jeej 0:6703784ff93e 185 modem_callbacks_t callbacks = {
Jeej 0:6703784ff93e 186 .read = my_read,
Jeej 0:6703784ff93e 187 .write = my_write,
Jeej 0:6703784ff93e 188 .read_fprop = my_read_fprop,
Jeej 0:6703784ff93e 189 .flush = my_flush,
Jeej 0:6703784ff93e 190 .remove = my_delete,
Jeej 0:6703784ff93e 191 .udata = my_udata,
Jeej 0:6703784ff93e 192 .lqual = my_lqual,
Jeej 0:6703784ff93e 193 .ldown = my_ldown,
Jeej 0:6703784ff93e 194 .reset = my_reset,
Jeej 0:6703784ff93e 195 .boot = my_boot
Jeej 0:6703784ff93e 196 };
Jeej 0:6703784ff93e 197
Jeej 0:6703784ff93e 198 // Callback for g_main_id User
Jeej 0:6703784ff93e 199 void my_main_callback(uint8_t terminal, int8_t err, uint8_t id)
Jeej 0:6703784ff93e 200 {
Jeej 0:6703784ff93e 201 (void)id;
Jeej 0:6703784ff93e 202
Jeej 0:6703784ff93e 203 if (terminal)
Jeej 0:6703784ff93e 204 {
Jeej 0:6703784ff93e 205 print_status(err);
Jeej 0:6703784ff93e 206 modem_ready.release();
Jeej 0:6703784ff93e 207 }
Jeej 0:6703784ff93e 208 else
Jeej 0:6703784ff93e 209 {
Jeej 0:6703784ff93e 210 print_resp(err);
Jeej 0:6703784ff93e 211 }
Jeej 0:6703784ff93e 212 }
Jeej 0:6703784ff93e 213
Jeej 0:6703784ff93e 214 /*** Main function ------------------------------------------------------------- ***/
Jeej 0:6703784ff93e 215 int main()
Jeej 0:6703784ff93e 216 {
Jeej 0:6703784ff93e 217 // Start & initialize
Jeej 0:6703784ff93e 218 #ifdef DEBUG_LED
Jeej 0:6703784ff93e 219 DBG_OPEN(DEBUG_LED);
Jeej 0:6703784ff93e 220 #else
Jeej 0:6703784ff93e 221 DBG_OPEN(NC);
Jeej 0:6703784ff93e 222 #endif
Jeej 0:6703784ff93e 223 PRINT("\n"
Jeej 0:6703784ff93e 224 "-----------------------------------------\n"
Jeej 1:27716ee59ca4 225 "-------------- Demo D7A LoRa ------------\n"
Jeej 0:6703784ff93e 226 "-----------------------------------------\n");
Jeej 0:6703784ff93e 227
Jeej 0:6703784ff93e 228 FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:6703784ff93e 229
Jeej 0:6703784ff93e 230 modem_helper_open(&callbacks);
Jeej 0:6703784ff93e 231
Jeej 0:6703784ff93e 232 g_main_id = modem_get_id(my_main_callback);
Jeej 0:6703784ff93e 233
Jeej 0:6703784ff93e 234 // Set custom retry policy
Jeej 0:6703784ff93e 235 // XXX Won't work the first time as we need to reboot the modem for the changes to be applied
Jeej 0:6703784ff93e 236 // Check current retry policy
Jeej 0:6703784ff93e 237 alp_retry_policy_t old;
Jeej 0:6703784ff93e 238 modem_read_file(WM_FID_ALP_CFG, &old, MY_POLICY_IDX * sizeof(alp_retry_policy_t), sizeof(alp_retry_policy_t), g_main_id);
Jeej 0:6703784ff93e 239 modem_ready.wait();
Jeej 0:6703784ff93e 240 if (memcmp(&old, &my_policy, sizeof(alp_retry_policy_t)))
Jeej 0:6703784ff93e 241 {
Jeej 0:6703784ff93e 242 // Update retry policy
Jeej 0:6703784ff93e 243 modem_write_file(WM_FID_ALP_CFG, &my_policy, MY_POLICY_IDX * sizeof(alp_retry_policy_t), sizeof(alp_retry_policy_t), g_main_id);
Jeej 0:6703784ff93e 244 modem_ready.wait();
Jeej 0:6703784ff93e 245 modem_flush_file(WM_FID_ALP_CFG, g_main_id);
Jeej 0:6703784ff93e 246 modem_ready.wait();
Jeej 0:6703784ff93e 247
Jeej 0:6703784ff93e 248 // Reboot
Jeej 0:6703784ff93e 249 PRINT("Rebooting to apply new retry policy\n");
Jeej 0:6703784ff93e 250 my_reset();
Jeej 0:6703784ff93e 251 }
Jeej 0:6703784ff93e 252
Jeej 1:27716ee59ca4 253 // Put modem to listen to downlink access class
Jeej 1:27716ee59ca4 254 modem_write_file(D7A_FID_DLL_CFG, &XCL_DL, offsetof(d7a_dll_cfg_t, xcl), sizeof(d7a_xcl_t), g_main_id);
Jeej 1:27716ee59ca4 255 modem_ready.wait();
Jeej 1:27716ee59ca4 256
Jeej 1:27716ee59ca4 257 // Configure interfaces to use uplink access class
Jeej 1:27716ee59ca4 258 modem_write_file(FID_D7A_ITF0, &XCL_UL, offsetof(alp_d7a_itf_t, cfg.addressee.xcl), sizeof(d7a_xcl_t), g_main_id);
Jeej 1:27716ee59ca4 259 modem_ready.wait();
Jeej 1:27716ee59ca4 260
Jeej 1:27716ee59ca4 261 modem_write_file(FID_D7A_ITF1, &XCL_UL, offsetof(alp_d7a_itf_t, cfg.addressee.xcl), sizeof(d7a_xcl_t), g_main_id);
Jeej 1:27716ee59ca4 262 modem_ready.wait();
Jeej 1:27716ee59ca4 263
Jeej 1:27716ee59ca4 264 modem_write_file(FID_D7A_ITF2, &XCL_UL, offsetof(alp_d7a_itf_t, cfg.addressee.xcl), sizeof(d7a_xcl_t), g_main_id);
Jeej 0:6703784ff93e 265 modem_ready.wait();
Jeej 0:6703784ff93e 266
Jeej 1:27716ee59ca4 267 modem_write_file(FID_D7A_ITF3, &XCL_UL, offsetof(alp_d7a_itf_t, cfg.addressee.xcl), sizeof(d7a_xcl_t), g_main_id);
Jeej 1:27716ee59ca4 268 modem_ready.wait();
Jeej 1:27716ee59ca4 269
Jeej 1:27716ee59ca4 270 // Configure duty
Jeej 1:27716ee59ca4 271 d7a_ctf_t duty = { .byte = DUTY };
Jeej 1:27716ee59ca4 272 for (int i = 0; i < 8; i++)
Jeej 1:27716ee59ca4 273 {
Jeej 1:27716ee59ca4 274 modem_write_file(D7A_FID_ACCESS_PROFILE_0 + XCL_DL.bf.s, &duty, offsetof(d7a_access_profile_t, sb[0].duty) + (i * sizeof(d7a_subband_t)), sizeof(d7a_ctf_t), g_main_id);
Jeej 1:27716ee59ca4 275 modem_ready.wait();
Jeej 1:27716ee59ca4 276 }
Jeej 1:27716ee59ca4 277
Jeej 1:27716ee59ca4 278 for (int i = 0; i < 8; i++)
Jeej 1:27716ee59ca4 279 {
Jeej 1:27716ee59ca4 280 modem_write_file(D7A_FID_ACCESS_PROFILE_0 + XCL_UL.bf.s, &duty, offsetof(d7a_access_profile_t, sb[0].duty) + (i * sizeof(d7a_subband_t)), sizeof(d7a_ctf_t), g_main_id);
Jeej 1:27716ee59ca4 281 modem_ready.wait();
Jeej 1:27716ee59ca4 282 }
Jeej 1:27716ee59ca4 283
Jeej 0:6703784ff93e 284 PRINT("Start D7A Stack\n");
Jeej 0:6703784ff93e 285 modem_activate_itf(ALP_ITF_TYPE_D7A, 24, 0, ALP_D7A_ISTAT_RESP | ALP_D7A_ISTAT_UNS, true, g_main_id);
Jeej 0:6703784ff93e 286 modem_ready.wait();
Jeej 0:6703784ff93e 287
Jeej 0:6703784ff93e 288 #ifdef DEBUG_BUTTON
Jeej 0:6703784ff93e 289 DebouncedInterrupt user_interrupt(DEBUG_BUTTON);
Jeej 0:6703784ff93e 290 user_interrupt.attach(button_push_isr, IRQ_FALL, 500, true);
Jeej 0:6703784ff93e 291
Jeej 0:6703784ff93e 292 Thread but_th(osPriorityNormal, 2048, NULL);
Jeej 0:6703784ff93e 293 osStatus status = but_th.start(button_user_thread);
Jeej 0:6703784ff93e 294 ASSERT(status == osOK, "Failed to start but thread (err: %d)\r\n", status);
Jeej 0:6703784ff93e 295 #else
Jeej 0:6703784ff93e 296 #error You need a button to use this APP as is
Jeej 0:6703784ff93e 297 #endif
Jeej 0:6703784ff93e 298
Jeej 0:6703784ff93e 299 #ifdef DEBUG_LED
Jeej 0:6703784ff93e 300 DigitalOut my_led(DEBUG_LED);
Jeej 0:6703784ff93e 301 #endif
Jeej 0:6703784ff93e 302
Jeej 0:6703784ff93e 303 // Set main task to lowest priority
Jeej 0:6703784ff93e 304 osThreadSetPriority(osThreadGetId(), osPriorityIdle);
Jeej 0:6703784ff93e 305 while(true)
Jeej 0:6703784ff93e 306 {
Jeej 0:6703784ff93e 307 Thread::wait(500);
Jeej 0:6703784ff93e 308 #ifdef DEBUG_LED
Jeej 0:6703784ff93e 309 my_led = !my_led;
Jeej 0:6703784ff93e 310 #endif
Jeej 0:6703784ff93e 311 }
Jeej 0:6703784ff93e 312 }