Scan nearby anchors and send result for location engine.
Dependencies: modem_ref_helper DebouncedInterrupt
Diff: main.cpp
- Revision:
- 0:83836029943b
- Child:
- 1:4534345afb6b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Nov 13 13:40:28 2019 +0000 @@ -0,0 +1,257 @@ +// @autor: jeremie@wizzilab.com +// @date: 2017-05-02 + +#include "DebouncedInterrupt.h" +#include "modem_ref_helper.h" +#include "modem_callbacks.h" +#include "files.h" + +Semaphore button_user(0); +Semaphore modem_ready(0); +Semaphore user_ready(0); +Queue<void, 8> modem_resp; + +enum { + MODEM_RESP_NO, + MODEM_RESP_TERMINAL, + MODEM_RESP_ERROR, + MODEM_RESP_ACK, + MODEM_RESP_TIMEOUT, +}; + +alp_d7a_itf_t report_itf = { + .type = ALP_ITF_TYPE_D7A, + .cfg.to = 0, + .cfg.te = 0, + .cfg.qos.bf.resp = D7A_RESP_PREFERRED, + .cfg.qos.bf.retry = ALP_RPOL_ONESHOT, + .cfg.addressee.ctrl.bf.nls = D7A_NLS_AES_CCM_64, + .cfg.addressee.ctrl.bf.idf = D7A_ID_NOID, + .cfg.addressee.xcl.bf = {.s = 2, .m = 0x1}, +}; + +alp_d7a_itf_t scan_itf = { + .type = ALP_ITF_TYPE_D7A, + .cfg.to = 0, + .cfg.te = 0, + .cfg.qos.bf.resp = D7A_RESP_ALL, + .cfg.qos.bf.retry = ALP_RPOL_ONESHOT, + .cfg.addressee.ctrl.bf.nls = D7A_NLS_AES_CCM_64, + .cfg.addressee.ctrl.bf.idf = D7A_ID_NBID, + .cfg.addressee.xcl.bf = {.s = 2, .m = 0x1},// XXX D7A_XCL_GW, + .cfg.addressee.id[0] = D7A_CTF_ENCODE(8), +}; + +// Main Callback +void my_main_callback(uint8_t terminal, int8_t err, uint8_t id) +{ + (void)id; + + if (ALP_ERR_NONE != err) + { + modem_print_error(ALP_ITF_TYPE_D7A, err); + } + + if (terminal) + { + modem_ready.release(); + } +} + +// Response Callback +void my_response_callback(uint8_t terminal, int8_t err, uint8_t id) +{ + (void)id; + + if (ALP_ERR_NONE != err) + { + modem_print_error(ALP_ITF_TYPE_D7A, err); + } + + if (terminal) + { + modem_resp.put((void*)MODEM_RESP_TERMINAL); + } + else + { + if (ALP_ERR_NONE == err) + { + modem_resp.put((void*)MODEM_RESP_ACK); + } + else + { + modem_resp.put((void*)MODEM_RESP_ERROR); + } + } + + // Wait end of user processing before resuming + user_ready.acquire(); +} + +// Interrupt Service Routine on button press. +void button_push_isr( void ) +{ + button_user.release(); +} + +void button_user_thread() +{ + osEvent evt; + uint32_t resp; + d7a_sp_res_t istat; + fw_version_t fw_ver; + uint8_t nb = 0; + + uint8_t id = modem_get_id(my_response_callback); + uint8_t main_id = modem_get_id(my_main_callback); + + memset(&istat, 0, sizeof(d7a_sp_res_t)); + memset(&fw_ver, 0, sizeof(fw_version_t)); + + while (true) + { + // Wait for button press + PRINT("Press button to scan...\r\n"); + button_user.acquire(); + + nb = 0; + + PRINT("Scanning...\n"); + + // Any broadcast with response is fine + modem_remote_read_file((uint8_t*)&scan_itf, D7_ITF_SIZE(&scan_itf), (void*)&istat, D7A_FID_FIRMWARE_VERSION, (void*)&fw_ver, 12, sizeof(fw_version_t), id); + + do + { + // Wait for callback + evt = modem_resp.get(3000); + resp = (evt.status == osEventMessage)? (uint32_t)evt.value.p : MODEM_RESP_TIMEOUT; + + if (MODEM_RESP_ACK == resp) + { + // Print metadata + nb++; + PRINT("%d: XCL:%02X ", nb, istat.addressee.xcl.byte); + PRINT_DATA("UID:", "%02X", istat.addressee.id, D7A_UID_LEN, " "); + PRINT("snr:%d rxlev:%d lb:%d ", istat.snr, istat.rxlev, istat.lb); + PRINT("v%d.%d.%d\n", fw_ver.major, fw_ver.minor, fw_ver.patch); + + // Fill file + if (nb <= STATUS_MAX_DEVICES) + { + // Update number of devices + ram_fs_write(FID_STATUS, 0, sizeof(uint8_t), &nb); + // Add new Link budget + ram_fs_write(FID_STATUS, sizeof(uint8_t) + ((nb-1) * sizeof(device_t)), sizeof(uint8_t), &istat.lb); + // Add new UID + ram_fs_write(FID_STATUS, sizeof(uint8_t) + ((nb-1) * sizeof(device_t)) + sizeof(uint8_t), D7A_UID_LEN, istat.addressee.id); + } + + // Clear istatus buffer + memset(&istat, 0, sizeof(d7a_sp_res_t)); + + // Resume processing + user_ready.release(); + } + else if (MODEM_RESP_TIMEOUT == resp) + { + // Could be because of the RF duty cycle, + // especialy after boot where the duty credit is near 0. + // The only thing to do is wait. + // The transmission will resume once some duty credit is available. + PRINT("WAITING...\n"); + } + else if (MODEM_RESP_ERROR == resp) + { + PRINT("ERROR.\n"); + + // Resume processing + user_ready.release(); + } + else if (MODEM_RESP_TERMINAL == resp) + { + PRINT("DONE.\n"); + + // Resume processing + user_ready.release(); + } + + } while (MODEM_RESP_TERMINAL != resp); + + // Send list + status_t status; + ram_fs_read(FID_STATUS, 0, sizeof(uint8_t), (uint8_t*)&status.nb); + ram_fs_read(FID_STATUS, 0, sizeof(uint8_t) + (status.nb * sizeof(device_t)), (uint8_t*)&status); + modem_send_file_content((uint8_t*)&report_itf, D7_ITF_SIZE(&report_itf), NULL, FID_STATUS, &status, 0, sizeof(uint8_t) + (status.nb * sizeof(device_t)), main_id); + modem_ready.acquire(); + } +} + +modem_callbacks_t callbacks = { + .read = my_read, + .write = my_write, + .read_fprop = my_read_fprop, + .flush = my_flush, + .remove = my_delete, + .udata = my_udata, + .lqual = my_lqual, + .ldown = my_ldown, + .reset = my_reset, + .boot = my_boot, + .busy = my_busy, + .itf_busy = NULL, +}; + + +/*** Main function ------------------------------------------------------------- ***/ +int main() +{ + // Start & initialize + DBG_OPEN(DEBUG_LED); + + PRINT("\n" + "-----------------------------------------\n" + "------------- Demo Localisation ---------\n" + "-----------------------------------------\n"); + + modem_helper_open(&callbacks); + + uint8_t id = modem_get_id(my_main_callback); + + PRINT("Register Files\n"); + // This is a local file. As we want to check the outcome of sending + // this, don't use D7AActP Notification but rather plain ALP ITF Forwarding. + // Declaration just allows remote access. + modem_update_file(FID_STATUS, (alp_file_header_t*)&h_status, (uint8_t*)&f_status); + + PRINT("Start D7A Stack\n"); + modem_activate_itf(ALP_ITF_TYPE_D7A, 24, 0, ALP_D7A_ISTAT_RESP | ALP_D7A_ISTAT_UNS | ALP_D7A_ISTAT_EOP, true, id); + modem_ready.acquire(); + + PRINT("Notify Modem Version\n"); + modem_notify_file(D7A_FID_FIRMWARE_VERSION, 0, SIZE_HOST_REV, id); + modem_ready.acquire(); + + PRINT("Notify FW Version\n"); + uint8_t default_root_key[16] = DEFAULT_ROOT_KEY; + modem_notify_host_rev(&f_rev, &h_rev, default_root_key); + + modem_free_id(id); + + DebouncedInterrupt user_interrupt(DEBUG_BUTTON); + user_interrupt.attach(button_push_isr, IRQ_FALL, 500, true); + + Thread but_th(osPriorityNormal, 2048, NULL); + osStatus status = but_th.start(button_user_thread); + ASSERT(status == osOK, "Failed to start but thread (err: %d)\r\n", status); + + DigitalOut my_led(DEBUG_LED); + + // Set main task to lowest priority + osThreadSetPriority(osThreadGetId(), osPriorityLow); + while(true) + { + ThisThread::sleep_for(500); + my_led = !my_led; + } +} \ No newline at end of file