Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: X_NUCLEO_IKS01A1 d7a_1x mbed-rtos mbed wizzi-utils
Revision 0:429446fe396d, committed 2016-11-21
- Comitter:
- mikl_andre
- Date:
- Mon Nov 21 07:24:34 2016 +0000
- Commit message:
- Initial Revision
Changed in this revision
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*)÷r); + // 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*)÷r); + + // 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