/* * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ /** * \addtogroup cc26xx-platforms * @{ * * \defgroup cc26xx-examples CC26xx Example Projects * * Example projects for CC26xx-based platforms. * @{ * * \defgroup cc26xx-demo CC26xx Demo Project * * Example project demonstrating the CC26xx platforms * * This example will work for the following boards: * - srf06-cc26xx: SmartRF06EB + CC26XX EM * - sensortag-cc26xx: CC26XX sensortag * * By default, the example will build for the srf06-cc26xx board. To switch * between platforms: * - make clean * - make BOARD=sensortag-cc26xx savetarget * * or * * make BOARD=srf06-cc26xx savetarget * * This is an IPv6/RPL-enabled example. Thus, if you have a border router in * your installation (same RDC layer, same PAN ID and RF channel), you should * be able to ping6 this demo node. * * This example also demonstrates CC26xx BLE operation. The process starts * the BLE beacon daemon (implemented in the RF driver). The daemon will * send out a BLE beacon periodically. Use any BLE-enabled application (e.g. * LightBlue on OS X or the TI BLE Multitool smartphone app) and after a few * seconds the cc26xx device will be discovered. * * - etimer/clock : Every CC26XX_DEMO_LOOP_INTERVAL clock ticks the LED defined * as CC26XX_DEMO_LEDS_PERIODIC will toggle and the device * will print out readings from some supported sensors * - sensors : Some sensortag sensors are read asynchronously (see sensor * documentation). For those, this example will print out * readings in a staggered fashion at a random interval * - Buttons : CC26XX_DEMO_SENSOR_1 button will toggle CC26XX_DEMO_LEDS_BUTTON * - CC26XX_DEMO_SENSOR_2 turns on LEDS_REBOOT and causes a * watchdog reboot * - The remaining buttons will just print something * - The example also shows how to retrieve the duration of a * button press (in ticks). The driver will generate a * sensors_changed event upon button release * - UART : Receiving an entire line of text over UART (ending * in \\r) will cause CC26XX_DEMO_LEDS_SERIAL_IN to toggle * This also demonstrates how a code module can influence * low-power operation: In this example we keep the UART on * and capable to RX even with the chip in deep sleep. * see keep_uart_on() and the UART driver * - Reed Relay : Will toggle the sensortag buzzer on/off * * @{ * * \file * Example demonstrating the cc26xx platforms */ #include "contiki.h" #include "sys/etimer.h" #include "sys/ctimer.h" #include "dev/leds.h" #include "dev/serial-line.h" #include "dev/watchdog.h" #include "random.h" #include "button-sensor.h" #include "batmon-sensor.h" #include "board-peripherals.h" #include "cc26xx-rf.h" #include "ti-lib.h" #include #include /*---------------------------------------------------------------------------*/ #define CC26XX_DEMO_LOOP_INTERVAL (CLOCK_SECOND * 20) #define CC26XX_DEMO_LEDS_PERIODIC LEDS_YELLOW #define CC26XX_DEMO_LEDS_BUTTON LEDS_RED #define CC26XX_DEMO_LEDS_SERIAL_IN LEDS_ORANGE #define CC26XX_DEMO_LEDS_REBOOT LEDS_ALL /*---------------------------------------------------------------------------*/ #define CC26XX_DEMO_SENSOR_NONE (void *)0xFFFFFFFF #define CC26XX_DEMO_SENSOR_1 &button_left_sensor #define CC26XX_DEMO_SENSOR_2 &button_right_sensor #if BOARD_SENSORTAG #define CC26XX_DEMO_SENSOR_3 CC26XX_DEMO_SENSOR_NONE #define CC26XX_DEMO_SENSOR_4 CC26XX_DEMO_SENSOR_NONE #define CC26XX_DEMO_SENSOR_5 &reed_relay_sensor #else #define CC26XX_DEMO_SENSOR_3 &button_up_sensor #define CC26XX_DEMO_SENSOR_4 &button_down_sensor #define CC26XX_DEMO_SENSOR_5 &button_select_sensor #endif /*---------------------------------------------------------------------------*/ static struct etimer et; /*---------------------------------------------------------------------------*/ PROCESS(cc26xx_demo_process, "cc26xx demo process"); AUTOSTART_PROCESSES(&cc26xx_demo_process); /*---------------------------------------------------------------------------*/ #if BOARD_SENSORTAG /*---------------------------------------------------------------------------*/ /* * Update sensor readings in a staggered fashion every SENSOR_READING_PERIOD * ticks + a random interval between 0 and SENSOR_READING_RANDOM ticks */ #define SENSOR_READING_PERIOD (CLOCK_SECOND * 20) #define SENSOR_READING_RANDOM (CLOCK_SECOND << 4) static struct ctimer bmp_timer, opt_timer, hdc_timer, tmp_timer, mpu_timer; /*---------------------------------------------------------------------------*/ static void init_bmp_reading(void *not_used); static void init_opt_reading(void *not_used); static void init_hdc_reading(void *not_used); static void init_tmp_reading(void *not_used); static void init_mpu_reading(void *not_used); /*---------------------------------------------------------------------------*/ static void print_mpu_reading(int reading) { if(reading < 0) { printf("-"); reading = -reading; } printf("%d.%02d", reading / 100, reading % 100); } /*---------------------------------------------------------------------------*/ static void get_bmp_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS); if(value != CC26XX_SENSOR_READING_ERROR) { printf("BAR: Pressure=%d.%02d hPa\n", value / 100, value % 100); } else { printf("BAR: Pressure Read Error\n"); } value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_TEMP); if(value != CC26XX_SENSOR_READING_ERROR) { printf("BAR: Temp=%d.%02d C\n", value / 100, value % 100); } else { printf("BAR: Temperature Read Error\n"); } SENSORS_DEACTIVATE(bmp_280_sensor); ctimer_set(&bmp_timer, next, init_bmp_reading, NULL); } /*---------------------------------------------------------------------------*/ static void get_tmp_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_ALL); if(value == CC26XX_SENSOR_READING_ERROR) { printf("TMP: Ambient Read Error\n"); return; } value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_AMBIENT); printf("TMP: Ambient=%d.%03d C\n", value / 1000, value % 1000); value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_OBJECT); printf("TMP: Object=%d.%03d C\n", value / 1000, value % 1000); SENSORS_DEACTIVATE(tmp_007_sensor); ctimer_set(&tmp_timer, next, init_tmp_reading, NULL); } /*---------------------------------------------------------------------------*/ static void get_hdc_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); if(value != CC26XX_SENSOR_READING_ERROR) { printf("HDC: Temp=%d.%02d C\n", value / 100, value % 100); } else { printf("HDC: Temp Read Error\n"); } value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); if(value != CC26XX_SENSOR_READING_ERROR) { printf("HDC: Humidity=%d.%02d %%RH\n", value / 100, value % 100); } else { printf("HDC: Humidity Read Error\n"); } ctimer_set(&hdc_timer, next, init_hdc_reading, NULL); } /*---------------------------------------------------------------------------*/ static void get_light_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); value = opt_3001_sensor.value(0); if(value != CC26XX_SENSOR_READING_ERROR) { printf("OPT: Light=%d.%02d lux\n", value / 100, value % 100); } else { printf("OPT: Light Read Error\n"); } /* The OPT will turn itself off, so we don't need to call its DEACTIVATE */ ctimer_set(&opt_timer, next, init_opt_reading, NULL); } /*---------------------------------------------------------------------------*/ static void get_mpu_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); printf("MPU Gyro: X="); value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_X); print_mpu_reading(value); printf(" deg/sec\n"); printf("MPU Gyro: Y="); value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Y); print_mpu_reading(value); printf(" deg/sec\n"); printf("MPU Gyro: Z="); value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Z); print_mpu_reading(value); printf(" deg/sec\n"); printf("MPU Acc: X="); value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_X); print_mpu_reading(value); printf(" G\n"); printf("MPU Acc: Y="); value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Y); print_mpu_reading(value); printf(" G\n"); printf("MPU Acc: Z="); value = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Z); print_mpu_reading(value); printf(" G\n"); SENSORS_DEACTIVATE(mpu_9250_sensor); ctimer_set(&mpu_timer, next, init_mpu_reading, NULL); } /*---------------------------------------------------------------------------*/ static void init_bmp_reading(void *not_used) { SENSORS_ACTIVATE(bmp_280_sensor); } /*---------------------------------------------------------------------------*/ static void init_opt_reading(void *not_used) { SENSORS_ACTIVATE(opt_3001_sensor); } /*---------------------------------------------------------------------------*/ static void init_hdc_reading(void *not_used) { SENSORS_ACTIVATE(hdc_1000_sensor); } /*---------------------------------------------------------------------------*/ static void init_tmp_reading(void *not_used) { SENSORS_ACTIVATE(tmp_007_sensor); } /*---------------------------------------------------------------------------*/ static void init_mpu_reading(void *not_used) { mpu_9250_sensor.configure(SENSORS_ACTIVE, MPU_9250_SENSOR_TYPE_ALL); } #endif /*---------------------------------------------------------------------------*/ static void get_sync_sensor_readings(void) { int value; printf("-----------------------------------------\n"); value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP); printf("Bat: Temp=%d.%02d C (%08x)\n", value >> 2, (value & 0x00000003) * 25, value); value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); printf("Bat: Volt=%d mV\n", (value * 125) >> 5); return; } /*---------------------------------------------------------------------------*/ static void init_sensors(void) { #if BOARD_SENSORTAG SENSORS_ACTIVATE(reed_relay_sensor); #endif SENSORS_ACTIVATE(batmon_sensor); } /*---------------------------------------------------------------------------*/ static void init_sensor_readings(void) { #if BOARD_SENSORTAG SENSORS_ACTIVATE(hdc_1000_sensor); SENSORS_ACTIVATE(tmp_007_sensor); SENSORS_ACTIVATE(opt_3001_sensor); SENSORS_ACTIVATE(bmp_280_sensor); init_mpu_reading(NULL); #endif } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc26xx_demo_process, ev, data) { PROCESS_BEGIN(); printf("CC26XX demo\n"); init_sensors(); /* Init the BLE advertisement daemon */ cc26xx_rf_ble_beacond_config(0, BOARD_STRING); cc26xx_rf_ble_beacond_start(); etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL); get_sync_sensor_readings(); init_sensor_readings(); keep_uart_on(); while(1) { PROCESS_YIELD(); if(ev == PROCESS_EVENT_TIMER) { if(data == &et) { leds_toggle(CC26XX_DEMO_LEDS_PERIODIC); get_sync_sensor_readings(); etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL); } } else if(ev == sensors_event) { if(data == CC26XX_DEMO_SENSOR_1) { printf("Left: Pin %d, press duration %d clock ticks\n", (CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_STATE), (CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION)); if((CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND) { printf("Long button press!\n"); } leds_toggle(CC26XX_DEMO_LEDS_BUTTON); } else if(data == CC26XX_DEMO_SENSOR_2) { leds_on(CC26XX_DEMO_LEDS_REBOOT); watchdog_reboot(); } else if(data == CC26XX_DEMO_SENSOR_3) { printf("Up\n"); } else if(data == CC26XX_DEMO_SENSOR_4) { printf("Down\n"); } else if(data == CC26XX_DEMO_SENSOR_5) { #if BOARD_SENSORTAG if(buzzer_state()) { buzzer_stop(); } else { buzzer_start(1000); } } else if(ev == sensors_event && data == &bmp_280_sensor) { get_bmp_reading(); } else if(ev == sensors_event && data == &opt_3001_sensor) { get_light_reading(); } else if(ev == sensors_event && data == &hdc_1000_sensor) { get_hdc_reading(); } else if(ev == sensors_event && data == &tmp_007_sensor) { get_tmp_reading(); } else if(ev == sensors_event && data == &mpu_9250_sensor) { get_mpu_reading(); #else printf("Sel: Pin %d, press duration %d clock ticks\n", button_select_sensor.value(BUTTON_SENSOR_VALUE_STATE), button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION)); #endif } } else if(ev == serial_line_event_message) { leds_toggle(CC26XX_DEMO_LEDS_SERIAL_IN); } } PROCESS_END(); } /*---------------------------------------------------------------------------*/ /** * @} * @} * @} */