WizziLab / Mbed 2 deprecated D7A_1x_TRAINING

Dependencies:   X_NUCLEO_IKS01A1 d7a_1x mbed-rtos mbed wizzi-utils

Files at this revision

API Documentation at this revision

Comitter:
mikl_andre
Date:
Mon Nov 21 07:24:34 2016 +0000
Commit message:
Initial Revision

Changed in this revision

X_NUCLEO_IKS01A1.lib Show annotated file Show diff for this revision Revisions of this file
d7a_1x.lib Show annotated file Show diff for this revision Revisions of this file
files.cpp Show annotated file Show diff for this revision Revisions of this file
files.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
sensors.cpp Show annotated file Show diff for this revision Revisions of this file
sensors.h Show annotated file Show diff for this revision Revisions of this file
simul.cpp Show annotated file Show diff for this revision Revisions of this file
simul.h Show annotated file Show diff for this revision Revisions of this file
wizzi-utils.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 429446fe396d X_NUCLEO_IKS01A1.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IKS01A1.lib	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/WizziLab/code/X_NUCLEO_IKS01A1/#bd74c33ecbbd
diff -r 000000000000 -r 429446fe396d d7a_1x.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/d7a_1x.lib	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/WizziLab/code/d7a_1x/#f71421d35d0b
diff -r 000000000000 -r 429446fe396d files.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/files.cpp	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,170 @@
+#include "files.h"
+#include "dbg.h"
+#include "sensors.h"
+
+GENERIC_FILE_INIT(dev_rev,
+    .rev.manufacturer_id     = 0x01BC50C7,
+    /// Device ID: Arbitrary number, at user/customer choice
+    .rev.device_id           = 0x00000010,
+    /// Hardware Board ID:
+    .rev.hw_version          = 0x00000152,
+    /// Firmware Version: made of
+    ///  - major,minor and patch indexes
+    ///  - fw_id : "build-flavour"
+    ///  FW_ID | MAJOR | MINOR | PATCH | HASH |
+    //     1B  |  1B   |  1B   |   2B  |  4B  |
+#if _SENSORS_SIMU_
+    .rev.fw_version.id       = 1,
+#else
+    .rev.fw_version.id       = 0,
+#endif
+    .rev.fw_version.major    = 1,
+    .rev.fw_version.minor    = 0,
+    .rev.fw_version.patch    = 0,
+    .rev.fw_version.hash     = 0x00000000,
+    /// "file-system" signature
+    .rev.fs_crc              = 0x00000000,
+);
+
+
+GENERIC_FILE_INIT(simul,
+    .divider = 500, // Boot value
+);
+
+
+GENERIC_FILE_INIT(mag_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 300,
+    .cfg.max_diff = 100,
+    .cfg.threshold_high = 1000,
+    .cfg.threshold_low = -1000,
+);
+    
+GENERIC_FILE_INIT(acc_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 300,
+    .cfg.max_diff = 100,
+    .cfg.threshold_high = 500,
+    .cfg.threshold_low = -500,
+);
+
+GENERIC_FILE_INIT(gyr_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 300,
+    .cfg.max_diff = 1000,
+    .cfg.threshold_high = 10000,
+    .cfg.threshold_low = -10000,
+);
+
+GENERIC_FILE_INIT(pre_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 60,
+    .cfg.max_diff = 100,
+    .cfg.threshold_high = 120000,
+    .cfg.threshold_low = 90000,
+);
+
+GENERIC_FILE_INIT(hum_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 60,
+    .cfg.max_diff = 100,
+    .cfg.threshold_high = 7000,
+    .cfg.threshold_low = 3000,
+);
+
+GENERIC_FILE_INIT(tem1_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 60,
+    .cfg.max_diff = 100,
+    .cfg.threshold_high = 3500,
+    .cfg.threshold_low = 2000,
+);
+
+GENERIC_FILE_INIT(tem2_cfg,
+    .cfg.report_type = REPORT_ON_DIFFERENCE,
+    .cfg.period = 1000,
+    .cfg.max_period = 60,
+    .cfg.max_diff = 100,
+    .cfg.threshold_high = 9000,
+    .cfg.threshold_low = 7000,
+);
+
+#define FILE_QTY    8
+
+static const void* file_map[FILE_QTY][2] = {
+    GENERIC_FILE_MAP(MAG_CFG_FILE_ID, mag_cfg),
+    GENERIC_FILE_MAP(ACC_CFG_FILE_ID, acc_cfg),
+    GENERIC_FILE_MAP(GYR_CFG_FILE_ID, gyr_cfg),
+    GENERIC_FILE_MAP(PRE_CFG_FILE_ID, pre_cfg),
+    GENERIC_FILE_MAP(HUM_CFG_FILE_ID, hum_cfg),
+    GENERIC_FILE_MAP(TEM1_CFG_FILE_ID, tem1_cfg),
+    GENERIC_FILE_MAP(TEM2_CFG_FILE_ID, tem2_cfg),
+    GENERIC_FILE_MAP(SIMUL_FILE_ID, simul),
+};
+
+void* file_get( uint8_t file_id )
+{    
+    for (uint8_t i=0 ; i<FILE_QTY ; i++)
+    {
+        if ((uint8_t)file_map[i][0] == file_id)
+        {
+            return (void*)file_map[i][1];
+        }
+    }
+    
+    ASSERT(false, "File %d does not exist\r\n");
+    
+    return NULL;
+}
+
+uint32_t fs_write_file(const uint8_t file_id,
+                        const uint16_t offset,
+                        const uint16_t size,
+                        const uint8_t* const content)
+{
+    uint32_t file = 0;
+    
+    DPRINT("WF %d\r\n", file_id);
+        
+    // Retrieve pointer to file
+    file = (uint32_t)file_get(file_id);
+        
+    if (!file)
+    {
+        return 0;
+    }
+    
+    // Write the new data
+    memcpy((void*)(file+offset), (void*)content, size);
+  
+    return size;
+}
+
+uint32_t fs_read_file( const uint8_t file_id,
+                        const uint16_t offset,
+                        const uint16_t size,
+                        uint8_t* buf)
+{
+    uint32_t file = 0;
+    
+    DPRINT("RF %d\r\n", file_id);
+    
+    // Retrieve pointer to file
+    file = (uint32_t)file_get(file_id);
+    
+    if (!file)
+    {
+        return 0;
+    }
+    
+    // Read data
+    memcpy((void*)buf, (void*)(file+offset), size);
+    
+    return size;
+}
diff -r 000000000000 -r 429446fe396d files.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/files.h	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,66 @@
+#ifndef _FILES_H_
+#define _FILES_H_
+
+#include "mbed.h"
+#include "d7a.h"
+#include "sensors.h"
+
+
+enum {
+    ALARM_FILE_ID = 224,
+    SIMUL_FILE_ID,
+        
+    MAG_CFG_FILE_ID = 240,
+    ACC_CFG_FILE_ID,
+    GYR_CFG_FILE_ID,
+    PRE_CFG_FILE_ID,  // 243
+    HUM_CFG_FILE_ID,
+    TEM1_CFG_FILE_ID,
+    TEM2_CFG_FILE_ID,
+    MAG_VALUE_FILE_ID, // 247
+    ACC_VALUE_FILE_ID,
+    GYR_VALUE_FILE_ID,
+    PRE_VALUE_FILE_ID, // 250
+    HUM_VALUE_FILE_ID,
+    TEM1_VALUE_FILE_ID,
+    TEM2_VALUE_FILE_ID, // 253
+};
+
+
+#define GENERIC_FILE(name,data)         TYPEDEF_STRUCT_PACKED{\
+                                            data\
+                                        } name##_t;\
+                                        extern name##_t f_##name;
+                                    
+#define GENERIC_FILE_INIT(name,...)     name##_t f_##name = {\
+                                            __VA_ARGS__\
+                                        }
+                                        
+#define GENERIC_FILE_MAP(fid,name)      { (void*)fid, (void*)&f_##name }
+
+
+
+// Firmware revision for the Dash7board
+GENERIC_FILE(dev_rev, d7a_revision_t rev;);
+
+GENERIC_FILE(simul, uint32_t divider;);
+
+GENERIC_FILE(mag_cfg, sensor_config_t cfg;);
+GENERIC_FILE(acc_cfg, sensor_config_t cfg;);
+GENERIC_FILE(gyr_cfg, sensor_config_t cfg;);
+GENERIC_FILE(pre_cfg, sensor_config_t cfg;);
+GENERIC_FILE(hum_cfg, sensor_config_t cfg;);
+GENERIC_FILE(tem1_cfg, sensor_config_t cfg;);
+GENERIC_FILE(tem2_cfg, sensor_config_t cfg;);
+
+uint32_t fs_write_file(const uint8_t file_id,
+                        const uint16_t offset,
+                        const uint16_t size,
+                        const uint8_t* const content);
+                        
+uint32_t fs_read_file( const uint8_t file_id,
+                        const uint16_t offset,
+                        const uint16_t size,
+                        uint8_t* buf);
+
+#endif // _FILE_SYS_H_
diff -r 000000000000 -r 429446fe396d main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,535 @@
+// This project is a demo of the DASH7 1.x stack
+// @autor: jeremie@wizzilab.com
+// @date: 2016-08-23
+//
+// ----- SETUP -----
+// This programm has been tested with the following hardware:
+// --> NUCLEO-L152RE + DASH7 enabled SHIELD_SP1ML_v1.0
+// For this demo to work, you need the previously described hardware.
+// A DASH7 1.x gateway have to be available in your area in order to retreive the data.
+//
+// ----- FILE SYSTEM -----
+// DASH7 is a file system based protocol. You read and write in files that are present on your device or your modem.
+// Some callbacks can be implemented by the user for allowing the stack to acceed the local file system. (See description of the callbacks for more details)
+// The file system is user defined and can be changed to fit your needs.
+// This demo uses a simple RAM file system.
+// The files are defined in files.h
+// The files values are initialized in files.cpp
+// 
+// ----- SENSORS -----
+// The sensors can be simulated (random data).
+//
+// ----- DEMO -----
+// This demo starts 7 threads (one for each sensor value) that will periodically read the sensor value
+// and depending on the sensor configuration file, will send the data to the DASH7 network (notification)
+// You can also report the alarm status by pushing the board's button (blue)
+// 
+// ----- DEBUG -----
+// Several debugging options are available in wizzi-utils/dbg/dbg.h
+// An ASSERT is a fatal error. By default, this error will reboot the device.
+
+#include "mbed.h"
+#include "rtos.h"
+#include "rtos_idle.h"
+#include "d7a.h"
+#include "sensors.h"
+#include "simul.h"
+#include "dbg.h"
+#include "DebouncedInterrupt.h"
+#include "files.h"
+
+// Select the sensors
+#if 0
+    #define _MAG_EN_        1
+    #define _ACC_EN_        1
+    #define _GYR_EN_        1
+    #define _PRE_EN_        1
+    #define _HUM_EN_        1
+    #define _TEM1_EN_       1
+    #define _TEM2_EN_       1
+#else
+    #define _MAG_EN_        0
+    #define _ACC_EN_        0
+    #define _GYR_EN_        0
+    #define _PRE_EN_        0
+    #define _HUM_EN_        0
+    #define _TEM1_EN_       0
+    #define _TEM2_EN_       0
+#endif
+
+// Semaphore for notifiying button presses
+Semaphore button_user(0);
+
+// Interrupt Service Routine on button press.
+void button_push_isr( void )
+{
+    button_user.release();
+}
+
+// file modified queue
+Queue<void, 8> fm_queue;
+
+
+// -----------------------------------------------
+// callbacks
+// -----------------------------------------------
+/**
+    Write data into a file.
+
+    @param const uint8_t            File ID
+    @param const uint16_t           Offset from start of data
+    @param const uint16_t           Size of data to be written
+    @param const uint8_t* const     Pointer to the data to write
+    @return uint32_t                Size of written data
+*/
+uint32_t write_file_callback(const uint8_t file_id,
+                             const uint16_t offset,
+                             const uint16_t size,
+                             const uint8_t* const content)
+{
+    uint32_t ret = 0;
+    
+    IPRINT("Write file %d offset:%d size:%d\r\n", file_id, offset, size);
+    
+    ret = fs_write_file(file_id, offset, size, content);
+
+    WARNING(ret, "File %d not found\r\n", file_id);
+    
+    // Indicate that the file has been modified
+    fm_queue.put((void*)file_id);
+    
+    return ret;
+}
+
+/**
+    Read data from a file.
+
+    @param const uint8_t            File ID
+    @param const uint16_t           Offset from start of data
+    @param const uint16_t           Size of data to be read
+    @param const uint8_t* const     Pointer to the reading buffer
+    @return uint32_t                Size of read data
+*/
+uint32_t read_file_callback(const uint8_t file_id,
+                            const uint16_t offset,
+                            const uint16_t size,
+                            uint8_t* buf)
+{
+    uint32_t ret = 0;
+
+    IPRINT("Read file %d offset:%d size:%d\r\n", file_id, offset, size);
+    
+    ret = fs_read_file(file_id, offset, size, buf);
+
+    WARNING(ret, "File %d not found\r\n", file_id);
+    
+    return ret;
+}
+
+/**
+    Called when a notification is finished
+
+    @param const uint8_t            File ID
+    @param const uint8_t            Error code
+    @return void
+*/
+void notif_done_callback(const uint8_t file_id, const uint8_t error)
+{
+    PRINT("Notif FID %d done. err %d\r\n", file_id, error);
+}
+
+void unsolicited_callback(d7a_msg_t** uns)
+{
+    PRINT("UNSOLICITED MESSAGE:\r\n");
+    d7a_print_msg(uns);
+    d7a_free_msg(uns);
+}
+
+// callbacks structure
+const d7a_callbacks_t callbacks = {
+    .write_file = write_file_callback,   // If NULL you cannot declare files
+    .read_file = read_file_callback,     // If NULL you cannot declare files
+    .notif_done = notif_done_callback,
+    .unsolicited_msg = unsolicited_callback,
+};
+
+// Com configuration for the DASH7 shield
+const d7a_com_config_t shield_config = {
+    .tx  = D10,
+    .rx  = D2,
+    .rts = D13,
+    .cts = D9,
+    .rx_buffer_size = 512,
+};
+
+
+// Check parameters to see if data should be send
+static bool report_needed(sensor_config_t* cfg, int32_t value, int32_t last_value, uint32_t last_report_time)
+{
+    switch (cfg->report_type)
+    {
+        case REPORT_ALWAYS:
+            // Send a report at each measure
+            IPRINT("Notif cause 1\r\n");
+            return true;
+        case REPORT_ON_DIFFERENCE:
+            // Send a report when the difference between the last reported measure and the current mesure is greater than max_diff
+            if (abs(last_value - value) >= cfg->max_diff)
+            {
+                IPRINT("Notif cause 2 last:%d new:%d max_diff:%d\r\n", last_value, value, cfg->max_diff);
+                return true;
+            }
+            break;
+        case REPORT_ON_THRESHOLD:
+            // Send a report when crossing a threshold
+            if (   (value >= cfg->threshold_high && last_value < cfg->threshold_high)
+                || (value <= cfg->threshold_low  && last_value > cfg->threshold_low)
+                || (value < cfg->threshold_high  && last_value >= cfg->threshold_high)
+                || (value > cfg->threshold_low   && last_value <= cfg->threshold_low))
+            {
+                IPRINT("Notif cause 3 last:%d new:%d th:%d tl:%d\r\n", last_value, value, cfg->threshold_high, cfg->threshold_low);
+                return true;
+            }
+            break;
+        default:
+            break;
+    }
+    
+    // Send a report if it's been more than max_period since the last report
+    if (((last_report_time/1000) >= cfg->max_period) && (cfg->max_period != 0))
+    {
+        IPRINT("Notif cause 4 max_period:%d time:%d\r\n", cfg->max_period, last_report_time);
+        return true;
+    }
+
+    return false;
+}
+
+// Initialisation of the sensor thread's context
+#define SENSOR_THREAD_CTX(_name,_vfid,_cfid,_read_func,_nb_values) \
+    int32_t _name##_last_report[_nb_values];\
+    int32_t _name##_current_value[_nb_values];\
+    sensor_thread_ctx_t _name##_thread_ctx = {\
+        .nb_values = _nb_values,\
+        .data_size = _nb_values * sizeof(int32_t),\
+        .read_value = _read_func,\
+        .last_report_value = (int32_t*)&_name##_last_report,\
+        .current_value = (int32_t*)&_name##_current_value,\
+        .last_report_time = 0,\
+        .value_file_id = _vfid,\
+        .cfg_file_id = _cfid\
+    }
+
+
+SENSOR_THREAD_CTX(mag,  MAG_VALUE_FILE_ID,  MAG_CFG_FILE_ID,  mag_get_value,  3);
+SENSOR_THREAD_CTX(acc,  ACC_VALUE_FILE_ID,  ACC_CFG_FILE_ID,  acc_get_value,  3);
+SENSOR_THREAD_CTX(gyr,  GYR_VALUE_FILE_ID,  GYR_CFG_FILE_ID,  gyr_get_value,  3);
+SENSOR_THREAD_CTX(pre,  PRE_VALUE_FILE_ID,  PRE_CFG_FILE_ID,  pre_get_value,  1);
+SENSOR_THREAD_CTX(hum,  HUM_VALUE_FILE_ID,  HUM_CFG_FILE_ID,  hum_get_value,  1);
+SENSOR_THREAD_CTX(tem1, TEM1_VALUE_FILE_ID, TEM1_CFG_FILE_ID, tem1_get_value, 1);
+SENSOR_THREAD_CTX(tem2, TEM2_VALUE_FILE_ID, TEM2_CFG_FILE_ID, tem2_get_value, 1);
+
+// -----------------------------------------------
+// Threads
+// -----------------------------------------------
+void sensor_thread(const void* p)
+{
+    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
+    d7a_msg_t** resp = NULL;
+    
+    // Get thread context
+    sensor_thread_ctx_t* th_ctx = (sensor_thread_ctx_t*)p;
+    
+    // Force a first notification
+    bool first_notif = true;
+    
+    // Retrieve notification config from local file
+    fs_read_file(th_ctx->cfg_file_id, 0, sizeof(sensor_config_t), (uint8_t*)&(th_ctx->cfg));
+
+    // Declare the config file to allow it to be accessed via the modem
+    d7a_declare(th_ctx->cfg_file_id, VOLATILE, RW_RW, sizeof(sensor_config_t), sizeof(sensor_config_t));
+    
+    // Create a file on the modem to store and notify the sensor value
+    d7a_create(th_ctx->value_file_id, VOLATILE, RW_R, th_ctx->data_size, th_ctx->data_size, D7A_NOTIFICATION_FULL, D7A_ITF_REPORT_CHECKED);
+
+    while (true)
+    {
+        // Read the sensor values
+        bool err = th_ctx->read_value(th_ctx->current_value);
+        
+        ASSERT(!err, "Failed to read sensor value for FID: %d\r\n", th_ctx->value_file_id);
+
+        // Check if data should be send
+        for (uint8_t i = 0; i < th_ctx->nb_values; i++)
+        {
+            if (report_needed(&(th_ctx->cfg),
+                th_ctx->current_value[i],
+                th_ctx->last_report_value[i],
+                th_ctx->last_report_time) || first_notif)
+            {
+                first_notif = false;
+                
+                PRINT("NOTIFY %3d: ", th_ctx->value_file_id);
+                for (uint8_t i = 0; i < th_ctx->nb_values; i++)
+                {
+                    PRINT("%9ld ", (int32_t)th_ctx->current_value[i]);   
+                }
+                PRINT("\r\n");
+
+                // Send data to the modem
+                resp = d7a_write(th_ctx->value_file_id, 0, th_ctx->data_size, (uint8_t*)th_ctx->current_value);
+                d7a_free_msg(resp);
+                
+                // Update last report value
+                memcpy(th_ctx->last_report_value, th_ctx->current_value, th_ctx->data_size);
+                // Reset last report time
+                th_ctx->last_report_time = 0;
+                break;
+            }
+        }
+        
+        // Update last report time
+        th_ctx->last_report_time += th_ctx->cfg.period;
+        
+        // Wait for period
+        Thread::wait(th_ctx->cfg.period);
+    }
+}
+
+void file_modified_thread(const void *p)
+{    
+    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
+    
+    while (true)
+    {
+        // Wait for a file modified event
+        osEvent evt = fm_queue.get();
+        
+        // Retrieve FID of modified file
+        uint8_t fid = (uint8_t)(uint32_t)evt.value.p;
+        
+        PRINT("File %d has been modified\r\n", fid);
+        
+        switch (fid)
+        {
+            // If a configuration file has been modified, update the context
+            case MAG_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(mag_thread_ctx.cfg));
+                break;
+            case ACC_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(acc_thread_ctx.cfg));
+                break;
+            case GYR_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(gyr_thread_ctx.cfg));
+                break;
+            case PRE_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(pre_thread_ctx.cfg));
+                break;
+            case HUM_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(hum_thread_ctx.cfg));
+                break;
+            case TEM1_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(tem1_thread_ctx.cfg));
+                break;
+            case TEM2_CFG_FILE_ID:
+                fs_read_file(fid, 0, sizeof(sensor_config_t), (uint8_t*)&(tem2_thread_ctx.cfg));
+                break;
+            case SIMUL_FILE_ID:
+                uint32_t divider;
+                // Retreive the simulation parameter from local file
+                fs_read_file(SIMUL_FILE_ID, 0, sizeof(uint32_t), (uint8_t*)&divider);
+                // Update the simulation parameters
+                update_simul_param(divider);
+                PRINT("Simulation Divider is Now %d\r\n", divider);
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+void button_user_thread(const void *p)
+{
+    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
+    
+    uint8_t alarm = 255;
+    d7a_msg_t** resp = NULL;
+
+    // Create the alarm file
+    //d7a_create(ALARM_FILE_ID, VOLATILE, RW_R, sizeof(uint8_t), sizeof(uint8_t), D7A_NOTIFICATION_FULL, D7A_ITF_SINGLE);
+    
+    // Update it with the default value
+    //resp = d7a_write(ALARM_FILE_ID, 0, sizeof(uint8_t), (uint8_t*)&alarm);
+    //d7a_free_msg(resp);
+    
+    while (true)
+    {
+        // Wait for button press
+        button_user.wait();
+        
+        // Toggle alarm state
+        alarm = !alarm;
+        
+        PRINT("BUTTON ALARM %d\r\n", alarm);
+#if 1 // Switch between Notify and Distant Read/Write example
+
+        // Send alarm state to the modem 
+        //resp = d7a_write(ALARM_FILE_ID, 0, sizeof(uint8_t), (uint8_t*)&alarm);
+        //WARNING(!resp[0]->err, "BUTTON ALARM ERR %d\r\n", resp[0]->err);
+        //d7a_free_msg(resp);
+#else
+        // Distant device that I want to acceed
+#if 0 // Unicast / Broadcast
+        // Unicast
+        d7a_addressee_t target = {
+            // Access Class
+            .xcl.byte = D7A_XCL_ENDPOINT_LO,
+            // Type of security you want to use
+            .ctrl.bf.nls = D7A_NLS_AES_CCM_64,
+            // Type of ID
+            .ctrl.bf.idf = D7A_ID_UID,
+            // Device ID
+            .id = { 0x00, 0x1B, 0xC5, 0x0C, 0x70, 0x00, 0x07, 0xA3 },
+        };
+#else    
+        // Broadcast
+        d7a_addressee_t target = {
+            // Access Class
+            .xcl.byte = D7A_XCL_ENDPOINT_LO,
+            // Type of security you want to use
+            .ctrl.bf.nls = D7A_NLS_AES_CCM_64,
+            // Type of ID
+            .ctrl.bf.idf = D7A_ID_NBID,
+            // Maximum number of responses (1-32)
+            .id[0] = D7A_NBID(8),
+        };
+#endif
+
+#if 1 // Read / Write
+        // Read example
+        //resp = d7a_read(MAG_CFG_FILE_ID, 12, 5, &target, D7A_ITF_ONESHOT);
+        resp = d7a_read(ALARM_FILE_ID, 0, 1, NULL, &target, D7A_ITF_ONESHOT);
+#else
+        // Write example
+        uint8_t v = 0x01;
+        resp = d7a_write(ALARM_FILE_ID, 0, 1, &v, NULL, &target, D7A_ITF_ONESHOT);
+#endif
+        // Check received response(s)
+        d7a_print_msg(resp);
+        
+        PRINT("Resp done.\r\n");
+        d7a_free_msg(resp);
+#endif
+
+
+    }
+}
+
+
+/*** Main function ------------------------------------------------------------- ***/
+int main()
+{
+    PinName DBG_LED = D12;
+        
+    // Go to sleep when idle
+    //rtos_attach_idle_hook(sleep);
+
+    // Start & initialize
+    DBG_OPEN(DBG_LED);
+    PRINT("\r\n--- Starting new run ---\r\n");
+    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
+    
+    DigitalOut myled(DBG_LED);
+    DebouncedInterrupt user_interrupt(USER_BUTTON);
+    user_interrupt.attach(button_push_isr, IRQ_FALL, 200, true);
+    myled = 1;
+    
+    extern uint16_t const os_maxtaskrun;
+    //IPRINT("Max user threads: %d\r\n", os_maxtaskrun-1-9);
+#if 0
+    d7a_open(&shield_config, A3, &callbacks);
+    d7a_modem_print_infos();
+    
+    // Create the revision file for the Dash7board
+    d7a_create(65, PERMANENT, RW_R, sizeof(d7a_revision_t), sizeof(d7a_revision_t), D7A_NOTIFICATION_FULL, D7A_ITF_REPORT_CHECKED);
+    // Notify revision
+    d7a_msg_t** resp = d7a_write(65, 0, sizeof(d7a_revision_t), (uint8_t*)&f_dev_rev);
+    d7a_free_msg(resp);
+#endif
+
+#if _SENSORS_SIMU_
+    PRINT("(Simulated sensors)\r\n");
+    uint32_t divider;
+    
+    // Retreive the simulation parameter from local file
+    fs_read_file(SIMUL_FILE_ID, 0, sizeof(uint32_t), (uint8_t*)&divider);
+    
+    // Update the simulation parameters
+    update_simul_param(divider);
+    
+    // Declare the simulation parameter file
+    //d7a_declare(SIMUL_FILE_ID, PERMANENT, RW_RW, sizeof(sensor_config_t), sizeof(sensor_config_t));
+
+#else
+    // Open I2C and initialise the sensors
+    DevI2C ext_i2c(D14, D15);
+    
+#if (_HUM_EN_ || _TEM1_EN_)
+    humidity_sensor = new HTS221(ext_i2c);
+    ASSERT(Init_HTS221(humidity_sensor), "Failed to init HTS221\r\n");
+    temp_sensor1 = humidity_sensor;
+#endif // _TEM_EN_
+#if _MAG_EN_
+    magnetometer = new LIS3MDL(ext_i2c);
+    ASSERT(Init_LIS3MDL(magnetometer), "Failed to init LIS3MDL\r\n");
+#endif // _MAG_EN_
+#if (_ACC_EN_ || _GYR_EN_)
+    accelerometer = new LSM6DS0(ext_i2c);
+    ASSERT(Init_LSM6DS0(accelerometer), "Failed to init LSM6DS0\r\n");
+    gyroscope = accelerometer;
+#endif // _ACC_EN_ || _GYR_EN_
+#if (_PRE_EN_ || _TEM2_EN_)
+    pressure_sensor = new LPS25H(ext_i2c);
+    ASSERT(Init_LPS25H(pressure_sensor), "Failed to init LPS25H\r\n");
+    temp_sensor2 = pressure_sensor;
+#endif // _PRE_EN_
+
+#endif // _SENSORS_SIMU_
+
+    // File modified thread
+    Thread fm_th(file_modified_thread);
+
+#if _MAG_EN_
+    Thread mag_th(sensor_thread, (void*)&mag_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _MAG_EN_
+#if _ACC_EN_
+    Thread acc_th(sensor_thread, (void*)&acc_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _ACC_EN_
+#if _GYR_EN_
+    Thread gyr_th(sensor_thread, (void*)&gyr_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _GYR_EN_
+#if _PRE_EN_
+    Thread pre_th(sensor_thread, (void*)&pre_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _PRE_EN_
+#if _HUM_EN_
+    Thread hum_th(sensor_thread, (void*)&hum_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _HUM_EN_
+#if _TEM1_EN_
+    Thread tem1_th(sensor_thread, (void*)&tem1_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _TEM1_EN_
+#if _TEM2_EN_
+    Thread tem2_th(sensor_thread, (void*)&tem2_thread_ctx, osPriorityNormal, DEFAULT_STACK_SIZE*2);
+#endif // _TEM2_EN_
+
+    // For button irq
+    Thread but_th(button_user_thread, NULL, osPriorityNormal, DEFAULT_STACK_SIZE*4);
+    
+    // Set main task to lowest priority
+    osThreadSetPriority(osThreadGetId(), osPriorityIdle);
+    while(true)
+    {
+        // Wait to avoid beeing stuck in loop
+        Thread::wait(200);
+        myled = !myled;
+    }
+}
\ No newline at end of file
diff -r 000000000000 -r 429446fe396d mbed-rtos.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/WizziLab/code/mbed-rtos/#d1fdc9c158f3
diff -r 000000000000 -r 429446fe396d mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7c328cabac7e
\ No newline at end of file
diff -r 000000000000 -r 429446fe396d sensors.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors.cpp	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,219 @@
+#include "mbed.h"
+#include "dbg.h"
+#include "sensors.h"
+#include "simul.h"
+
+#define CALL_METH(obj, meth, param, ret) ((obj == NULL) ?       \
+                      ((*(param) = (ret)), 0) : \
+                      ((obj)->meth(param))      \
+                      )
+
+LIS3MDL *magnetometer;
+LSM6DS0 *accelerometer;
+LSM6DS0 *gyroscope;
+LPS25H *pressure_sensor;
+LPS25H *temp_sensor2;
+HTS221 *humidity_sensor;
+HTS221 *temp_sensor1;
+
+__inline int32_t float2_to_int(float v)
+{
+    return (int32_t)(v*100);
+}
+
+bool Init_HTS221(HTS221* ht_sensor)
+{
+    uint8_t ht_id = 0;
+    HUM_TEMP_InitTypeDef InitStructure;
+
+    /* Check presence */
+    if((ht_sensor->ReadID(&ht_id) != HUM_TEMP_OK) ||
+       (ht_id != I_AM_HTS221))
+        {
+            delete ht_sensor;
+            ht_sensor = NULL;
+            return true;
+        }
+    
+    /* Configure sensor */
+    InitStructure.OutputDataRate = HTS221_ODR_12_5Hz;
+
+    if(ht_sensor->Init(&InitStructure) != HUM_TEMP_OK)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool Init_LIS3MDL(LIS3MDL* magnetometer)
+{
+    uint8_t m_id = 0;
+    MAGNETO_InitTypeDef InitStructure;
+
+    /* Check presence */
+    if((magnetometer->ReadID(&m_id) != MAGNETO_OK) ||
+       (m_id != I_AM_LIS3MDL_M))
+    {
+        delete magnetometer;
+        magnetometer = NULL;
+        return true;
+    }
+      
+    /* Configure sensor */
+    InitStructure.M_FullScale = LIS3MDL_M_FS_4;
+    InitStructure.M_OperatingMode = LIS3MDL_M_MD_CONTINUOUS;
+    InitStructure.M_XYOperativeMode = LIS3MDL_M_OM_HP;
+    InitStructure.M_OutputDataRate = LIS3MDL_M_DO_80;
+
+    if(magnetometer->Init(&InitStructure) != MAGNETO_OK)
+    {
+        return false;
+    }
+      
+    return true;
+}
+
+bool Init_LPS25H(LPS25H* pt_sensor)
+{
+    uint8_t p_id = 0;
+    PRESSURE_InitTypeDef InitStructure;
+    
+    /* Check presence */
+    if((pt_sensor->ReadID(&p_id) != PRESSURE_OK) ||
+       (p_id != I_AM_LPS25H))
+    {
+        delete pt_sensor;
+        pt_sensor = NULL;
+        return true;
+    }
+            
+    /* Configure sensor */
+    InitStructure.OutputDataRate = LPS25H_ODR_1Hz;
+    InitStructure.BlockDataUpdate = LPS25H_BDU_CONT;
+    InitStructure.DiffEnable = LPS25H_DIFF_DISABLE;
+    InitStructure.SPIMode = LPS25H_SPI_SIM_4W;
+    InitStructure.PressureResolution = LPS25H_P_RES_AVG_8;
+    InitStructure.TemperatureResolution = LPS25H_T_RES_AVG_8;
+        
+    if(pt_sensor->Init(&InitStructure) != PRESSURE_OK)
+    {
+        return false;
+    }
+    
+    return true;
+}
+
+bool Init_LSM6DS0(LSM6DS0* gyro_lsm6ds0)
+{
+    IMU_6AXES_InitTypeDef InitStructure;
+    uint8_t xg_id = 0;
+
+    /* Check presence */
+    if((gyro_lsm6ds0->ReadID(&xg_id) != IMU_6AXES_OK) ||
+       (xg_id != I_AM_LSM6DS0_XG))
+    {
+        delete gyro_lsm6ds0;
+        gyro_lsm6ds0 = NULL;
+        return true;
+    }
+            
+    /* Configure sensor */
+    InitStructure.G_FullScale       = 2000.0f; /* 2000DPS */
+    InitStructure.G_OutputDataRate  = 119.0f;  /* 119HZ */
+    InitStructure.G_X_Axis          = 1;       /* Enable */
+    InitStructure.G_Y_Axis          = 1;       /* Enable */
+    InitStructure.G_Z_Axis          = 1;       /* Enable */
+
+    InitStructure.X_FullScale       = 2.0f;    /* 2G */
+    InitStructure.X_OutputDataRate  = 119.0f;  /* 119HZ */
+    InitStructure.X_X_Axis          = 1;       /* Enable */
+    InitStructure.X_Y_Axis          = 1;       /* Enable */
+    InitStructure.X_Z_Axis          = 1;       /* Enable */
+              
+    if(gyro_lsm6ds0->Init(&InitStructure) != IMU_6AXES_OK)
+    {
+        return false; 
+    }
+            
+    return true;
+}
+
+bool mag_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 3, -1900, 1900);
+#else
+    return CALL_METH(magnetometer, Get_M_Axes, buf, 0)? true : false;
+#endif
+}
+
+bool acc_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 3, -1900, 1900);
+#else
+    return CALL_METH(accelerometer, Get_X_Axes, buf, 0)? true : false;
+#endif
+}
+
+bool gyr_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 3, -40000, 40000);
+#else
+    return CALL_METH(gyroscope, Get_G_Axes, buf, 0)? true : false;
+#endif
+}
+
+bool pre_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 1, 96000, 104000);
+#else
+    bool err;
+    float tmp;
+    err = CALL_METH(pressure_sensor, GetPressure, &tmp, 0.0f)? true : false;
+    buf[0] = float2_to_int(tmp);
+    return err;
+#endif
+}
+
+bool hum_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 1, 1000, 9000);
+#else
+    bool err;
+    float tmp;
+    err = CALL_METH(humidity_sensor, GetHumidity, &tmp, 0.0f)? true : false;
+    buf[0] = float2_to_int(tmp);
+    return err;
+#endif
+}
+
+bool tem1_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 1, 1100, 3900);
+#else
+    bool err;
+    float tmp;
+    err = CALL_METH(temp_sensor1, GetTemperature, &tmp, 0.0f)? true : false;
+    buf[0] = float2_to_int(tmp);
+    return err;
+#endif
+}
+
+bool tem2_get_value(int32_t* buf)
+{
+#if _SENSORS_SIMU_
+    return simul_sensor_value(buf, 1, 5100, 10100);
+#else
+    bool err;
+    float tmp;
+    err = CALL_METH(temp_sensor2, GetFahrenheit, &tmp, 0.0f)? true : false;
+    buf[0] = float2_to_int(tmp);
+    return err;
+#endif
+}
\ No newline at end of file
diff -r 000000000000 -r 429446fe396d sensors.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors.h	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,76 @@
+#ifndef _SENSORS_H_
+#define _SENSORS_H_
+
+#include "hts221/hts221_class.h"
+#include "lis3mdl/lis3mdl_class.h"
+#include "lps25h/lps25h_class.h"
+#include "lsm6ds0/lsm6ds0_class.h"
+#include "d7a.h"
+
+// Simulate the sensors (if X_NUCLEO_IKS01A1 not connected)
+//#define _SENSORS_SIMU_    1
+
+extern LIS3MDL *magnetometer;
+extern LSM6DS0 *accelerometer;
+extern LSM6DS0 *gyroscope;
+extern LPS25H *pressure_sensor;
+extern LPS25H *temp_sensor2;
+extern HTS221 *humidity_sensor;
+extern HTS221 *temp_sensor1;
+
+
+// Types of reporting
+typedef enum {
+    REPORT_ALWAYS,
+    REPORT_ON_DIFFERENCE,
+    REPORT_ON_THRESHOLD,
+} report_type_t;
+
+// Sensor reporting configuration
+TYPEDEF_STRUCT_PACKED {
+    uint8_t  report_type; // Type of report asked
+    uint32_t period; // Measure period (ms)
+    uint32_t max_period; // Maximum time between reports (s)
+    uint32_t max_diff; // Maximum difference allowed between two reported values
+    int32_t  threshold_high; // High threshold value triggering a report
+    int32_t  threshold_low; // Low threshold value triggering a report
+} sensor_config_t;
+
+typedef struct
+{
+    // Number of data fields
+    uint32_t nb_values;
+    // Total size of data
+    uint32_t data_size;
+    // Read value function
+    bool (*read_value)(int32_t*);
+    // Last reported value
+    int32_t* last_report_value;
+    // Current measured value
+    int32_t* current_value;
+    // Time elapsed since last report (ms)
+    uint32_t last_report_time;
+    
+    // File ID of the sensor value file
+    uint8_t value_file_id;
+    // Sensor configuration file ID
+    uint8_t cfg_file_id;
+    // Sensor configuration context
+    sensor_config_t cfg;
+} sensor_thread_ctx_t;
+
+
+bool Init_HTS221(HTS221* ht_sensor);
+bool Init_LIS3MDL(LIS3MDL* magnetometer);
+bool Init_LPS25H(LPS25H* pt_sensor);
+bool Init_LSM6DS0(LSM6DS0* gyro_lsm6ds0);
+
+bool mag_get_value(int32_t* buf);
+bool acc_get_value(int32_t* buf);
+bool gyr_get_value(int32_t* buf);
+bool pre_get_value(int32_t* buf);
+bool hum_get_value(int32_t* buf);
+bool tem1_get_value(int32_t* buf);
+bool tem2_get_value(int32_t* buf);
+
+#endif // _SENSORS_H_
\ No newline at end of file
diff -r 000000000000 -r 429446fe396d simul.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simul.cpp	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,60 @@
+#include "mbed.h"
+#include "simul.h"
+#include "dbg.h"
+
+
+unsigned int m_z=12434,m_w=33254;
+ 
+unsigned int rnd() {
+    m_z = 36969 * (m_z & 65535) + (m_z >>16);
+    m_w = 18000 * (m_w & 65535) + (m_w >>16);
+    return ((m_z <<16) + m_w);
+}
+
+uint32_t g_simul_divider = 500;
+
+void update_simul_param(uint32_t value)
+{
+    g_simul_divider = value;
+}
+
+bool simul_sensor_value(int32_t* buf, uint32_t nb_values, int32_t min, int32_t max)
+{
+    for (uint8_t i = 0; i < nb_values; i++)
+    {
+        int32_t new_value;
+        
+        uint32_t r = rnd()%g_simul_divider;
+        
+        if (r)
+        {
+            if (r%2)
+            {
+                new_value = buf[i] + 1;
+            }
+            else
+            {
+                new_value = buf[i] - 1;
+            }
+            
+            if (new_value > max)
+            {
+                new_value = max;
+            }
+            
+            if (new_value < min)
+            {
+                new_value = min;
+            }
+        }
+        else
+        {
+            new_value = (rnd()%(max - min)) + min;
+        }
+        
+        buf[i] = new_value;
+    }
+    
+    return false;
+}
+
diff -r 000000000000 -r 429446fe396d simul.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simul.h	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,7 @@
+#ifndef _SIMUL_H_
+#define _SIMUL_H_
+
+void update_simul_param(uint32_t value);
+bool simul_sensor_value(int32_t* buf, uint32_t nb_values, int32_t min, int32_t max);
+
+#endif // _SIMUL_H_
\ No newline at end of file
diff -r 000000000000 -r 429446fe396d wizzi-utils.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wizzi-utils.lib	Mon Nov 21 07:24:34 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/WizziLab/code/wizzi-utils/#58cee7457908