contiki/examples/cc26xx/cc26xx-demo.c
George Oikonomou 421fbfae25 Change the LPM locks API:
Instead of using a separate data structure to request that a PD remain powered during deep sleep,
we do the same within the main LPM data structure through an additional field.

This allows us to maintain only one linked list of LPM modules and overall improves code clarity
2015-05-15 09:21:02 +01:00

456 lines
15 KiB
C

/*
* 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 <stdio.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
#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();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
* @}
*/