diff --git a/.gitignore b/.gitignore index 7286a98ba..d8874dffb 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ *.c128 *.c64 *.cc2538dk +*.srf06-cc26xx *.ev-aducrf101mkxz *.report summary diff --git a/.travis.yml b/.travis.yml index 386829b5d..03559d8a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,6 +48,13 @@ before_script: arm-none-eabi-gcc --version ; fi + ## Download and extract cc26xxware + - if [ ${BUILD_ARCH:-0} = arm ] ; then + wget http://www.ti.com/lit/sw/swrc296/swrc296.zip && + unzip swrc296.zip && + export TI_CC26XXWARE=cc26xxware_2_20_06_14829 ; + fi + ## Install RL78 GCC toolchain - sudo apt-get install libncurses5:i386 zlib1g:i386 - $WGET http://adamdunkels.github.io/contiki-fork/gnurl78-v13.02-elf_1-2_i386.deb && diff --git a/cpu/cc26xx/Makefile.cc26xx b/cpu/cc26xx/Makefile.cc26xx new file mode 100644 index 000000000..a339bd9f1 --- /dev/null +++ b/cpu/cc26xx/Makefile.cc26xx @@ -0,0 +1,132 @@ +CC = arm-none-eabi-gcc +CPP = arm-none-eabi-cpp +LD = arm-none-eabi-gcc +AR = arm-none-eabi-ar +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +NM = arm-none-eabi-nm +SIZE = arm-none-eabi-size + +### TI CC26xxware out-of-tree +### TI_CC26XXWARE is the home directory of the cc26xxware +### It MUST be provided as a path relative to $(CONTIKI) +### For example, if +### CONTIKI = /home/user/contiki +### and TI_CC26XXWARE is stored in +### /home/user/cc26xxware +### then set +### TI_CC26XXWARE = ../cc26xxware +ifndef TI_CC26XXWARE + $(error TI_CC26XXWARE not defined. Please see the README) +endif + +### cc26xxware sources will be added to the MODULES list +TI_CC26XXWARE_SRC = $(TI_CC26XXWARE)/driverlib + +### The directory with startup sources will be added to the CONTIKI_CPU_DIRS +### and the sources therein are added to the sources list explicitly. They are +### also listed explicitly in the linker command (through TARGET_STARTFILES), +### to make sure they always get linked in the image +TI_CC26XXWARE_STARTUP = ../../$(TI_CC26XXWARE)/startup_files +TI_CC26XXWARE_STARTUP_SRCS = ccfg.c startup_gcc.c + +### MODULES will add some of these to the include pach, but we need to add +### them earlier to prevent filename clashes with Contiki core files +CFLAGS += -I$(CONTIKI)/$(TI_CC26XXWARE) -I$(CONTIKI)/$(TI_CC26XXWARE_SRC) +CFLAGS += -I$(CONTIKI)/$(TI_CC26XXWARE)/inc +MODULES += $(TI_CC26XXWARE_SRC) + +LDSCRIPT = $(CONTIKI_CPU)/cc26xx.ld + +CFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian +CFLAGS += -ffunction-sections -fdata-sections +CFLAGS += -fshort-enums -fomit-frame-pointer -fno-strict-aliasing +CFLAGS += -Wall -std=c99 + +### Workaround for driverlib's cpu.h which tests if defined(gcc) +### Delete if it gets fixed or if we stop using the driverlib +CFLAGS += -Dgcc=__GNUC__ + +LDFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian -nostartfiles +LDFLAGS += -T $(LDSCRIPT) +LDFLAGS += -Wl,--gc-sections,--sort-section=alignment +LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch +OBJCOPY_FLAGS += -O binary --gap-fill 0xff +OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb + +### Are we building with code size optimisations? +ifeq ($(SMALL),1) + CFLAGS += -Os +else + CFLAGS += -O2 +endif + +### If the user-specified a Node ID, pass a define +ifdef NODEID + CFLAGS += -DIEEE_ADDR_NODE_ID=$(NODEID) +endif + +### CPU-dependent cleanup files +CLEAN += symbols.c symbols.h *.d *.elf *.hex + +### CPU-dependent directories +CONTIKI_CPU_DIRS = . dev dev/rfc-api $(TI_CC26XXWARE_STARTUP) + +### Use the existing debug I/O in cpu/arm/common +CONTIKI_CPU_DIRS += ../arm/common/dbg-io + +### CPU-dependent source files +CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c cc26xx-rtc.c uart.c +CONTIKI_CPU_SOURCEFILES += cc26xx-rf.c contiki-watchdog.c +CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c +CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c +CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c + +DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c + +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) + +TARGET_START_SOURCEFILES += fault-handlers.c $(TI_CC26XXWARE_STARTUP_SRCS) +TARGET_STARTFILES = $(addprefix $(OBJECTDIR)/,$(call oname, $(TARGET_START_SOURCEFILES))) + +### Don't treat the .elf as intermediate +.PRECIOUS: %.elf %.hex %.bin + +### Always re-build ieee-addr.o in case the command line passes a new NODEID +FORCE: + +$(OBJECTDIR)/ieee-addr.o: ieee-addr.c FORCE | $(OBJECTDIR) + $(TRACE_CC) + $(Q)$(CC) $(CFLAGS) -c $< -o $@ + +### Compilation rules +CUSTOM_RULE_LINK=1 + +%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) + $(TRACE_LD) + $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@ + +%.hex: %.elf + $(OBJCOPY) -O ihex $< $@ + +%.bin: %.elf + $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ + +%.lst: %.elf + $(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ + +### We don't really need the .hex and .bin for the .$(TARGET) but let's make +### sure they get built +%.$(TARGET): %.elf %.hex %.bin + cp $< $@ + +# a target that gives a user-friendly memory profile, taking into account the RAM +# that is statically occupied by the stack as defined in the linker script +# see $(LDSCRIPT) +RAM_SIZE = 0x00003E00 +FLASH_SIZE = 0x0001E000 +STACK_SIZE = 0 +%.size: %.$(TARGET) + @$(SIZE) -A $< | egrep "data|bss" | awk '{s+=$$2} END {s=s+$(STACK_SIZE); f=$(RAM_SIZE)-s; printf "[RAM] used %6d, free %6d\n",s,f;}' + @$(SIZE) -A $< | egrep "text|isr_vector" | awk '{s+=$$2} END {f=$(FLASH_SIZE)-s; printf "[Flash] used %6d, free %6d\n",s,f;}' + diff --git a/cpu/cc26xx/cc26xx-model.h b/cpu/cc26xx/cc26xx-model.h new file mode 100644 index 000000000..44ee1cfe3 --- /dev/null +++ b/cpu/cc26xx/cc26xx-model.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, 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 + * @{ + * + * \defgroup cc26xx-models CC26xx models + * + * The CC26xx comes out in various flavours. Most notable within the context + * of this Contiki port: The CC2630 with IEEE (but no BLE) support and the + * CC2650 with IEEE and BLE support. + * + * This port supports both models and will automatically turn off the BLE code + * if the CC2630 is selected. + * + * @{ + */ +/** + * \file + * Header file with definitions relating to various CC26xx variants + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC26XX_MODEL_H_ +#define CC26XX_MODEL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +#ifdef CC26XX_MODEL_CONF_CPU_VARIANT +#define CC26XX_MODEL_CPU_VARIANT CC26XX_MODEL_CONF_CPU_VARIANT +#else +#define CC26XX_MODEL_CPU_VARIANT 2650 +#endif + +#if (CC26XX_MODEL_CPU_VARIANT != 2630) && (CC26XX_MODEL_CPU_VARIANT != 2650) +#error Incorrect CC26xx variant selected. +#error Check the value of CC26XX_MODEL_CONF_CPU_VARIANT +#error Supported values: 2630 and 2650 +#endif +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_MODEL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/cc26xx.ld b/cpu/cc26xx/cc26xx.ld new file mode 100644 index 000000000..27c39c6c5 --- /dev/null +++ b/cpu/cc26xx/cc26xx.ld @@ -0,0 +1,103 @@ +/* + * 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. + */ + +/* CC26XX linker script */ + +/* Entry Point */ +ENTRY(ResetISR) + +MEMORY +{ + /* Flash Size 128 KB minus the CCA area below (76 bytes) */ + FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001FFAC + + /* + * Customer Configuration Area and Bootloader Backdoor configuration + * in flash, up to 80 bytes + */ + FLASH_CCFG (RX) : ORIGIN = 0x0001FFAC, LENGTH = 84 + + /* RAM Size 20KB (PG2.1) */ + SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00005000 +} + +/*. Highest address of the stack. Used in startup file .*/ +_estack = ORIGIN(SRAM) + LENGTH(SRAM); /* End of SRAM */ + +/*. Generate a link error if heap and stack don’t fit into RAM .*/ +_Min_Heap_Size = 0; +_Min_Stack_Size = 0x100; + +SECTIONS +{ + .text : + { + _text = .; + KEEP(*(.vectors)) + *(.text*) + *(.rodata*) + _etext = .; + } > FLASH = 0 + + .data : + { + _data = .; + *(vtable) + *(.data*) + _edata = .; + } > SRAM AT > FLASH + + .ARM.exidx : + { + *(.ARM.exidx*) + } > FLASH + + .bss : + { + _bss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > SRAM + + .ccfg : + { + KEEP(*(.ccfg)) + } > FLASH_CCFG + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >SRAM +} diff --git a/cpu/cc26xx/clock.c b/cpu/cc26xx/clock.c new file mode 100644 index 000000000..fdf3b9405 --- /dev/null +++ b/cpu/cc26xx/clock.c @@ -0,0 +1,189 @@ +/* + * 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 platform + * @{ + * + * \defgroup cc26xx-platforms TI CC26xx-powered Platforms + * @{ + * + * \defgroup cc26xx The TI CC26xx CPU + * @{ + * + * \addtogroup cc26xx-clocks + * @{ + * + * \defgroup cc26xx-software-clock CC26xx Software Clock + * + * Implementation of the clock module for the cc26xx. + * + * The software clock uses the facilities provided by the AON RTC driver + * @{ + * + * \file + * Software clock implementation for the TI CC26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +static volatile clock_time_t count; +static volatile clock_time_t second_countdown; +static volatile unsigned long secs; +/*---------------------------------------------------------------------------*/ +static void +power_domain_on(void) +{ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != + PRCM_DOMAIN_POWER_ON); +} +/*---------------------------------------------------------------------------*/ +void +clock_init(void) +{ + count = 0; + secs = 0; + second_countdown = CLOCK_SECOND; + + /* + * Here, we configure GPT0 Timer A, which we subsequently use in + * clock_delay_usec + * + * First, enable GPT0 in run mode. We don't need it in sleep mode + */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Disable both GPT0 timers */ + HWREG(GPT0_BASE + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN); + + /* + * We assume that the clock is running at 48MHz, we use GPT0 Timer A, + * one-shot, countdown, prescaled by 48 gives us 1 tick per usec + */ + ti_lib_timer_configure(GPT0_BASE, + TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT); + + /* Global config: split pair (2 x 16-bit wide) */ + HWREG(GPT0_BASE + GPT_O_CFG) = TIMER_CFG_SPLIT_PAIR >> 24; + + /* + * Pre-scale value 47 pre-scales by 48 + * + * ToDo: The theoretical value here should be 47 (to provide x48 prescale) + * However, 49 seems to give results much closer to the desired delay + */ + ti_lib_timer_prescale_set(GPT0_BASE, TIMER_B, 49); + + /* GPT0 / Timer B: One shot, PWM interrupt enable */ + HWREG(GPT0_BASE + GPT_O_TBMR) = + ((TIMER_CFG_B_ONE_SHOT >> 8) & 0xFF) | GPT_TBMR_TBPWMIE; +} +/*---------------------------------------------------------------------------*/ +CCIF clock_time_t +clock_time(void) +{ + return count; +} +/*---------------------------------------------------------------------------*/ +void +clock_update(void) +{ + count++; + if(etimer_pending()) { + etimer_request_poll(); + } + + if(--second_countdown == 0) { + secs++; + second_countdown = CLOCK_SECOND; + } +} +/*---------------------------------------------------------------------------*/ +void +clock_set_seconds(unsigned long sec) +{ + secs = sec; +} +/*---------------------------------------------------------------------------*/ +CCIF unsigned long +clock_seconds(void) +{ + return secs; +} +/*---------------------------------------------------------------------------*/ +void +clock_wait(clock_time_t i) +{ + clock_time_t start; + + start = clock_time(); + while(clock_time() - start < (clock_time_t)i); +} +/*---------------------------------------------------------------------------*/ +void +clock_delay_usec(uint16_t len) +{ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != + PRCM_DOMAIN_POWER_ON) { + power_domain_on(); + } + + ti_lib_timer_load_set(GPT0_BASE, TIMER_B, len); + ti_lib_timer_enable(GPT0_BASE, TIMER_B); + + /* + * Wait for TBEN to clear. CC26xxware does not provide us with a convenient + * function, hence the direct register access here + */ + while(HWREG(GPT0_BASE | GPT_O_CTL) & GPT_CTL_TBEN); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Obsolete delay function but we implement it here since some code + * still uses it + */ +void +clock_delay(unsigned int i) +{ + clock_delay_usec(i); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + * @} + * @} + */ diff --git a/cpu/cc26xx/dbg.h b/cpu/cc26xx/dbg.h new file mode 100644 index 000000000..a5bff7513 --- /dev/null +++ b/cpu/cc26xx/dbg.h @@ -0,0 +1,65 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-char-io CC26xx Character I/O + * + * CC26xx CPU-specific functions for debugging and SLIP I/O + * @{ + * + * \file + * Header file for the CC26xx Debug I/O module + */ +#ifndef DBG_H_ +#define DBG_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Print a stream of bytes + * \param seq A pointer to the stream + * \param len The number of bytes to print + * \return The number of printed bytes + * + * This function is an arch-specific implementation required by the dbg-io + * API in cpu/arm/common/dbg-io. It prints a stream of bytes over the + * peripheral used by the platform. + */ +unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/*---------------------------------------------------------------------------*/ +#endif /* DBG_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/debug-uart.h b/cpu/cc26xx/debug-uart.h new file mode 100644 index 000000000..c2d9b0ffb --- /dev/null +++ b/cpu/cc26xx/debug-uart.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012, 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-char-io + * @{ + * + * \file + * This file is here because DBG I/O expects it to be. It just includes + * our own dbg.h which has a non-misleading name and which also adheres + * to Contiki's naming convention + */ +/*---------------------------------------------------------------------------*/ +#ifndef DEBUG_UART_H_ +#define DEBUG_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "dbg.h" +/*---------------------------------------------------------------------------*/ +#endif /* DEBUG_UART_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/batmon-sensor.c b/cpu/cc26xx/dev/batmon-sensor.c new file mode 100644 index 000000000..8131307a0 --- /dev/null +++ b/cpu/cc26xx/dev/batmon-sensor.c @@ -0,0 +1,143 @@ +/* + * 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-batmon + * @{ + * + * \file + * Driver for the CC26xx AON battery monitor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "batmon-sensor.h" + +#include "ti-lib.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +#define SENSOR_STATUS_DISABLED 0 +#define SENSOR_STATUS_ENABLED 1 + +static int enabled = SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type BATMON_SENSOR_TYPE_TEMP or BATMON_SENSOR_TYPE_VOLT + * + * \return The raw sensor reading, not converted to human-readable form + */ +static int +value(int type) +{ + uint32_t tmp_value; + + if(enabled == SENSOR_STATUS_DISABLED) { + PRINTF("Sensor Disabled\n"); + return 0; + } + + if(type == BATMON_SENSOR_TYPE_TEMP) { + tmp_value = ti_lib_aon_batmon_temperature_get(); + } else if(type == BATMON_SENSOR_TYPE_VOLT) { + tmp_value = ti_lib_aon_batmon_battery_voltage_get(); + } else { + PRINTF("Invalid type\n"); + return 0; + } + + return (int)tmp_value; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the battery monitor sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable If + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_aon_batmon_enable(); + ti_lib_aon_batmon_measurement_cycle_set(AON_BATMON_CYCLE_32); + enabled = SENSOR_STATUS_ENABLED; + break; + case SENSORS_ACTIVE: + if(enable) { + ti_lib_aon_batmon_enable(); + enabled = SENSOR_STATUS_ENABLED; + } else { + ti_lib_aon_batmon_disable(); + enabled = SENSOR_STATUS_DISABLED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the sensor is enabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(batmon_sensor, "Battery Monitor", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/batmon-sensor.h b/cpu/cc26xx/dev/batmon-sensor.h new file mode 100644 index 000000000..12b0c6bbd --- /dev/null +++ b/cpu/cc26xx/dev/batmon-sensor.h @@ -0,0 +1,57 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-batmon CC26xx BatMon sensor driver + * + * Driver for the on-chip battery voltage and chip temperature sensor. + * @{ + * + * \file + * Header file for the CC26xx battery monitor + */ +/*---------------------------------------------------------------------------*/ +#ifndef BATMON_SENSOR_H_ +#define BATMON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#define BATMON_SENSOR_TYPE_TEMP 1 +#define BATMON_SENSOR_TYPE_VOLT 2 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor batmon_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* BATMON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/cc26xx-rf.c b/cpu/cc26xx/dev/cc26xx-rf.c new file mode 100644 index 000000000..c791969e5 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rf.c @@ -0,0 +1,2179 @@ +/* + * 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-rf + * @{ + * + * \file + * Implementation of the CC26xx RF driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/radio.h" +#include "dev/cc26xx-rf.h" +#include "net/packetbuf.h" +#include "net/rime/rimestats.h" +#include "net/linkaddr.h" +#include "net/netstack.h" +#include "sys/energest.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "lpm.h" +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +/* RF core and RF HAL API */ +#include "hw_rfc_dbell.h" +#include "hw_rfc_pwr.h" +/*---------------------------------------------------------------------------*/ +/* RF Core Mailbox API */ +#include "mailbox.h" +#include "common_cmd.h" +#include "common_cmd_field.h" +#include "ble_cmd.h" +#include "ble_cmd_field.h" +#include "ieee_cmd.h" +#include "ieee_cmd_field.h" +#include "data_entry.h" +#include "ble_mailbox.h" +#include "ieee_mailbox.h" +/*---------------------------------------------------------------------------*/ +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define BUSYWAIT_UNTIL(cond, max_time) \ + do { \ + rtimer_clock_t t0; \ + t0 = RTIMER_NOW(); \ + while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ + } while(0) +/*---------------------------------------------------------------------------*/ +#ifndef MIN +#define MIN(n, m) (((n) < (m)) ? (n) : (m)) +#endif +/*---------------------------------------------------------------------------*/ +#ifdef __GNUC__ +#define CC_ALIGN_ATTR(n) __attribute__ ((aligned(n))) +#else +#define CC_ALIGN_ATTR(n) +#endif +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Data entry status field constants */ +#define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */ +#define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */ +#define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */ +#define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */ +#define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */ +/*---------------------------------------------------------------------------*/ +/* RF stats data structure */ +static uint8_t rf_stats[16] = { 0 }; +/*---------------------------------------------------------------------------*/ +/* RF Command status constants - Correspond to values in the CMDSTA register */ +#define RF_CMD_STATUS_PENDING 0x00 +#define RF_CMD_STATUS_DONE 0x01 +#define RF_CMD_STATUS_ILLEGAL_PTR 0x81 +#define RF_CMD_STATUS_UNKNOWN_CMD 0x82 +#define RF_CMD_STATUS_UNKNOWN_DIR_CMD 0x83 +#define RF_CMD_STATUS_CONTEXT_ERR 0x85 +#define RF_CMD_STATUS_SCHEDULING_ERR 0x86 +#define RF_CMD_STATUS_PAR_ERR 0x87 +#define RF_CMD_STATUS_QUEUE_ERR 0x88 +#define RF_CMD_STATUS_QUEUE_BUSY 0x89 + +/* Status values starting with 0x8 correspond to errors */ +#define RF_CMD_STATUS_ERR_MASK 0x80 + +/* Return values for rf_send_cmd_ok */ +#define RF_CMD_ERROR 0 +#define RF_CMD_OK 1 + +/* The size of the RF commands buffer */ +#define RF_CMD_BUFFER_SIZE 128 +/*---------------------------------------------------------------------------*/ +/* RF Radio Op status constants. Field 'status' in Radio Op command struct */ +#define RF_RADIO_OP_STATUS_IDLE 0x0000 +#define RF_RADIO_OP_STATUS_PENDING 0x0001 +#define RF_RADIO_OP_STATUS_ACTIVE 0x0002 +#define RF_RADIO_OP_STATUS_SKIPPED 0x0003 +#define RF_RADIO_OP_STATUS_DONE_OK 0x0400 +#define RF_RADIO_OP_STATUS_DONE_COUNTDOWN 0x0401 +#define RF_RADIO_OP_STATUS_DONE_RXERR 0x0402 +#define RF_RADIO_OP_STATUS_DONE_TIMEOUT 0x0403 +#define RF_RADIO_OP_STATUS_DONE_STOPPED 0x0404 +#define RF_RADIO_OP_STATUS_DONE_ABORT 0x0405 +#define RF_RADIO_OP_STATUS_ERROR_PAST_START 0x0800 +#define RF_RADIO_OP_STATUS_ERROR_START_TRIG 0x0801 +#define RF_RADIO_OP_STATUS_ERROR_CONDITION 0x0802 +#define RF_RADIO_OP_STATUS_ERROR_PAR 0x0803 +#define RF_RADIO_OP_STATUS_ERROR_POINTER 0x0804 +#define RF_RADIO_OP_STATUS_ERROR_CMDID 0x0805 +#define RF_RADIO_OP_STATUS_ERROR_NO_SETUP 0x0807 +#define RF_RADIO_OP_STATUS_ERROR_NO_FS 0x0808 +#define RF_RADIO_OP_STATUS_ERROR_SYNTH_PROG 0x0809 + +/* Additional Op status values for IEEE mode */ +#define RF_RADIO_OP_STATUS_IEEE_SUSPENDED 0x2001 +#define RF_RADIO_OP_STATUS_IEEE_DONE_OK 0x2400 +#define RF_RADIO_OP_STATUS_IEEE_DONE_BUSY 0x2401 +#define RF_RADIO_OP_STATUS_IEEE_DONE_STOPPED 0x2402 +#define RF_RADIO_OP_STATUS_IEEE_DONE_ACK 0x2403 +#define RF_RADIO_OP_STATUS_IEEE_DONE_ACKPEND 0x2404 +#define RF_RADIO_OP_STATUS_IEEE_DONE_TIMEOUT 0x2405 +#define RF_RADIO_OP_STATUS_IEEE_DONE_BGEND 0x2406 +#define RF_RADIO_OP_STATUS_IEEE_DONE_ABORT 0x2407 +#define RF_RADIO_OP_STATUS_ERROR_WRONG_BG 0x0806 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_PAR 0x2800 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_NO_SETUP 0x2801 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_NO_FS 0x2802 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_SYNTH_PROG 0x2803 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_RXOVF 0x2804 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_TXUNF 0x2805 + +/* Op status values for BLE mode */ +#define RF_RADIO_OP_STATUS_BLE_DONE_OK 0x1400 +#define RF_RADIO_OP_STATUS_BLE_DONE_RXTIMEOUT 0x1401 +#define RF_RADIO_OP_STATUS_BLE_DONE_NOSYNC 0x1402 +#define RF_RADIO_OP_STATUS_BLE_DONE_RXERR 0x1403 +#define RF_RADIO_OP_STATUS_BLE_DONE_CONNECT 0x1404 +#define RF_RADIO_OP_STATUS_BLE_DONE_MAXNACK 0x1405 +#define RF_RADIO_OP_STATUS_BLE_DONE_ENDED 0x1406 +#define RF_RADIO_OP_STATUS_BLE_DONE_ABORT 0x1407 +#define RF_RADIO_OP_STATUS_BLE_DONE_STOPPED 0x1408 +#define RF_RADIO_OP_STATUS_BLE_ERROR_PAR 0x1800 +#define RF_RADIO_OP_STATUS_BLE_ERROR_RXBUF 0x1801 +#define RF_RADIO_OP_STATUS_BLE_ERROR_NO_SETUP 0x1802 +#define RF_RADIO_OP_STATUS_BLE_ERROR_NO_FS 0x1803 +#define RF_RADIO_OP_STATUS_BLE_ERROR_SYNTH_PROG 0x1804 +#define RF_RADIO_OP_STATUS_BLE_ERROR_RXOVF 0x1805 +#define RF_RADIO_OP_STATUS_BLE_ERROR_TXUNF 0x1806 + +/* Bits 15:12 signify the protocol */ +#define RF_RADIO_OP_STATUS_PROTO_MASK 0xF000 +#define RF_RADIO_OP_STATUS_PROTO_GENERIC 0x0000 +#define RF_RADIO_OP_STATUS_PROTO_BLE 0x1000 +#define RF_RADIO_OP_STATUS_PROTO_IEEE 0x2000 +#define RF_RADIO_OP_STATUS_PROTO_PROP 0x3000 + +/* Bits 11:10 signify Running / Done OK / Done with error */ +#define RF_RADIO_OP_MASKED_STATUS 0x0C00 +#define RF_RADIO_OP_MASKED_STATUS_RUNNING 0x0000 +#define RF_RADIO_OP_MASKED_STATUS_DONE 0x0400 +#define RF_RADIO_OP_MASKED_STATUS_ERROR 0x0800 +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the current status of a running Radio Op command + * \param a A pointer with the buffer used to initiate the command + * \return The value of the Radio Op buffer's status field + * + * This macro can be used to e.g. return the status of a previously + * initiated background operation, or of an immediate command + */ +#define RF_RADIO_OP_GET_STATUS(a) GET_FIELD_V(a, radioOp, status) +/*---------------------------------------------------------------------------*/ +/* Special value returned by CMD_IEEE_CCA_REQ when an RSSI is not available */ +#define RF_CMD_CCA_REQ_RSSI_UNKNOWN -128 + +/* Used for the return value of channel_clear */ +#define RF_CCA_CLEAR 1 +#define RF_CCA_BUSY 0 + +/* Used as an error return value for get_cca_info */ +#define RF_GET_CCA_INFO_ERROR 0xFF + +/* + * Values of the individual bits of the ccaInfo field in CMD_IEEE_CCA_REQ's + * status struct + */ +#define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 00 */ +#define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 01 */ +#define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 10 */ +/*---------------------------------------------------------------------------*/ +#define RF_MODE_BLE 0 +#define RF_MODE_IEEE 1 +/*---------------------------------------------------------------------------*/ +/* How long to wait for an ongoing ACK TX to finish before starting frame TX */ +#define TX_WAIT_TIMEOUT (RTIMER_SECOND >> 11) + +/* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */ +#define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10) +/*---------------------------------------------------------------------------*/ +/* TX Power dBm lookup table - values from SmartRF Studio */ +typedef struct output_config { + radio_value_t dbm; + uint8_t register_ib; + uint8_t register_gc; +} output_config_t; + +static const output_config_t output_power[] = { + { 5, 0x29, 0x00 }, + { 4, 0x20, 0x00 }, + { 3, 0x19, 0x00 }, + { 2, 0x25, 0x01 }, + { 1, 0x21, 0x01 }, + { 0, 0x1D, 0x01 }, + { -3, 0x19, 0x03 }, + { -6, 0x13, 0x03 }, + { -9, 0x0F, 0x03 }, +}; + +#define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) + +/* Max and Min Output Power in dBm */ +#define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm) +#define OUTPUT_POWER_MAX (output_power[0].dbm) +#define OUTPUT_POWER_UNKNOWN 0xFFFF + +/* Default TX Power - position in output_power[] */ +#define CC26XX_RF_TX_POWER 0 +const output_config_t *tx_power_current = &output_power[0]; +/*---------------------------------------------------------------------------*/ +#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \ + | RFC_PWR_PWMCLKEN_CPERAM_M) +/*---------------------------------------------------------------------------*/ +/* RF interrupts */ +#define RX_IRQ IRQ_IEEE_RX_ENTRY_DONE +#define TX_IRQ IRQ_IEEE_TX_FRAME +#define TX_ACK_IRQ IRQ_IEEE_TX_ACK +#define ERROR_IRQ IRQ_INTERNAL_ERROR + +/* + * We don't really care about TX ISR, we just use it to bring the CM3 out + * of sleep, which it enters while the RF is TXing + */ +#define ENABLED_IRQS (RX_IRQ + TX_IRQ + ERROR_IRQ) + +#define cc26xx_rf_cpe0_isr RFCCPE0IntHandler +#define cc26xx_rf_cpe1_isr RFCCPE1IntHandler +/*---------------------------------------------------------------------------*/ +/* + * Buffers used to send commands to the RF core (generic and IEEE commands). + * Some of those buffers are re-usable, some are not. + * + * If you are uncertain, declare a new buffer. + */ +/* + * A buffer to send a CMD_IEEE_RX and to subsequently monitor its status + * Do not use this buffer for any commands other than CMD_IEEE_RX + */ +static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN_ATTR(4); + +/* + * A buffer used to send immediate and foreground Radio Op (e.g. CMD_IEEE_TX) + * commands. + * + * Do not re-use this buffer to send a command before the previous command + * has been completed. + * + * Do not intermingle preparation of this buffer to send a command with calls + * that might lead to a different command, since the latter will overwrite what + * you have written in preparation for the former. + */ +static uint8_t cmd_immediate_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN_ATTR(4); +/*---------------------------------------------------------------------------*/ +/* BLE macros, variables and buffers */ + +/* BLE Intervals: Send a burst of advertisements every BLE_ADV_INTERVAL secs */ +#define BLE_ADV_INTERVAL (CLOCK_SECOND * 5) +#define BLE_ADV_DUTY_CYCLE (CLOCK_SECOND / 10) +#define BLE_ADV_MESSAGES 10 + +/* BLE Advertisement-related macros */ +#define BLE_ADV_TYPE_DEVINFO 0x01 +#define BLE_ADV_TYPE_NAME 0x09 +#define BLE_ADV_TYPE_MANUFACTURER 0xFF +#define BLE_ADV_NAME_BUF_LEN 32 +#define BLE_ADV_PAYLOAD_BUF_LEN 64 +#define BLE_UUID_SIZE 16 + +#if CC26XX_RF_BLE_SUPPORT +/* BLE buffers / variables */ +static unsigned char ble_cmd_buf[32] CC_ALIGN_ATTR(4) = { 0 }; +static unsigned char ble_tx_rx_buf[128] CC_ALIGN_ATTR(4); +static uint8_t ble_mode_on; + +/* BLE beacond config */ +static struct ble_beacond_config { + clock_time_t interval; + char adv_name[BLE_ADV_NAME_BUF_LEN]; +} beacond_config; + +/* BLE overrides */ +static uint32_t ble_overrides[] = { + 0x00364038, /* Synth: Set RTRIM (POTAILRESTRIM) to 6 */ + 0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */ + 0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */ + 0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */ + 0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */ + 0x00456088, /* Adjust AGC reference level */ + 0xFFFFFFFF, /* End of override list */ +}; + +PROCESS(cc26xx_rf_ble_beacon_process, "CC26xx RF BLE Beacon Process"); + +static void init_ble(void); +#else +#define init_ble(...) +#endif /* CC26XX_RF_BLE_SUPPORT */ +/*---------------------------------------------------------------------------*/ +#define RX_BUF_SIZE 140 +/* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */ +static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN_ATTR(4); +static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN_ATTR(4); +static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN_ATTR(4); +static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN_ATTR(4); + +/* The RX Data Queue */ +static dataQueue_t rx_data_queue = { 0 }; + +/* Receive entry pointer to keep track of read items */ +volatile static uint8_t *rx_read_entry; +/*---------------------------------------------------------------------------*/ +/* The outgoing frame buffer */ +#define TX_BUF_SIZE 180 + +static uint8_t tx_buf[TX_BUF_SIZE]; +/*---------------------------------------------------------------------------*/ +/* Overrides for IEEE 802.15.4, differential mode */ +static uint32_t ieee_overrides[] = { + 0x00354038, /* Synth: Set RTRIM (POTAILRESTRIM) to 5 */ + 0x4001402D, /* Synth: Correct CKVD latency setting (address) */ + 0x00608402, /* Synth: Correct CKVD latency setting (value) */ + 0x4001405D, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (address) */ + 0x1801F800, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (value) */ + 0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */ + 0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */ + 0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */ + 0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */ + 0x002B50DC, /* Adjust AGC DC filter */ + 0x05000243, /* Increase synth programming timeout */ + 0x002082C3, /* Increase synth programming timeout */ + 0xFFFFFFFF, /* End of override list */ +}; +/*---------------------------------------------------------------------------*/ +PROCESS(cc26xx_rf_process, "CC26xx RF driver"); +/*---------------------------------------------------------------------------*/ +static int on(void); +static int off(void); +static void setup_interrupts(void); +/*---------------------------------------------------------------------------*/ +/* Select the HF XOSC as the source for the HF clock, but don't switch yet */ +static void +request_hf_xosc(void) +{ + /* Enable OSC DIG interface to change clock sources */ + ti_lib_osc_interface_enable(); + + /* Make sure the SMPH clock within AUX is enabled */ + ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK); + while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY); + + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { + /* + * Request to switch to the crystal to enable radio operation. It takes a + * while for the XTAL to be ready so instead of performing the actual + * switch, we return and we do other stuff while the XOSC is getting ready. + */ + ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF); + } + + /* Disable OSC DIG interface */ + ti_lib_osc_interface_disable(); +} +/*---------------------------------------------------------------------------*/ +/* + * Switch to the XOSC. This will block until the XOSC is ready, so this must + * be preceded by a call to select_hf_xosc() + */ +static void +switch_to_hf_xosc(void) +{ + /* Enable OSC DIG interface to change clock sources */ + ti_lib_osc_interface_enable(); + + /* Make sure the SMPH clock within AUX is enabled */ + ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK); + while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY); + + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { + /* Switch the HF clock source (cc26xxware executes this from ROM) */ + ti_lib_osc_hf_source_switch(); + } + + /* Disable OSC DIG interface */ + ti_lib_osc_interface_disable(); +} +/*---------------------------------------------------------------------------*/ +static void +switch_to_hf_rc_osc(void) +{ + /* Enable OSC DIG interface to change clock sources */ + ti_lib_osc_interface_enable(); + + /* Make sure the SMPH clock within AUX is enabled */ + ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK); + while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY); + + /* Set all clock sources to the HF RC Osc */ + ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF); + + /* Check to not enable HF RC oscillator if already enabled */ + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_RCOSC_HF) { + /* Switch the HF clock source (cc26xxware executes this from ROM) */ + ti_lib_osc_hf_source_switch(); + } + ti_lib_osc_interface_disable(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +rf_is_accessible(void) +{ + if(ti_lib_prcm_rf_ready() && + ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) == + PRCM_DOMAIN_POWER_ON) { + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Sends a command to the RF core. + * + * \param cmd The command value or a pointer to a command buffer + * \param status A pointer to a variable which will hold the status + * \return RF_CMD_OK or RF_CMD_ERROR + * + * This function supports all three types of command (Radio OP, immediate and + * direct) + * + * For immediate and Radio OPs, cmd is a pointer to the data structure + * containing the command and its parameters. This data structure must be + * 4-byte aligned. + * + * For direct commands, cmd contains the value of the command alongside its + * parameters + * + * The caller is responsible of allocating and populating cmd for Radio OP and + * immediate commands + * + * The caller is responsible for allocating status + */ +static uint_fast8_t +rf_send_cmd(uint32_t cmd, uint32_t *status) +{ + uint32_t timeout_count = 0; + + /* + * Make sure ContikiMAC doesn't turn us off from within an interrupt while + * we are accessing RF Core registers + */ + ti_lib_int_master_disable(); + + if(!rf_is_accessible()) { + PRINTF("rf_send_cmd: RF was off\n"); + ti_lib_int_master_enable(); + return RF_CMD_ERROR; + } + + HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd; + do { + *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA); + if(++timeout_count > 50000) { + PRINTF("rf_send_cmd: Timeout\n"); + ti_lib_int_master_enable(); + return RF_CMD_ERROR; + } + } while(*status == RF_CMD_STATUS_PENDING); + + ti_lib_int_master_enable(); + + /* + * If we reach here the command is no longer pending. It is either completed + * successfully or with error + */ + return *status == RF_CMD_STATUS_DONE; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Checks whether the RFC domain is accessible and the RFC is in IEEE RX + * \return 1: RFC in RX mode (and therefore accessible too). 0 otherwise + */ +static uint8_t +rf_is_on(void) +{ + if(!rf_is_accessible()) { + return 0; + } + + return RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_RADIO_OP_STATUS_ACTIVE; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Check the RF's TX status + * \return 1 RF is transmitting + * \return 0 RF is not transmitting + * + * TX mode may be triggered either by a CMD_IEEE_TX or by the automatic + * transmission of an ACK frame. + */ +static uint8_t +transmitting(void) +{ + uint32_t cmd_status; + + /* If we are off, we are not in TX */ + if(!rf_is_accessible()) { + return 0; + } + + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_IEEE_CCA_REQ)); + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_IEEE_CCA_REQ; + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_ERROR) { + PRINTF("transmitting: CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + return 0; + } + + if((GET_FIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, currentRssi) + == RF_CMD_CCA_REQ_RSSI_UNKNOWN) && + (GET_BITFIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, ccaInfo, ccaEnergy) + == RF_CMD_CCA_REQ_CCA_STATE_BUSY)) { + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns CCA information + * \return RF_GET_CCA_INFO_ERROR if the RF was not on + * \return On success, the return value is formatted as per the ccaInfo field + * of CMD_IEEE_CCA_REQ + * + * It is the caller's responsibility to make sure the RF is on. This function + * will return RF_GET_CCA_INFO_ERROR if the RF is off + * + * This function will in fact wait for a valid RSSI signal + */ +static uint8_t +get_cca_info(void) +{ + uint32_t cmd_status; + int8_t rssi; + + if(!rf_is_on()) { + PRINTF("get_cca_info: Not on\n"); + return RF_GET_CCA_INFO_ERROR; + } + + rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN; + + while(rssi == RF_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) { + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_IEEE_CCA_REQ)); + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_IEEE_CCA_REQ; + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_ERROR) { + PRINTF("get_cca_info: CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + + return RF_GET_CCA_INFO_ERROR; + } + + rssi = GET_FIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, currentRssi); + } + + /* We have a valid RSSI signal. Return the CCA Info */ + return GET_FIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, ccaInfo); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Reads the current signal strength (RSSI) + * \return The current RSSI in dBm or CMD_GET_RSSI_UNKNOWN + * + * This function reads the current RSSI on the currently configured + * channel. + */ +static radio_value_t +get_rssi(void) +{ + uint32_t cmd_status; + int8_t rssi; + uint8_t was_off = 0; + + /* If we are off, turn on first */ + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("get_rssi: on() failed\n"); + return RF_CMD_CCA_REQ_RSSI_UNKNOWN; + } + } + + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_GET_RSSI)); + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_GET_RSSI; + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_ERROR) { + rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN; + } + + /* Current RSSI in bits 23:16 of cmd_status */ + rssi = (cmd_status >> 16) & 0xFF; + + /* If we were off, turn back off */ + if(was_off) { + off(); + } + + return rssi; +} +/*---------------------------------------------------------------------------*/ +/* Returns the current TX power in dBm */ +static radio_value_t +get_tx_power(void) +{ + return tx_power_current->dbm; +} +/*---------------------------------------------------------------------------*/ +/* + * Set TX power to 'at least' power dBm + * This works with a lookup table. If the value of 'power' does not exist in + * the lookup table, TXPOWER will be set to the immediately higher available + * value + */ +static void +set_tx_power(radio_value_t power) +{ + uint32_t cmd_status; + int i; + + /* Send a CMD_SET_TX_POWER command to the RF */ + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_SET_TX_POWER)); + + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_SET_TX_POWER; + + for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) { + if(power <= output_power[i].dbm) { + GET_FIELD(cmd_immediate_buf, CMD_SET_TX_POWER, txPower) = + BITVALUE(CMD_SET_TX_POWER, txPower, IB, output_power[i].register_ib) | + BITVALUE(CMD_SET_TX_POWER, txPower, GC, output_power[i].register_gc) | + BITVALUE(CMD_SET_TX_POWER, txPower, tempCoeff, 0); + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_OK) { + /* Success: Remember the new setting */ + tx_power_current = &output_power[i]; + } else { + PRINTF("set_tx_power: CMDSTA=0x%08lx\n", cmd_status); + } + return; + } + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Wait till running radio Op command completes + * + * \return RF_CMD_ERROR or RF_CMD_OK + * + * RF_CMD_OK will be returned if the Radio Op returned with + * RF_RADIO_OP_STATUS_DONE_OK + * + * RF_CMD_ERROR will be returned in the radio op returned with any other + * RF_RADIO_OP_STATUS_DONE_xyz + */ +static uint_fast8_t +rf_wait_cmd_completed_ok(uint8_t *cmd) +{ + _TYPE_radioOp_status tmp_status; + uint32_t timeoutCount = 0; + + /* + * 0x04XX=DONE, 0x0400=DONE_OK while all other "DONE" values means done + * but with some kind of error (ref. "Common radio operation status codes") + */ + do { + tmp_status = GET_FIELD_V(cmd, radioOp, status); + if(++timeoutCount > 500000) { + return RF_CMD_ERROR; + } + } while((tmp_status & RF_RADIO_OP_MASKED_STATUS) != RF_RADIO_OP_MASKED_STATUS_DONE); + + return tmp_status == RF_RADIO_OP_STATUS_DONE_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Builds common radio parameters for radio operations + * + * \param *cmd Pointer to buffer to add parameters to + * \param command Radio command number (e.g. COMMAND_RADIO_SETUP) + * + * \note The buffer must be emptied with memset() before calling this function + * + * \return None + */ +static void +rf_build_radio_op_cmd(uint8_t *cmd, uint16_t command) +{ + GET_FIELD(cmd, radioOp, commandNo) = command; + GET_FIELD(cmd, radioOp, status) = IDLE; + GET_FIELD(cmd, radioOp, pNextOp) = NULL; + GET_FIELD(cmd, radioOp, startTime) = 0; + GET_FIELD(cmd, radioOp, startTrigger) = TRIG_NOW; + GET_FIELD(cmd, radioOp, condition) = COND_NEVER; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Sends a CMD_RADIO_SETUP for the selected mode (IEEE or BLE) + * \param mode RF_MODE_BLE or RF_MODE_IEEE + * \return RF_CMD_OK or RF_CMD_ERROR + * + * ToDo: Likely to need one more argument to set bNoAdi on first startup + * vs when coming back from sleep + */ +static uint8_t +rf_radio_setup(uint8_t mode) +{ + uint32_t cmd_status; + + /* Create radio setup command */ + memset(cmd_immediate_buf, 0x00, SIZEOF_RADIO_OP(CMD_RADIO_SETUP)); + rf_build_radio_op_cmd(cmd_immediate_buf, CMD_RADIO_SETUP); + + /* Set output power to the current (or default) value */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, txPower) = + BITVALUE(CMD_RADIO_SETUP, txPower, IB, tx_power_current->register_ib) | + BITVALUE(CMD_RADIO_SETUP, txPower, GC, tx_power_current->register_gc) | + BITVALUE(CMD_RADIO_SETUP, txPower, tempCoeff, 0); + + /* Do mode-dependent things (e.g. apply overrides) */ + if(mode == RF_MODE_IEEE) { + /* Add override control pointer */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, pRegOverride) = ieee_overrides; +#if CC26XX_RF_BLE_SUPPORT + } else if(mode == RF_MODE_BLE) { + /* Add override control pointer */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, pRegOverride) = ble_overrides; +#endif + } else { + PRINTF("rf_radio_setup: Unknown mode %u\n", mode); + return RF_CMD_ERROR; + } + + /* Lastly, set the mode */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, mode) = mode; + + /* Send Radio setup to RF Core */ + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) != RF_CMD_OK) { + PRINTF("rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + return RF_CMD_ERROR; + } + + /* Wait until radio setup is done */ + if(rf_wait_cmd_completed_ok(cmd_immediate_buf) != RF_CMD_OK) { + PRINTF("rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Applies patches (if any) + * \return RF_CMD_OK or RF_CMD_ERROR + * + * Currently patches are not required. + */ +static uint8_t +apply_patches() +{ + uint32_t cmd_status; + + /* Patch of uninitialized pointer */ + *((uint32_t *)0x21000028) = 0x00000000; + + /* Start radio timer (RAT) */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_START_RAT), &cmd_status) != RF_CMD_OK) { + PRINTF("apply_patches: START_RAT fail, CMDSTA=0x%08lx\n", cmd_status); + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Set up radio in IEEE802.15.4 RX mode + * + * \return RF_CMD_OK Succeeded + * \return RF_CMD_ERROR Failed + * + * This function assumes that cmd_ieee_rx_buf has been previously populated + * with correct values. This can be done through init_rf_params (sets defaults) + * or through Contiki's extended RF API (set_value, set_object) + */ +static uint8_t +rf_cmd_ieee_rx() +{ + uint32_t cmd_status; + rtimer_clock_t t0; + int ret; + + ret = rf_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status); + + if(ret != RF_CMD_OK) { + PRINTF("rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", + ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + } + + t0 = RTIMER_NOW(); + + while(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_RADIO_OP_STATUS_ACTIVE && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT))); + + /* Wait to enter RX */ + if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_RADIO_OP_STATUS_ACTIVE) { + PRINTF("rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + return RF_CMD_ERROR; + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static void +init_rx_buffers(void) +{ + /* Two-element circular buffer, hardcoded for now.. */ + GET_FIELD(rx_buf_0, dataEntry, pNextEntry) = rx_buf_1; + GET_FIELD(rx_buf_0, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_0, dataEntry, length) = sizeof(rx_buf_0) - 8; + + GET_FIELD(rx_buf_1, dataEntry, pNextEntry) = rx_buf_2; + GET_FIELD(rx_buf_1, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_1, dataEntry, length) = sizeof(rx_buf_1) - 8; + + GET_FIELD(rx_buf_2, dataEntry, pNextEntry) = rx_buf_3; + GET_FIELD(rx_buf_2, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_2, dataEntry, length) = sizeof(rx_buf_2) - 8; + + /* Point to first element again */ + GET_FIELD(rx_buf_3, dataEntry, pNextEntry) = rx_buf_0; + GET_FIELD(rx_buf_3, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_3, dataEntry, length) = sizeof(rx_buf_3) - 8; +} +/*---------------------------------------------------------------------------*/ +static void +init_rf_params(void) +{ + memset(cmd_ieee_rx_buf, 0x00, SIZEOF_RADIO_OP(CMD_IEEE_RX)); + + GET_FIELD(cmd_ieee_rx_buf, radioOp, commandNo) = CMD_IEEE_RX; + GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE; + GET_FIELD(cmd_ieee_rx_buf, radioOp, pNextOp) = NULL; + GET_FIELD(cmd_ieee_rx_buf, radioOp, startTime) = 0x00000000; + GET_FIELD(cmd_ieee_rx_buf, radioOp, startTrigger) = TRIG_NOW; + GET_FIELD(cmd_ieee_rx_buf, radioOp, condition) = COND_NEVER; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, channel) = CC26XX_RF_CHANNEL; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, rxConfig) = + BITVALUE(CMD_IEEE_RX, rxConfig, bAutoFlushCrc, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAutoFlushIgn, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bIncludePhyHdr, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bIncludeCrc, 1) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendRssi, 1) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendCorrCrc, 1) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendSrcInd, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendTimestamp, 0); + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pRxQ) = &rx_data_queue; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pOutput) = rf_stats; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt) = +#if CC26XX_RF_CONF_PROMISCOUS + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltEn, 0) | +#else + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltEn, 1) | +#endif + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltStop, 1) | +#if CC26XX_RF_CONF_AUTOACK + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoAckEn, 1) | +#else + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoAckEn, 0) | +#endif + BITVALUE(CMD_IEEE_RX, frameFiltOpt, slottedAckEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoPendEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, defaultPend, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPendDataReqOnly, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPanCoord, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bStrictLenFilter, 0); + /* Receive all frame types */ + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameTypes) = + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt0Beacon, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt1Data, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt2Ack, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt3MacCmd, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt4Reserved, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt5Reserved, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt6Reserved, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt7Reserved, 1); + /* Configure CCA settings */ + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaOpt) = + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaEnEnergy, 1) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaEnCorr, 0) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaEnSync, 0) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaCorrOp, 0) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaSyncOp, 0); + /* Set CCA RSSI Threshold, 0xA6 corresponds to -90dBm (two's comp.)*/ + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaRssiThr) = 0xA6; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, numExtEntries) = 0x00; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, numShortEntries) = 0x00; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pExtEntryList) = 0; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pShortEntryList) = 0; + + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, endTrigger) = TRIG_NEVER; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, endTime) = 0x00000000; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Turn on power to the RFC and boot it. + * + * \return RF_CMD_OK or RF_CMD_ERROR + */ +static int +power_up(void) +{ + uint32_t cmd_status; + + ti_lib_int_master_disable(); + ti_lib_int_pend_clear(INT_RF_CPE0); + ti_lib_int_pend_clear(INT_RF_CPE1); + ti_lib_int_disable(INT_RF_CPE0); + ti_lib_int_disable(INT_RF_CPE1); + + /* Enable RF Core power domain */ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) + != PRCM_DOMAIN_POWER_ON); + + ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + while(!rf_is_accessible()) { + PRINTF("power_up: Not ready\n"); + } + + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0; + ti_lib_int_enable(INT_RF_CPE0); + ti_lib_int_enable(INT_RF_CPE1); + ti_lib_int_master_enable(); + + /* Let CPE boot */ + HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK; + + /* Send ping (to verify RFCore is ready and alive) */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CMD_OK) { + PRINTF("power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status); + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD + */ +static void +power_down(void) +{ + ti_lib_int_master_disable(); + ti_lib_int_disable(INT_RF_CPE0); + ti_lib_int_disable(INT_RF_CPE1); + + if(rf_is_accessible()) { + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0; + } + + /* Shut down the RFCORE clock domain in the MCU VD */ + ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Turn off RFCORE PD */ + ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) + != PRCM_DOMAIN_POWER_OFF); + + ti_lib_int_pend_clear(INT_RF_CPE0); + ti_lib_int_pend_clear(INT_RF_CPE1); + ti_lib_int_enable(INT_RF_CPE0); + ti_lib_int_enable(INT_RF_CPE1); + ti_lib_int_master_enable(); +} +/*---------------------------------------------------------------------------*/ +static int +rx_on(void) +{ + int ret; + + /* Get status of running IEEE_RX (if any) */ + if(rf_is_on()) { + PRINTF("rx_on: We were on. PD=%u, RX=0x%04x \n", rf_is_accessible(), + RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + return RF_CMD_OK; + } + + /* Put CPE in RX using the currently configured parameters */ + ret = rf_cmd_ieee_rx(); + + if(ret) { + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +rx_off(void) +{ + uint32_t cmd_status; + int ret; + + /* If we are off, do nothing */ + if(!rf_is_on()) { + return RF_CMD_OK; + } + + /* Wait for ongoing ACK TX to finish */ + while(transmitting()); + + /* Send a CMD_STOP command to RF Core */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CMD_OK) { + PRINTF("RX off: CMD_ABORT status=0x%08lx\n", cmd_status); + /* Continue nonetheless */ + } + + while(rf_is_on()); + + if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED || + RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) { + /* Stopped gracefully */ + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + ret = RF_CMD_OK; + } else { + PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + ret = RF_CMD_ERROR; + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static void +rx_isr(void) +{ + process_poll(&cc26xx_rf_process); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_cpe1_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + ti_lib_int_master_disable(); + PRINTF("RF Error\n"); + + if(!rf_is_accessible()) { + if(power_up() != RF_CMD_OK) { + return; + } + } + + /* Clear interrupt flags */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + ti_lib_int_master_enable(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_cpe0_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + if(!rf_is_accessible()) { + printf("RF ISR called but RF not ready... PANIC!!\n"); + if(power_up() != RF_CMD_OK) { + PRINTF("power_up() failed\n"); + return; + } + } + + ti_lib_int_master_disable(); + if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_IRQ) { + rx_isr(); + } + + /* Clear interrupt flags */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + ti_lib_int_master_enable(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +static void +setup_interrupts(void) +{ + /* We are already turned on by the caller, so this should not happen */ + if(!rf_is_accessible()) { + PRINTF("setup_interrupts: No access\n"); + return; + } + + /* Disable interrupts */ + ti_lib_int_master_disable(); + + /* Set all interrupt channels to CPE0 channel, error to CPE1 */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ; + + /* Acknowledge TX_Frame, Rx_Entry_Done and ERROR */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS; + + /* Clear interrupt flags, active low clear(?) */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + + ti_lib_int_pend_clear(INT_RF_CPE0); + ti_lib_int_pend_clear(INT_RF_CPE1); + ti_lib_int_enable(INT_RF_CPE0); + ti_lib_int_enable(INT_RF_CPE1); + ti_lib_int_master_enable(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +request(void) +{ + /* + * We rely on the RDC layer to turn us on and off. Thus, if we are on we + * will only allow sleep, standby otherwise + */ + if(rf_is_on()) { + return LPM_MODE_SLEEP; + } + + return LPM_MODE_MAX_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL); +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + lpm_register_module(&cc26xx_rf_lpm_module); + + /* Enable IEEE, BLE and Common-CMD APIs */ + HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5; + + /* Wipe out the BLE adv buffer */ + init_ble(); + + /* Initialise RX buffers */ + memset(rx_buf_0, 0, RX_BUF_SIZE); + memset(rx_buf_1, 0, RX_BUF_SIZE); + memset(rx_buf_2, 0, RX_BUF_SIZE); + memset(rx_buf_3, 0, RX_BUF_SIZE); + + /* Set of RF Core data queue. Circular buffer, no last entry */ + rx_data_queue.pCurrEntry = rx_buf_0; + + rx_data_queue.pLastEntry = NULL; + + /* Initialize current read pointer to first element (used in ISR) */ + rx_read_entry = rx_buf_0; + + /* Populate the RF parameters data structure with default values */ + init_rf_params(); + + if(on() != RF_CMD_OK) { + PRINTF("init: on() failed\n"); + return RF_CMD_ERROR; + } + + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + process_start(&cc26xx_rf_process, NULL); + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +prepare(const void *payload, unsigned short payload_len) +{ + int len = MIN(payload_len, sizeof(tx_buf)); + + memcpy(tx_buf, payload, len); + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static int +transmit(unsigned short transmit_len) +{ + int ret; + uint8_t was_off = 0; + uint32_t cmd_status; + uint16_t stat; + uint8_t tx_active = 0; + rtimer_clock_t t0; + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("transmit: on() failed\n"); + return RF_CMD_ERROR; + } + } + + /* + * We are certainly not TXing a frame as a result of CMD_IEEE_TX, but we may + * be in the process of TXing an ACK. In that case, wait for the TX to finish + * or return after approx TX_WAIT_TIMEOUT + */ + t0 = RTIMER_NOW(); + + do { + tx_active = transmitting(); + } while(tx_active == 1 && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TX_WAIT_TIMEOUT))); + + if(tx_active) { + PRINTF("transmit: Already TXing and wait timed out\n"); + + if(was_off) { + off(); + } + + return RADIO_TX_COLLISION; + } + + /* Send the CMD_IEEE_TX command */ + memset(cmd_immediate_buf, 0, SIZEOF_RADIO_OP(CMD_IEEE_TX)); + + rf_build_radio_op_cmd(cmd_immediate_buf, CMD_IEEE_TX); + + GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, payloadLen) = transmit_len; + GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, pPayload) = tx_buf; + + ret = rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status); + + if(ret) { + /* If we enter here, TX actually started */ + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); + + /* Idle away while the command is running */ + while((RF_RADIO_OP_GET_STATUS(cmd_immediate_buf) & RF_RADIO_OP_MASKED_STATUS) + == RF_RADIO_OP_MASKED_STATUS_RUNNING) { + lpm_sleep(); + } + + stat = RF_RADIO_OP_GET_STATUS(cmd_immediate_buf); + + if(stat == RF_RADIO_OP_STATUS_IEEE_DONE_OK) { + /* Sent OK */ + RIMESTATS_ADD(lltx); + ret = RADIO_TX_OK; + } else { + /* Operation completed, but frame was not sent */ + PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret, + cmd_status, stat); + ret = RADIO_TX_ERR; + } + } else { + /* Failure sending the CMD_IEEE_TX command */ + PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", + ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + + ret = RADIO_TX_ERR; + } + + /* + * Update ENERGEST state here, before a potential call to off(), which + * will correctly update it if required. + */ + ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + if(was_off) { + off(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +send(const void *payload, unsigned short payload_len) +{ + prepare(payload, payload_len); + return transmit(payload_len); +} +/*---------------------------------------------------------------------------*/ +static int +read_frame(void *buf, unsigned short buf_len) +{ + int len = 0; + + if(GET_FIELD_V(rx_read_entry, dataEntry, status) == DATA_ENTRY_STATUS_FINISHED) { + /* Set status to 0 "Pending" in element */ + GET_FIELD_V(rx_read_entry, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + + if(rx_read_entry[8] > 0) { + memcpy(buf, (char *)&rx_read_entry[9], buf_len); + + /* Remove the footer */ + len = MIN(buf_len, rx_read_entry[8] - 4); + + int rssi = (int8_t)rx_read_entry[9 + len + 2]; + + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + RIMESTATS_ADD(llrx); + + /* Clear the length byte */ + rx_read_entry[8] = 0; + } + + /* Move read entry pointer to next entry */ + rx_read_entry = GET_FIELD_V(rx_read_entry, dataEntry, pNextEntry); + } + + return len; +} +/*---------------------------------------------------------------------------*/ +static int +channel_clear(void) +{ + uint8_t was_off = 0; + uint8_t cca_info; + int ret = RF_CCA_CLEAR; + + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. Indicate a clear channel + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("channel_clear: Interrupt context but BLE in progress\n"); + return RF_CCA_CLEAR; + } +#endif + + if(rf_is_on()) { + /* + * Wait for potential leftover ACK still being sent. + * Strictly speaking, if we are TXing an ACK then the channel is not clear. + * However, channel_clear is only ever called to determine whether there is + * someone else's packet in the air, not ours. + * + * We could probably even simply return that the channel is clear + */ + while(transmitting()); + } else { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("channel_clear: on() failed\n"); + if(was_off) { + off(); + } + return RF_CCA_CLEAR; + } + } + + cca_info = get_cca_info(); + + if(cca_info == RF_GET_CCA_INFO_ERROR) { + PRINTF("channel_clear: CCA error\n"); + ret = RF_CCA_CLEAR; + } else { + /* + * cca_info bits 1:0 - ccaStatus + * Return 1 (clear) if idle or invalid. + */ + ret = (cca_info & 0x03) != RF_CMD_CCA_REQ_CCA_STATE_BUSY; + } + + if(was_off) { + off(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +receiving_packet(void) +{ + int ret = 0; + uint8_t cca_info; + uint8_t was_off = 0; + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("receiving_packet: on() failed\n"); + return RF_CMD_ERROR; + } + } + + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. We are not receiving + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("receiving_packet: Interrupt context but BLE in progress\n"); + return 0; + } +#endif + + /* If we are off, we are not receiving */ + if(!rf_is_on()) { + PRINTF("receiving_packet: We were off\n"); + return 0; + } + + /* If we are transmitting (can only be an ACK here), we are not receiving */ + if(transmitting()) { + PRINTF("receiving_packet: We were TXing\n"); + return 0; + } + + cca_info = get_cca_info(); + + if(cca_info == RF_GET_CCA_INFO_ERROR) { + /* If we can't read CCA info, return "not receiving" */ + ret = 0; + } else { + /* Return 1 (receiving) if ccaState is busy */ + ret = (cca_info & 0x03) == RF_CMD_CCA_REQ_CCA_STATE_BUSY; + } + + if(was_off) { + off(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + volatile uint8_t *current = rx_data_queue.pCurrEntry; + int rv = 0; + + /* Go through all RX buffers and check their status */ + do { + if(GET_FIELD_V(current, dataEntry, status) == + DATA_ENTRY_STATUS_FINISHED) { + rv = 1; + process_poll(&cc26xx_rf_process); + } + + current = GET_FIELD_V(current, dataEntry, pNextEntry); + } while(current != rx_data_queue.pCurrEntry); + + /* If we didn't find an entry at status finished, no frames are pending */ + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + /* + * Request the HF XOSC as the source for the HF clock. Needed before we can + * use the FS. This will only request, it will _not_ perform the switch. + */ + request_hf_xosc(); + + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. Abort, but pretend everything is OK. + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("on: Interrupt context but BLE in progress\n"); + return RF_CMD_OK; + } +#endif + + if(rf_is_on()) { + PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_is_accessible(), + RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + return RF_CMD_OK; + } + + if(power_up() != RF_CMD_OK) { + PRINTF("on: power_up() failed\n"); + return RF_CMD_ERROR; + } + + if(apply_patches() != RF_CMD_OK) { + PRINTF("on: apply_patches() failed\n"); + return RF_CMD_ERROR; + } + + init_rx_buffers(); + + setup_interrupts(); + + /* + * Trigger a switch to the XOSC, so that we can subsequently use the RF FS + * This will block until the XOSC is actually ready, but give how we + * requested it early on, this won't be too long a wait/ + */ + switch_to_hf_xosc(); + + if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) { + PRINTF("on: radio_setup() failed\n"); + return RF_CMD_ERROR; + } + + return rx_on(); +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. Abort, but pretend everything is OK. + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("off: Interrupt context but BLE in progress\n"); + return RF_CMD_OK; + } +#endif + + while(transmitting()); + + power_down(); + + /* Switch HF clock source to the RCOSC to preserve power */ + switch_to_hf_rc_osc(); + + /* We pulled the plug, so we need to restore the status manually */ + GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE; + + /* + * Just in case there was an ongoing RX (which started after we begun the + * shutdown sequence), we don't want to leave the buffer in state == ongoing + */ + GET_FIELD_V(rx_buf_0, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + GET_FIELD_V(rx_buf_1, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + GET_FIELD_V(rx_buf_2, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + GET_FIELD_V(rx_buf_3, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch(param) { + case RADIO_PARAM_POWER_MODE: + /* On / off */ + *value = rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = (radio_value_t)GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, channel); + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + *value = (radio_value_t)GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localPanID); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + *value = (radio_value_t)GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localShortAddr); + return RADIO_RESULT_OK; + case RADIO_PARAM_RX_MODE: + *value = 0; + if(GET_BITFIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt, frameFiltEn)) { + *value |= RADIO_RX_MODE_ADDRESS_FILTER; + } + if(GET_BITFIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt, autoAckEn)) { + *value |= RADIO_RX_MODE_AUTOACK; + } + + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + *value = get_tx_power(); + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + *value = GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaRssiThr); + return RADIO_RESULT_OK; + case RADIO_PARAM_RSSI: + *value = get_rssi(); + + if(*value == RF_CMD_CCA_REQ_RSSI_UNKNOWN) { + return RADIO_RESULT_ERROR; + } else { + return RADIO_RESULT_OK; + } + case RADIO_CONST_CHANNEL_MIN: + *value = CC26XX_RF_CHANNEL_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = CC26XX_RF_CHANNEL_MAX; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MIN: + *value = OUTPUT_POWER_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = OUTPUT_POWER_MAX; + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + uint8_t was_off = 0; + radio_result_t rv; + + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + if(on() != RF_CMD_OK) { + PRINTF("set_value: on() failed (1)\n"); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < CC26XX_RF_CHANNEL_MIN || + value > CC26XX_RF_CHANNEL_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, channel) = (uint8_t)value; + break; + case RADIO_PARAM_PAN_ID: + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localPanID) = (uint16_t)value; + break; + case RADIO_PARAM_16BIT_ADDR: + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localShortAddr) = (uint16_t)value; + break; + case RADIO_PARAM_RX_MODE: + { + if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | + RADIO_RX_MODE_AUTOACK)) { + return RADIO_RESULT_INVALID_VALUE; + } + + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt) = + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltEn, + (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltStop, 1) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoAckEn, + (value & RADIO_RX_MODE_AUTOACK) != 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, slottedAckEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoPendEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, defaultPend, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPendDataReqOnly, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPanCoord, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bStrictLenFilter, 0); + + break; + } + case RADIO_PARAM_TXPOWER: + if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + + set_tx_power(value); + + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaRssiThr) = (int8_t)value; + break; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } + + /* If we reach here we had no errors. Apply new settings */ + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("set_value: on() failed (2)\n"); + return RADIO_RESULT_ERROR; + } + } + + if(rx_off() != RF_CMD_OK) { + PRINTF("set_value: rx_off() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + if(rx_on() != RF_CMD_OK) { + PRINTF("set_value: rx_on() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + /* If we were off, turn back off */ + if(was_off) { + off(); + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + uint8_t *target; + uint8_t *src; + int i; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size != 8 || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + + target = dest; + src = (uint8_t *)(GET_FIELD_PTR(cmd_ieee_rx_buf, CMD_IEEE_RX, localExtAddr)); + + for(i = 0; i < 8; i++) { + target[i] = src[7 - i]; + } + + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + uint8_t was_off = 0; + radio_result_t rv; + int i; + uint8_t *dst; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size != 8 || !src) { + return RADIO_RESULT_INVALID_VALUE; + } + + dst = (uint8_t *)(GET_FIELD_PTR(cmd_ieee_rx_buf, CMD_IEEE_RX, + localExtAddr)); + + for(i = 0; i < 8; i++) { + dst[i] = ((uint8_t *)src)[7 - i]; + } + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("set_object: on() failed\n"); + return RADIO_RESULT_ERROR; + } + } + + if(rx_off() != RF_CMD_OK) { + PRINTF("set_object: rx_off() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + if(rx_on() != RF_CMD_OK) { + PRINTF("set_object: rx_on() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + /* If we were off, turn back off */ + if(was_off) { + off(); + } + + return rv; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver cc26xx_rf_driver = { + init, + prepare, + transmit, + send, + read_frame, + channel_clear, + receiving_packet, + pending_packet, + on, + off, + get_value, + set_value, + get_object, + set_object, +}; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc26xx_rf_process, ev, data) +{ + int len; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT(); + do { + packetbuf_clear(); + len = read_frame(packetbuf_dataptr(), PACKETBUF_SIZE); + + if(len > 0) { + packetbuf_set_datalen(len); + + NETSTACK_RDC.input(); + } + } while(len > 0); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +#if CC26XX_RF_BLE_SUPPORT +/*---------------------------------------------------------------------------*/ +/** + * \brief Builds common radio parameters for radio operations + * + * \param *cmd Pointer to buffer to add parameters to + * \param command Radio command number (e.g. COMMAND_RADIO_SETUP) + * + * \note The buffer must be emptied with memset() before calling this function + * + * \return None + */ +static void +rf_build_ble_radio_op_cmd(uint8_t *cmd, uint16_t command) +{ + GET_FIELD(cmd, radioOp, commandNo) = command; + GET_FIELD(cmd, radioOp, status) = IDLE; + GET_FIELD(cmd, radioOp, pNextOp) = NULL; + GET_FIELD(cmd, radioOp, startTime) = 0; + GET_FIELD(cmd, radioOp, startTrigger) = TRIG_NOW; + GET_FIELD(cmd, radioOp, condition) = COND_NEVER; +} +/*---------------------------------------------------------------------------*/ +static void +init_ble() +{ + ble_mode_on = 0; + + memset(beacond_config.adv_name, 0, BLE_ADV_NAME_BUF_LEN); + beacond_config.interval = BLE_ADV_INTERVAL; +} +/*---------------------------------------------------------------------------*/ +static int +send_ble_adv_nc(int channel, uint8_t *output, uint8_t *adv_payload, + int adv_payload_len, uint16_t *dev_address) +{ + uint32_t cmd_status; + int ret; + + /* Erase ble_tx_rx_buf array */ + memset(ble_tx_rx_buf, 0x00, SIZEOF_RADIO_OP(CMD_BLE_ADV_NC)); + rf_build_ble_radio_op_cmd(ble_tx_rx_buf, CMD_BLE_ADV_NC); + + GET_FIELD(ble_tx_rx_buf, bleRadioOp, channel) = channel; + GET_FIELD(ble_tx_rx_buf, bleRadioOp, whitening) = 0; + + memset(ble_cmd_buf, 0x00, SIZEOF_STRUCT(bleAdvPar)); + GET_FIELD(ble_tx_rx_buf, bleRadioOp, pParams) = (uint8_t *)ble_cmd_buf; + GET_FIELD(ble_tx_rx_buf, bleRadioOp, pOutput) = output; + + /* Set up BLE Advertisement parameters */ + GET_FIELD(ble_cmd_buf, bleAdvPar, pRxQ) = NULL; + GET_FIELD(ble_cmd_buf, bleAdvPar, rxConfig) = 0; + GET_FIELD(ble_cmd_buf, bleAdvPar, advConfig) = 0; + GET_FIELD(ble_cmd_buf, bleAdvPar, advLen) = adv_payload_len; + GET_FIELD(ble_cmd_buf, bleAdvPar, scanRspLen) = 0; + GET_FIELD(ble_cmd_buf, bleAdvPar, pAdvData) = adv_payload; + GET_FIELD(ble_cmd_buf, bleAdvPar, pScanRspData) = NULL; + GET_FIELD(ble_cmd_buf, bleAdvPar, pDeviceAddress) = dev_address; + GET_FIELD(ble_cmd_buf, bleAdvPar, pWhiteList) = NULL; + GET_FIELD(ble_cmd_buf, bleAdvPar, endTrigger) = TRIG_NEVER; + GET_FIELD(ble_cmd_buf, bleAdvPar, endTime) = TRIG_NEVER; + + if(rf_send_cmd((uint32_t)ble_tx_rx_buf, &cmd_status) == RF_CMD_ERROR) { + PRINTF("send_ble_adv_nc: Chan=%d CMDSTA=0x%08lx, status=0x%04x\n", + channel, cmd_status, RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf)); + return RF_CMD_ERROR; + } + + /* Wait for the ADV_NC to go out */ + while((RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf) & RF_RADIO_OP_MASKED_STATUS) + == RF_RADIO_OP_MASKED_STATUS_RUNNING); + + if(RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf) == RF_RADIO_OP_STATUS_BLE_DONE_OK) { + /* Sent OK */ + ret = RF_CMD_OK; + } else { + /* Radio Op completed, but ADV NC was not sent */ + PRINTF("send_ble_adv_nc: Chan=%d CMDSTA=0x%08lx, status=0x%04x\n", + channel, cmd_status, RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf)); + ret = RF_CMD_ERROR; + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +send_ble_adv(int channel, uint8_t *adv_payload, int adv_payload_len) +{ + if(send_ble_adv_nc(channel, rf_stats, adv_payload, adv_payload_len, + (uint16_t *)&linkaddr_node_addr.u8[2]) != RF_CMD_OK) { + PRINTF("send_ble_adv: Channel=%d, Error advertising\n", channel); + /* Break the loop, but don't return just yet */ + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) +{ + static struct etimer ble_adv_et; + static uint8_t payload[BLE_ADV_PAYLOAD_BUF_LEN]; + static int p = 0; + static int i; + uint8_t was_on; + int j; + uint32_t cmd_status; + + PROCESS_BEGIN(); + + while(1) { + etimer_set(&ble_adv_et, beacond_config.interval); + + PROCESS_WAIT_EVENT(); + + if(ev == PROCESS_EVENT_EXIT) { + PROCESS_EXIT(); + } + + /* Set the adv payload each pass: The device name may have changed */ + p = 0; + + /* device info */ + payload[p++] = 0x02; /* 2 bytes */ + payload[p++] = BLE_ADV_TYPE_DEVINFO; + payload[p++] = 0x1a; /* LE general discoverable + BR/EDR */ + payload[p++] = 1 + strlen(beacond_config.adv_name); + payload[p++] = BLE_ADV_TYPE_NAME; + memcpy(&payload[p], beacond_config.adv_name, + strlen(beacond_config.adv_name)); + p += strlen(beacond_config.adv_name); + + for(i = 0; i < BLE_ADV_MESSAGES; i++) { + /* + * Under ContikiMAC, some IEEE-related operations will be called from an + * interrupt context. We need those to see that we are in BLE mode. + */ + ti_lib_int_master_disable(); + ble_mode_on = 1; + ti_lib_int_master_enable(); + + /* + * Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three + * channels, with a BLE_ADV_DUTY_CYCLE interval between bursts + * + * First, determine our state: + * + * If we are running NullRDC, we are likely in IEEE RX mode. We need to + * abort the IEEE BG Op before entering BLE mode. + * If we are ContikiMAC, we are likely off, in which case we need to + * boot the CPE before entering BLE mode + */ + was_on = rf_is_accessible(); + + if(was_on) { + /* + * We were on: If we are in the process of receiving an IEEE frame, + * abort the BLE beacon burst. Otherwise, terminate the IEEE BG Op + * so we can switch to BLE mode + */ + if(receiving_packet()) { + PRINTF("cc26xx_rf_ble_beacon_process: We were receiving\n"); + + /* Abort this pass */ + break; + } + + if(rx_off() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: rx_off() failed\n"); + + /* Abort this pass */ + break; + } + } else { + /* Request the HF XOSC to source the HF clock. */ + request_hf_xosc(); + + /* We were off: Boot the CPE */ + if(power_up() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: power_up() failed\n"); + + /* Abort this pass */ + break; + } + + if(apply_patches() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: apply_patches() failed\n"); + + /* Abort this pass */ + break; + } + + /* Trigger a switch to the XOSC, so that we can use the FS */ + switch_to_hf_xosc(); + } + + /* Enter BLE mode */ + if(rf_radio_setup(RF_MODE_BLE) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: Error entering BLE mode\n"); + /* Continue so we can at least try to restore our previous state */ + } else { + /* Send advertising packets on all 3 advertising channels */ + for(j = 37; j <= 39; j++) { + if(send_ble_adv(j, payload, p) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: Channel=%d," + "Error advertising\n", j); + /* Break the loop, but don't return just yet */ + break; + } + } + } + + /* Send a CMD_STOP command to RF Core */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_STOP), &cmd_status) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: status=0x%08lx\n", cmd_status); + /* Continue... */ + } + + if(was_on) { + /* We were on, go back to IEEE mode */ + if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: radio_setup() failed\n"); + } + + /* Enter IEEE RX mode */ + if(rx_on() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: rx_on() failed\n"); + } + } else { + power_down(); + + /* Switch HF clock source to the RCOSC to preserve power */ + switch_to_hf_rc_osc(); + } + etimer_set(&ble_adv_et, BLE_ADV_DUTY_CYCLE); + + ti_lib_int_master_disable(); + ble_mode_on = 0; + ti_lib_int_master_enable(); + + /* Wait unless this is the last burst */ + if(i < BLE_ADV_MESSAGES - 1) { + PROCESS_WAIT_EVENT(); + } + } + + ti_lib_int_master_disable(); + ble_mode_on = 0; + ti_lib_int_master_enable(); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_RF_BLE_SUPPORT */ +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_ble_beacond_config(clock_time_t interval, const char *name) +{ +#if CC26XX_RF_BLE_SUPPORT + if(name != NULL) { + memset(beacond_config.adv_name, 0, BLE_ADV_NAME_BUF_LEN); + + if(strlen(name) == 0 || strlen(name) >= BLE_ADV_NAME_BUF_LEN) { + return; + } + + memcpy(beacond_config.adv_name, name, strlen(name)); + } + + if(interval != 0) { + beacond_config.interval = interval; + } +#endif +} +/*---------------------------------------------------------------------------*/ +uint8_t +cc26xx_rf_ble_beacond_start() +{ +#if CC26XX_RF_BLE_SUPPORT + if(beacond_config.adv_name[0] == 0) { + return RF_CMD_ERROR; + } + + process_start(&cc26xx_rf_ble_beacon_process, NULL); + + return RF_CMD_OK; +#else + return RF_CMD_ERROR; +#endif +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_ble_beacond_stop() +{ +#if CC26XX_RF_BLE_SUPPORT + process_exit(&cc26xx_rf_ble_beacon_process); +#endif +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/cc26xx-rf.h b/cpu/cc26xx/dev/cc26xx-rf.h new file mode 100644 index 000000000..4087a037d --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rf.h @@ -0,0 +1,116 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-rf CC26xx RF driver + * + * The CC26xx RF has dual capability: It can operate in IEEE 802.15.4 mode at + * 2.4GHz, but it can also operate in BLE mode. This driver provides a fully + * contiki-compliant .15.4 functionality, but it also provides some very basic + * BLE capability. + * + * @{ + */ +/** + * \file + * Header file for the CC26xx RF driver + */ +#ifndef CC26XX_RF_H_ +#define CC26XX_RF_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "cc26xx-model.h" +#include "dev/radio.h" +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ +#ifdef CC26XX_RF_CONF_CHANNEL +#define CC26XX_RF_CHANNEL CC26XX_RF_CONF_CHANNEL +#else +#define CC26XX_RF_CHANNEL 18 +#endif /* CC26XX_RF_CONF_CHANNEL */ + +#ifdef CC26XX_RF_CONF_AUTOACK +#define CC26XX_RF_AUTOACK CC26XX_RF_CONF_AUTOACK +#else +#define CC26XX_RF_AUTOACK 1 +#endif /* CC26XX_RF_CONF_AUTOACK */ + +#if defined (CC26XX_RF_CONF_BLE_SUPPORT) && (CC26XX_MODEL_CPU_VARIANT == 2650) +#define CC26XX_RF_BLE_SUPPORT CC26XX_RF_CONF_BLE_SUPPORT +#else +#define CC26XX_RF_BLE_SUPPORT 0 +#endif +/*--------------------------------------------------------------------------- + * RF Config + *---------------------------------------------------------------------------*/ +/* Constants */ +#define CC26XX_RF_CHANNEL_MIN 11 +#define CC26XX_RF_CHANNEL_MAX 26 +#define CC26XX_RF_CHANNEL_SPACING 5 +#define CC26XX_RF_CHANNEL_SET_ERROR -1 +#define CC26XX_RF_MAX_PACKET_LEN 127 +#define CC26XX_RF_MIN_PACKET_LEN 4 +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the device name to use with the BLE advertisement/beacon daemon + * \param interval The interval (ticks) between two consecutive beacon bursts + * \param name The device name to advertise + * + * If name is NULL it will be ignored. If interval==0 it will be ignored. Thus, + * this function can be used to configure a single parameter at a time if so + * desired. + */ +void cc26xx_rf_ble_beacond_config(clock_time_t interval, const char *name); + +/** + * \brief Start the BLE advertisement/beacon daemon + * \return 1: Success, 0: Failure + * + * Before calling this function, the name to advertise must first be set by + * calling cc26xx_rf_ble_beacond_set_adv_name(). Otherwise, this function will + * return an error. + */ +uint8_t cc26xx_rf_ble_beacond_start(void); + +/** + * \brief Stop the BLE advertisement/beacon daemon + */ +void cc26xx_rf_ble_beacond_stop(void); +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_RF_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/cc26xx-rtc.c b/cpu/cc26xx/dev/cc26xx-rtc.c new file mode 100644 index 000000000..b06aebd22 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rtc.c @@ -0,0 +1,127 @@ +/* + * 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-rtc + * @{ + * + */ +/** + * \file + * Implementation of the CC26xx AON RTC driver + */ +#include "contiki.h" +#include "sys/energest.h" +#include "rtimer.h" +#include "lpm.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#define cc26xx_rtc_isr(...) AONRTCIntHandler(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* Prototype of a function in clock.c. Called every time the handler fires */ +void clock_update(void); +/*---------------------------------------------------------------------------*/ +void +cc26xx_rtc_init(void) +{ + uint32_t compare_value; + + /* Disable and clear interrupts */ + ti_lib_int_master_disable(); + ti_lib_aon_rtc_disable(); + + ti_lib_aon_rtc_event_clear(AON_RTC_CH0); + ti_lib_aon_rtc_event_clear(AON_RTC_CH2); + + /* Setup the wakeup event */ + ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU0, AON_EVENT_RTC0); + ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC2); + + /* Configure channel 2 in continuous compare, 128 ticks / sec */ + compare_value = (RTIMER_SECOND / CLOCK_SECOND) + + ti_lib_aon_rtc_current_compare_value_get(); + ti_lib_aon_rtc_compare_value_set(AON_RTC_CH2, compare_value); + ti_lib_aon_rtc_inc_value_ch2_set(RTIMER_SECOND / CLOCK_SECOND); + ti_lib_aon_rtc_mode_ch2_set(AON_RTC_MODE_CH2_CONTINUOUS); + + /* Enable event generation for channels 0 and 2 and enable the RTC */ + ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2); + ti_lib_aon_rtc_channel_enable(AON_RTC_CH2); + + ti_lib_aon_rtc_enable(); + + ti_lib_int_enable(INT_AON_RTC); + ti_lib_int_master_enable(); +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +cc26xx_rtc_get_next_trigger() +{ + rtimer_clock_t ch2 = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH2); + + if(HWREG(AON_RTC_BASE + AON_RTC_O_CHCTL) & AON_RTC_CHCTL_CH0_EN) { + rtimer_clock_t ch0 = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH2); + + return RTIMER_CLOCK_LT(ch0 ,ch2) ? ch0 : ch2; + } + + return ch2; +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rtc_schedule_one_shot(uint32_t ticks) +{ + /* Set the channel to fire a one-shot compare event at time==ticks */ + ti_lib_aon_rtc_compare_value_set(AON_RTC_CH0, ticks); + ti_lib_aon_rtc_channel_enable(AON_RTC_CH0); +} +/*---------------------------------------------------------------------------*/ +/* The AON RTC interrupt handler */ +void +cc26xx_rtc_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + if(ti_lib_aon_rtc_event_get(AON_RTC_CH0)) { + ti_lib_aon_rtc_event_clear(AON_RTC_CH0); + rtimer_run_next(); + } + + if(ti_lib_aon_rtc_event_get(AON_RTC_CH2)) { + ti_lib_aon_rtc_event_clear(AON_RTC_CH2); + clock_update(); + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/cc26xx-rtc.h b/cpu/cc26xx/dev/cc26xx-rtc.h new file mode 100644 index 000000000..4fbaa1795 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rtc.h @@ -0,0 +1,100 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-clocks CC26xx clock and timer subsystem + * + * For the CC26xx cpu we use the AON RTC as the basis for all clocks and timers + * + * We configure the AON RTC's channel 2 to run in continuous mode, generating + * 128 interrupts / second. In continuous mode, the next compare event is + * scheduled by the hardware automatically; the events are equidistant and + * this also means we don't need the overhead of re-scheduling within the + * interrupt handler + * + * For rtimers, we use the RTC's channel 0 in one-shot compare mode. When the + * compare event fires, we call rtimer_run_next + * + * The RTC runs in all power modes except 'shutdown' + * + * \sa cpu/cc26xx/clock.c cpu/cc26xx/rtimer-arch.c + * @{ + * + * \defgroup cc26xx-rtc CC26xx AON RTC driver + * + * Underpins the platform's software clocks and timers + * + * @{ + * \file + * Header file for the CC26XX AON RTC driver + */ +#ifndef CC26XX_RTC_H_ +#define CC26XX_RTC_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "rtimer.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the CC26XX AON RTC module + * + * This timer configures the AON RTC's channel 2 to run in continuous mode + * This function must be called before clock_init() and rtimer_init() + */ +void cc26xx_rtc_init(void); + +/** + * \brief Return the time of the next scheduled rtimer event + * \return The time at which the next rtimer event is due to fire + * + * This function will check both AON RTC channels and will only take CH0's + * compare into account if the channel is actually enabled + */ +rtimer_clock_t cc26xx_rtc_get_next_trigger(void); + +/** + * \brief Schedule an AON RTC channel 0 one-shot compare event + * \param t The time when the event will be fired. This is an absolute + * time, in other words the event will fire AT time \e t, + * not IN \e t ticks + */ +void cc26xx_rtc_schedule_one_shot(uint32_t t); +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_RTC_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/cc26xx-uart.c b/cpu/cc26xx/dev/cc26xx-uart.c new file mode 100644 index 000000000..5a45bb03b --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-uart.c @@ -0,0 +1,249 @@ +/* + * 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. + */ +#include "contiki-conf.h" +#include "cc26xx-uart.h" +#include "hw_types.h" +#include "hw_memmap.h" +#include "sys_ctrl.h" +#include "prcm.h" +#include "ioc.h" +#include "uart.h" +#include "lpm.h" +#include "ti-lib.h" +#include "sys/energest.h" + +#include +/*---------------------------------------------------------------------------*/ +/* Which events to trigger a UART interrupt */ +#define CC26XX_UART_RX_INTERRUPT_TRIGGERS (UART_INT_RX | UART_INT_RT) + +/* All interrupt masks */ +#define CC26XX_UART_INTERRUPT_ALL (UART_INT_OE | UART_INT_BE | UART_INT_PE | \ + UART_INT_FE | UART_INT_RT | UART_INT_TX | \ + UART_INT_RX | UART_INT_CTS) +/*---------------------------------------------------------------------------*/ +#define cc26xx_uart_isr UART0IntHandler +/*---------------------------------------------------------------------------*/ +static int (*input_handler)(unsigned char c); +/*---------------------------------------------------------------------------*/ +static void +power_domain_on(void) +{ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON); +} +/*---------------------------------------------------------------------------*/ +static void +configure_baud_rate(void) +{ + /* + * Configure the UART for 115,200, 8-N-1 operation. + * This function uses SysCtrlClockGet() to get the system clock + * frequency. This could be also be a variable or hard coded value + * instead of a function call. + */ + ti_lib_uart_config_set_exp_clk(UART0_BASE, + ti_lib_sys_ctrl_peripheral_clock_get( + PRCM_PERIPH_UART0, + SYSCTRL_SYSBUS_ON), + CC26XX_UART_CONF_BAUD_RATE, + (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | + UART_CONFIG_PAR_NONE)); +} +/*---------------------------------------------------------------------------*/ +static void +configure_registers(void) +{ + /* + * Map UART signals to the correct GPIO pins and configure them as + * hardware controlled. + */ + ti_lib_ioc_pin_type_uart(UART0_BASE, BOARD_IOID_UART_RX, BOARD_IOID_UART_TX, + BOARD_IOID_UART_CTS, BOARD_IOID_UART_RTS); + + configure_baud_rate(); + + /* + * Generate an RX interrupt at FIFO 1/2 full. + * We don't really care about the TX interrupt + */ + ti_lib_uart_fifo_level_set(UART0_BASE, UART_FIFO_TX7_8, UART_FIFO_RX4_8); + + /* Configure which interrupts to generate: FIFO level or after RX timeout */ + ti_lib_uart_int_enable(UART0_BASE, CC26XX_UART_RX_INTERRUPT_TRIGGERS); +} +/*---------------------------------------------------------------------------*/ +static void +uart_on(void) +{ + power_domain_on(); + + /* Configure baud rate and enable */ + if((HWREG(UART0_BASE + UART_O_CTL) & UART_CTL_UARTEN) == 0) { + configure_registers(); + + /* Enable UART */ + ti_lib_uart_enable(UART0_BASE); + } +} +/*---------------------------------------------------------------------------*/ +static uint8_t +lpm_permit_max_pm_handler(void) +{ + return LPM_MODE_MAX_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static void +lpm_drop_handler(uint8_t mode) +{ + /* Do nothing if the PD is off */ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON) { + return; + } + + /* Wait for outstanding TX to complete */ + while(ti_lib_uart_busy(UART0_BASE)); + + /* + * Check our clock gate under Deep Sleep. If it's off, we can shut down. If + * it's on, this means that some other code module wants UART functionality + * during deep sleep, so we stay enabled + */ + if((HWREG(PRCM_BASE + PRCM_O_UARTCLKGDS) & 1) == 0) { + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_UART_RX); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_UART_TX); + + ti_lib_uart_disable(UART0_BASE); + } +} +/*---------------------------------------------------------------------------*/ +static void +lpm_wakeup_handler(void) +{ + uart_on(); +} +/*---------------------------------------------------------------------------*/ +/* Declare a data structure to register with LPM. */ +LPM_MODULE(uart_module, lpm_permit_max_pm_handler, + lpm_drop_handler, lpm_wakeup_handler); +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_init() +{ + /* Exit without initialising if ports are misconfigured */ + if(BOARD_IOID_UART_RX == IOID_UNUSED || + BOARD_IOID_UART_TX == IOID_UNUSED) { + return; + } + + /* Enable the serial domain and wait for domain to be on */ + power_domain_on(); + + /* Enable the UART clock when running and sleeping */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0); + + /* Apply clock settings and wait for them to take effect */ + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Disable Interrupts */ + ti_lib_int_master_disable(); + + /* Make sure the peripheral is disabled */ + ti_lib_uart_disable(UART0_BASE); + + /* Disable all UART module interrupts */ + ti_lib_uart_int_disable(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); + + configure_registers(); + + /* Acknowledge UART interrupts */ + ti_lib_int_enable(INT_UART0); + + /* Re-enable processor interrupts */ + ti_lib_int_master_enable(); + + /* Enable UART */ + ti_lib_uart_enable(UART0_BASE); + + /* Register ourselves with the LPM module */ + lpm_register_module(&uart_module); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_write_byte(uint8_t c) +{ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON) { + return; + } + + ti_lib_uart_char_put(UART0_BASE, c); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_set_input(int (*input)(unsigned char c)) +{ + input_handler = input; + return; +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_isr(void) +{ + char the_char; + uint32_t flags; + + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* Read out the masked interrupt status */ + flags = ti_lib_uart_int_status(UART0_BASE, true); + + /* Clear all UART interrupt flags */ + ti_lib_uart_int_clear(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); + + if((flags & CC26XX_UART_RX_INTERRUPT_TRIGGERS) != 0) { + /* + * If this was a FIFO RX or an RX timeout, read all bytes available in the + * RX FIFO. + */ + while(ti_lib_uart_chars_avail(UART0_BASE)) { + the_char = ti_lib_uart_char_get_non_blocking(UART0_BASE); + + if(input_handler != NULL) { + input_handler((unsigned char)the_char); + } + } + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} diff --git a/cpu/cc26xx/dev/cc26xx-uart.h b/cpu/cc26xx/dev/cc26xx-uart.h new file mode 100644 index 000000000..4647b9339 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-uart.h @@ -0,0 +1,76 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-uart CC26xx UARTs + * + * Driver for the CC26xx UART controller + * @{ + * + * \file + * Header file for the CC26xx UART driver + */ +#ifndef CC26XX_UART_H_ +#define CC26XX_UART_H_ + +#include +/*---------------------------------------------------------------------------*/ +/** \name UART functions + * @{ + */ + +/** + * \brief Initialises the UART controller, configures I/O control + * and interrupts + */ +void cc26xx_uart_init(); + +/** + * \brief Sends a single character down the UART + * \param b The character to transmit + */ +void cc26xx_uart_write_byte(uint8_t b); + +/** + * \brief Assigns a callback to be called when the UART receives a byte + * \param input A pointer to the function + */ +void cc26xx_uart_set_input(int (*input)(unsigned char c)); + +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_UART_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/contiki-watchdog.c b/cpu/cc26xx/dev/contiki-watchdog.c new file mode 100644 index 000000000..8241b5045 --- /dev/null +++ b/cpu/cc26xx/dev/contiki-watchdog.c @@ -0,0 +1,99 @@ +/* + * 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-clocks + * @{ + * + * \defgroup cc26xx-wdt CC26xx watchdog timer driver + * + * Driver for the CC26xx Watchdog Timer + * + * This file is not called watchdog.c because the filename is in use by + * TI CC26xxware + * @{ + * + * \file + * Implementation of the cc26xx watchdog driver. + */ +#include "watchdog.h" +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialises the CC26xx WDT + * + * Simply sets the reload counter to a default value. The WDT is not started + * yet. To start it, watchdog_start() must be called. + */ +void +watchdog_init(void) +{ + ti_lib_wathdog_reload_set(0xFFFFF); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Starts the CC26xx WDT + */ +void +watchdog_start(void) +{ + ti_lib_wathdog_reset_enable(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Refreshes the CC26xx WDT + */ +void +watchdog_periodic(void) +{ + ti_lib_wathdog_int_clear(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Stub function to satisfy API requirements + */ +void +watchdog_stop(void) +{ +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Manually trigger a WDT reboot + */ +void +watchdog_reboot(void) +{ + watchdog_start(); + while(1); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/gpio-interrupt.c b/cpu/cc26xx/dev/gpio-interrupt.c new file mode 100644 index 000000000..a2c6dd42b --- /dev/null +++ b/cpu/cc26xx/dev/gpio-interrupt.c @@ -0,0 +1,97 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +#include "gpio-interrupt.h" +#include "sys/energest.h" +#include "lpm.h" +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#define gpio_interrupt_isr GPIOIntHandler +/*---------------------------------------------------------------------------*/ +/* Handler array */ +static gpio_interrupt_handler_t handlers[NUM_IO_MAX]; +/*---------------------------------------------------------------------------*/ +void +gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f) +{ + uint8_t interrupts_disabled = ti_lib_int_master_disable(); + + /* Clear interrupts on specified pins */ + ti_lib_gpio_event_clear(1 << ioid); + + handlers[ioid] = f; + + /* Re-enable interrupts */ + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +gpio_interrupt_init() +{ + int i; + + for(i = 0; i < NUM_IO_MAX; i++) { + handlers[i] = NULL; + } + + ti_lib_int_enable(INT_EDGE_DETECT); +} +/*---------------------------------------------------------------------------*/ +void +gpio_interrupt_isr(void) +{ + uint32_t pin_mask; + uint8_t i; + + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* Read interrupt flags */ + pin_mask = (HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) & GPIO_PIN_MASK); + + /* Clear the interrupt flags */ + HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) = pin_mask; + + /* Run custom ISRs */ + for(i = 0; i < NUM_GPIO_PINS; i++) { + /* Call the handler if there is one registered for this event */ + if((pin_mask & (1 << i)) && handlers[i] != NULL) { + handlers[i](i); + } + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ + diff --git a/cpu/cc26xx/dev/gpio-interrupt.h b/cpu/cc26xx/dev/gpio-interrupt.h new file mode 100644 index 000000000..6a64f26f6 --- /dev/null +++ b/cpu/cc26xx/dev/gpio-interrupt.h @@ -0,0 +1,71 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-gpio-interrupts CC26xx GPIO interrupt handling + * + * The CC26xx GPIO interrupt handler and an API which can be used by other + * parts of the code when they wish to be notified of a GPIO interrupt + * + * @{ + * + * \file + * Header file for the CC26xx GPIO interrupt management + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_INTERRUPT_H_ +#define GPIO_INTERRUPT_H_ +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ +typedef void (*gpio_interrupt_handler_t)(uint8_t ioid); +/*---------------------------------------------------------------------------*/ +/** \brief Initialise the GPIO interrupt handling module */ +void gpio_interrupt_init(void); + +/** + * \brief Register a GPIO interrupt handler + * \param f Pointer to a handler to be called when an interrupt is raised on + * ioid + * \param ioid Associate \a f with this ioid. \e ioid must be specified with + * its numeric representation (0, 1, .. 31). Defines for these + * numeric representations are IOID_x + */ +void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f); + +#endif /* GPIO_INTERRUPT_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/rfc-api/ble_cmd.h b/cpu/cc26xx/dev/rfc-api/ble_cmd.h new file mode 100644 index 000000000..f7320fe4d --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ble_cmd.h @@ -0,0 +1,1082 @@ +/****************************************************************************** +* Filename: ble_cmd.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for Bluetooth Low Energy commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef __BLE_CMD_H +#define __BLE_CMD_H + +#ifndef __RFC_STRUCT +#ifdef __GNUC__ +#define __RFC_STRUCT __attribute__ ((aligned (4))) +#else +#define __RFC_STRUCT +#endif +#endif + +//! \addtogroup rfc +//! @{ + +//! \addtogroup ble_cmd +//! @{ + +#include +#include "mailbox.h" +#include "common_cmd.h" + +typedef struct __RFC_STRUCT rfc_bleMasterPar_s rfc_bleMasterPar_t; +typedef struct __RFC_STRUCT rfc_bleMasterSlavePar_s rfc_bleMasterSlavePar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_INITIATOR_s rfc_CMD_BLE_INITIATOR_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_TX_TEST_s rfc_CMD_BLE_TX_TEST_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_MASTER_s rfc_CMD_BLE_MASTER_t; +typedef struct __RFC_STRUCT rfc_bleWhiteListEntry_s rfc_bleWhiteListEntry_t; +typedef struct __RFC_STRUCT rfc_bleGenericRxPar_s rfc_bleGenericRxPar_t; +typedef struct __RFC_STRUCT rfc_bleTxTestPar_s rfc_bleTxTestPar_t; +typedef struct __RFC_STRUCT rfc_bleInitiatorOutput_s rfc_bleInitiatorOutput_t; +typedef struct __RFC_STRUCT rfc_bleWhiteListEntryWords_s rfc_bleWhiteListEntryWords_t; +typedef struct __RFC_STRUCT rfc_bleMasterSlaveOutput_s rfc_bleMasterSlaveOutput_t; +typedef struct __RFC_STRUCT rfc_bleRxStatus_s rfc_bleRxStatus_t; +typedef struct __RFC_STRUCT rfc_bleRadioOp_s rfc_bleRadioOp_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_NC_s rfc_CMD_BLE_ADV_NC_t; +typedef struct __RFC_STRUCT rfc_bleTxTestOutput_s rfc_bleTxTestOutput_t; +typedef struct __RFC_STRUCT rfc_bleAdvPar_s rfc_bleAdvPar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_SCAN_s rfc_CMD_BLE_ADV_SCAN_t; +typedef struct __RFC_STRUCT rfc_bleAdvOutput_s rfc_bleAdvOutput_t; +typedef struct __RFC_STRUCT rfc_bleScannerOutput_s rfc_bleScannerOutput_t; +typedef struct __RFC_STRUCT rfc_bleSlavePar_s rfc_bleSlavePar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_DIR_s rfc_CMD_BLE_ADV_DIR_t; +typedef struct __RFC_STRUCT rfc_bleInitiatorPar_s rfc_bleInitiatorPar_t; +typedef struct __RFC_STRUCT rfc_bleScannerPar_s rfc_bleScannerPar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_SLAVE_s rfc_CMD_BLE_SLAVE_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_s rfc_CMD_BLE_ADV_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_SCANNER_s rfc_CMD_BLE_SCANNER_t; +typedef struct __RFC_STRUCT rfc_bleGenericRxOutput_s rfc_bleGenericRxOutput_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_GENERIC_RX_s rfc_CMD_BLE_GENERIC_RX_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_PAYLOAD_s rfc_CMD_BLE_ADV_PAYLOAD_t; + +//! \addtogroup bleRadioOp +//! @{ +struct __RFC_STRUCT rfc_bleRadioOp_s { + uint16_t commandNo; //!< The command ID number + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + uint8_t* pParams; //!< Pointer to command specific parameter structure + uint8_t* pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_SLAVE +//! @{ +#define CMD_BLE_SLAVE 0x1801 +struct __RFC_STRUCT rfc_CMD_BLE_SLAVE_s { + uint16_t commandNo; //!< The command ID number 0x1801 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleSlavePar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleMasterSlaveOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_MASTER +//! @{ +#define CMD_BLE_MASTER 0x1802 +struct __RFC_STRUCT rfc_CMD_BLE_MASTER_s { + uint16_t commandNo; //!< The command ID number 0x1802 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleMasterPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleMasterSlaveOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV +//! @{ +#define CMD_BLE_ADV 0x1803 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_s { + uint16_t commandNo; //!< The command ID number 0x1803 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_DIR +//! @{ +#define CMD_BLE_ADV_DIR 0x1804 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_DIR_s { + uint16_t commandNo; //!< The command ID number 0x1804 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_NC +//! @{ +#define CMD_BLE_ADV_NC 0x1805 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_NC_s { + uint16_t commandNo; //!< The command ID number 0x1805 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_SCAN +//! @{ +#define CMD_BLE_ADV_SCAN 0x1806 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_SCAN_s { + uint16_t commandNo; //!< The command ID number 0x1806 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_SCANNER +//! @{ +#define CMD_BLE_SCANNER 0x1807 +struct __RFC_STRUCT rfc_CMD_BLE_SCANNER_s { + uint16_t commandNo; //!< The command ID number 0x1807 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleScannerPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleScannerOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_INITIATOR +//! @{ +#define CMD_BLE_INITIATOR 0x1808 +struct __RFC_STRUCT rfc_CMD_BLE_INITIATOR_s { + uint16_t commandNo; //!< The command ID number 0x1808 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleInitiatorPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleInitiatorOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_GENERIC_RX +//! @{ +#define CMD_BLE_GENERIC_RX 0x1809 +struct __RFC_STRUCT rfc_CMD_BLE_GENERIC_RX_s { + uint16_t commandNo; //!< The command ID number 0x1809 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleGenericRxPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleGenericRxOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_TX_TEST +//! @{ +#define CMD_BLE_TX_TEST 0x180A +struct __RFC_STRUCT rfc_CMD_BLE_TX_TEST_s { + uint16_t commandNo; //!< The command ID number 0x180A + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleTxTestPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleTxTestOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_PAYLOAD +//! @{ +#define CMD_BLE_ADV_PAYLOAD 0x1001 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_PAYLOAD_s { + uint16_t commandNo; //!< The command ID number 0x1001 + uint8_t payloadType; //!< \brief 0: Advertising data
+ //!< 1: Scan response data + uint8_t newLen; //!< Length of the new payload + uint8_t* pNewData; //!< Pointer to the buffer containing the new data + rfc_bleAdvPar_t *pParams; //!< Pointer to the parameter structure to update +}; + +//! @} + +//! \addtogroup bleMasterSlavePar +//! @{ +struct __RFC_STRUCT rfc_bleMasterSlavePar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + dataQueue_t* pTxQ; //!< Pointer to transmit queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t lastRxSn:1; //!< The SN bit of the header of the last packet received with CRC OK + uint8_t lastTxSn:1; //!< The SN bit of the header of the last transmitted packet + uint8_t nextTxSn:1; //!< The SN bit of the header of the next packet to transmit + uint8_t bFirstPkt:1; //!< For slave: 0 if a packet has been transmitted on the connection, 1 otherwise + uint8_t bAutoEmpty:1; //!< 1 if the last transmitted packet was an auto-empty packet + uint8_t bLlCtrlTx:1; //!< 1 if the last transmitted packet was an LL control packet (LLID = 11) + uint8_t bLlCtrlAckRx:1; //!< 1 if the last received packet was the ACK of an LL control packet + uint8_t bLlCtrlAckPending:1; //!< 1 if the last successfully received packet was an LL control packet which has not yet been ACK'ed + } seqStat; + uint8_t maxNack; //!< Maximum number of NACKs received before operation ends. 0: No limit + uint8_t maxPkt; //!< Maximum number of packets transmitted in the operation before it ends. 0: No limit + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte +}; + +//! @} + +//! \addtogroup bleMasterPar +//! @{ +//! Parameter structure for master (CMD_BLE_MASTER) + +struct __RFC_STRUCT rfc_bleMasterPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + dataQueue_t* pTxQ; //!< Pointer to transmit queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t lastRxSn:1; //!< The SN bit of the header of the last packet received with CRC OK + uint8_t lastTxSn:1; //!< The SN bit of the header of the last transmitted packet + uint8_t nextTxSn:1; //!< The SN bit of the header of the next packet to transmit + uint8_t bFirstPkt:1; //!< For slave: 0 if a packet has been transmitted on the connection, 1 otherwise + uint8_t bAutoEmpty:1; //!< 1 if the last transmitted packet was an auto-empty packet + uint8_t bLlCtrlTx:1; //!< 1 if the last transmitted packet was an LL control packet (LLID = 11) + uint8_t bLlCtrlAckRx:1; //!< 1 if the last received packet was the ACK of an LL control packet + uint8_t bLlCtrlAckPending:1; //!< 1 if the last successfully received packet was an LL control packet which has not yet been ACK'ed + } seqStat; + uint8_t maxNack; //!< Maximum number of NACKs received before operation ends. 0: No limit + uint8_t maxPkt; //!< Maximum number of packets transmitted in the operation before it ends. 0: No limit + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the connection event as soon as allowed + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< connection event as soon as allowed +}; + +//! @} + +//! \addtogroup bleSlavePar +//! @{ +//! Parameter structure for slave (CMD_BLE_SLAVE) + +struct __RFC_STRUCT rfc_bleSlavePar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + dataQueue_t* pTxQ; //!< Pointer to transmit queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t lastRxSn:1; //!< The SN bit of the header of the last packet received with CRC OK + uint8_t lastTxSn:1; //!< The SN bit of the header of the last transmitted packet + uint8_t nextTxSn:1; //!< The SN bit of the header of the next packet to transmit + uint8_t bFirstPkt:1; //!< For slave: 0 if a packet has been transmitted on the connection, 1 otherwise + uint8_t bAutoEmpty:1; //!< 1 if the last transmitted packet was an auto-empty packet + uint8_t bLlCtrlTx:1; //!< 1 if the last transmitted packet was an LL control packet (LLID = 11) + uint8_t bLlCtrlAckRx:1; //!< 1 if the last received packet was the ACK of an LL control packet + uint8_t bLlCtrlAckPending:1; //!< 1 if the last successfully received packet was an LL control packet which has not yet been ACK'ed + } seqStat; + uint8_t maxNack; //!< Maximum number of NACKs received before operation ends. 0: No limit + uint8_t maxPkt; //!< Maximum number of packets transmitted in the operation before it ends. 0: No limit + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } timeoutTrigger; //!< Trigger that defines timeout of the first receive operation + ratmr_t timeoutTime; //!< \brief Time used together with timeoutTrigger that defines timeout of the first + //!< receive operation + uint16_t __dummy0; + uint8_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the connection event as soon as allowed + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< connection event as soon as allowed +}; + +//! @} + +//! \addtogroup bleAdvPar +//! @{ +//! Parameter structure for advertiser (CMD_BLE_ADV*) + +struct __RFC_STRUCT rfc_bleAdvPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t advFilterPolicy:2; //!< \brief The advertiser filter policy, as defined in Volume 2, Part E, Section 7.8.5 of + //!< the Bluetooth 4.0 spec + uint8_t deviceAddrType:1; //!< The type of the device address – public (0) or random (1) + uint8_t peerAddrType:1; //!< Directed advertiser: The type of the peer address – public (0) or random (1) + uint8_t bStrictLenFilter:1; //!< 1: Discard messages with illegal length + } advConfig; + uint8_t advLen; //!< Size of advertiser data + uint8_t scanRspLen; //!< Size of scan response data + uint8_t* pAdvData; //!< Pointer to buffer containing ADV*_IND data + uint8_t* pScanRspData; //!< Pointer to buffer containing SCAN_RSP data + uint16_t* pDeviceAddress; //!< Pointer to device address used for this device + rfc_bleWhiteListEntry_t *pWhiteList; //!< Pointer to white list or peer address (directed advertiser) + uint16_t __dummy0; + uint8_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the advertiser event as soon as allowed + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< advertiser event as soon as allowed +}; + +//! @} + +//! \addtogroup bleScannerPar +//! @{ +//! Parameter structure for scanner (CMD_BLE_SCANNER) + +struct __RFC_STRUCT rfc_bleScannerPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t scanFilterPolicy:1; //!< \brief The advertiser filter policy, as defined in Volume 2, Part E, Section 7.8.10 of + //!< the Bluetooth 4.0 spec + uint8_t bActiveScan:1; //!< \brief 0: Passive scan
+ //!< 1: Active scan + uint8_t deviceAddrType:1; //!< The type of the device address – public (0) or random (1) + uint8_t :1; + uint8_t bStrictLenFilter:1; //!< 1: Discard messages with illegal length + uint8_t bAutoWlIgnore:1; //!< 1: Automatically set ignore bit in white list + uint8_t bEndOnRpt:1; //!< 1: End scanner operation after each reported ADV*_IND and potentially SCAN_RSP + } scanConfig; + uint16_t randomState; //!< State for pseudo-random number generation used in backoff procedure + uint16_t backoffCount; //!< Parameter backoffCount used in backoff procedure, cf. Bluetooth 4.0 spec + struct { + uint8_t logUpperLimit:4; //!< Binary logarithm of parameter upperLimit used in scanner backoff procedure + uint8_t bLastSucceeded:1; //!< \brief 1 if the last SCAN_RSP was successfully received and upperLimit + //!< not changed + uint8_t bLastFailed:1; //!< \brief 1 if reception of the last SCAN_RSP failed and upperLimit was not + //!< changed + } backoffPar; + uint8_t scanReqLen; //!< Size of scan request data + uint8_t* pScanReqData; //!< Pointer to buffer containing SCAN_REQ data + uint16_t* pDeviceAddress; //!< Pointer to device address used for this device + rfc_bleWhiteListEntry_t *pWhiteList; //!< Pointer to white list + uint16_t __dummy0; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } timeoutTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + ratmr_t timeoutTime; //!< \brief Time used together with timeoutTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_RXTIMEOUT + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_ENDED +}; + +//! @} + +//! \addtogroup bleInitiatorPar +//! @{ +//! Parameter structure for initiator (CMD_BLE_INITIATOR) + +struct __RFC_STRUCT rfc_bleInitiatorPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t bUseWhiteList:1; //!< \brief Initiator filter policy, cf. Volume 2, Part E, Section 7.8.10 of the + //!< Bluetooth 4.0 spec:
+ //!< 0: Use specific peer address
+ //!< 1: Use white list + uint8_t bDynamicWinOffset:1; //!< 1: Use dynamic WinOffset insertion + uint8_t deviceAddrType:1; //!< The type of the device address – public (0) or random (1) + uint8_t peerAddrType:1; //!< The type of the peer address – public (0) or random (1) + uint8_t bStrictLenFilter:1; //!< 1: Discard messages with illegal length + } initConfig; + uint8_t __dummy0; + uint8_t connectReqLen; //!< Size of connect request data + uint8_t* pConnectReqData; //!< Pointer to buffer containing LLData to go in the CONNECT_REQ + uint16_t* pDeviceAddress; //!< Pointer to device address used for this device + rfc_bleWhiteListEntry_t *pWhiteList; //!< Pointer to white list or peer address + ratmr_t connectTime; //!< \brief Indication of timer value of the first possible start time of the first connection event. + //!< Set to the calculated value if a connection is made and to the next possible connection + //!< time if not. + uint16_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } timeoutTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + ratmr_t timeoutTime; //!< \brief Time used together with timeoutTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_RXTIMEOUT + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_ENDED +}; + +//! @} + +//! \addtogroup bleGenericRxPar +//! @{ +//! Parameter structure for generic Rx (CMD_BLE_GENERIC_RX) + +struct __RFC_STRUCT rfc_bleGenericRxPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue. May be NULL; if so, received packets are not stored + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + uint8_t bRepeat; //!< \brief 0: End operation after receiving a packet
+ //!< 1: Restart receiver after receiving a packet + uint16_t __dummy0; + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Rx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< Rx operation +}; + +//! @} + +//! \addtogroup bleTxTestPar +//! @{ +//! Parameter structure for Tx test (CMD_BLE_TX_TEST) + +struct __RFC_STRUCT rfc_bleTxTestPar_s { + uint16_t numPackets; //!< \brief Number of packets to transmit
+ //!< 0: Transmit unlimited number of packets + uint8_t payloadLength; //!< The number of payload bytes in each packet. + uint8_t packetType; //!< \brief The packet type to be used, encoded according to the Bluetooth 4.0 spec, Volume 2, Part E, + //!< Section 7.8.29 + ratmr_t period; //!< Number of radio timer cycles between the start of each packet + struct { + uint8_t bOverrideDefault:1; //!< \brief 0: Use default packet encoding
+ //!< 1: Override packet contents + uint8_t bUsePrbs9:1; //!< \brief If bOverride is 1:
+ //!< 1: Use PRBS9 encoding of packet + uint8_t bUsePrbs15:1; //!< \brief If bOverride is 1:
+ //!< 1: Use PRBS15 encoding of packet + } config; + uint8_t byteVal; //!< If config.bOverride is 1, value of each byte to be sent + uint8_t __dummy0; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Test Tx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< Test Tx operation +}; + +//! @} + +//! \addtogroup bleMasterSlaveOutput +//! @{ +//! Output structure for master and slave (CMD_BLE_MASTER/CMD_BLE_SLAVE) + +struct __RFC_STRUCT rfc_bleMasterSlaveOutput_s { + uint8_t nTx; //!< \brief Total number of packets (including auto-empty and retransmissions) that have been + //!< transmitted + uint8_t nTxAck; //!< Total number of transmitted packets (including auto-empty) that have been ACK'ed + uint8_t nTxCtrl; //!< Number of unique LL control packets from the Tx queue that have been transmitted + uint8_t nTxCtrlAck; //!< Number of LL control packets from the Tx queue that have been finished (ACK'ed) + uint8_t nTxCtrlAckAck; //!< \brief Number of LL control packets that have been ACK'ed and where an ACK has been sent in + //!< response + uint8_t nTxRetrans; //!< Number of retransmissions that has been done + uint8_t nTxEntryDone; //!< Number of packets from the Tx queue that have been finished (ACK'ed) + uint8_t nRxOk; //!< Number of packets that have been received with payload, CRC OK and not ignored + uint8_t nRxCtrl; //!< Number of LL control packets that have been received with CRC OK and not ignored + uint8_t nRxCtrlAck; //!< \brief Number of LL control packets that have been received with CRC OK and not ignored, and + //!< then ACK'ed + uint8_t nRxNok; //!< Number of packets that have been received with CRC error + uint8_t nRxIgnored; //!< \brief Number of packets that have been received with CRC OK and ignored due to repeated + //!< sequence number + uint8_t nRxEmpty; //!< Number of packets that have been received with CRC OK and no payload + uint8_t nRxBufFull; //!< Number of packets that have been received and discarded due to lack of buffer space + int8_t lastRssi; //!< RSSI of last received packet + struct { + uint8_t bTimeStampValid:1; //!< 1 if a valid time stamp has been written to timeStamp; 0 otherwise + uint8_t bLastCrcErr:1; //!< 1 if the last received packet had CRC error; 0 otherwise + uint8_t bLastIgnored:1; //!< 1 if the last received packet with CRC OK was ignored; 0 otherwise + uint8_t bLastEmpty:1; //!< 1 if the last received packet with CRC OK was empty; 0 otherwise + uint8_t bLastCtrl:1; //!< 1 if the last received packet with CRC OK was empty; 0 otherwise + uint8_t bLastMd:1; //!< 1 if the last received packet with CRC OK had MD = 1; 0 otherwise + uint8_t bLastAck:1; //!< \brief 1 if the last received packet with CRC OK was an ACK of a transmitted packet; + //!< 0 otherwise + } pktStatus; + ratmr_t timeStamp; //!< Slave operation: Time stamp of first received packet +}; + +//! @} + +//! \addtogroup bleAdvOutput +//! @{ +//! Output structure for advertiser (CMD_BLE_ADV*) + +struct __RFC_STRUCT rfc_bleAdvOutput_s { + uint16_t nTxAdvInd; //!< Number of ADV*_IND packets completely transmitted + uint8_t nTxScanRsp; //!< Number of SCAN_RSP packets transmitted + uint8_t nRxScanReq; //!< Number of SCAN_REQ packets received OK and not ignored + uint8_t nRxConnectReq; //!< Number of CONNECT_REQ packets received OK and not ignored + uint8_t __dummy0; + uint16_t nRxNok; //!< Number of packets received with CRC error + uint16_t nRxIgnored; //!< Number of packets received with CRC OK, but ignored + uint8_t nRxBufFull; //!< Number of packets received that did not fit in Rx queue + int8_t lastRssi; //!< The RSSI of the last received packet + ratmr_t timeStamp; //!< Time stamp of the last received packet +}; + +//! @} + +//! \addtogroup bleScannerOutput +//! @{ +//! Output structure for scanner (CMD_BLE_SCANNER) + +struct __RFC_STRUCT rfc_bleScannerOutput_s { + uint16_t nTxScanReq; //!< Number of transmitted SCAN_REQ packets + uint16_t nBackedOffScanReq; //!< Number of SCAN_REQ packets not sent due to backoff procedure + uint16_t nRxAdvOk; //!< Number of ADV*_IND packets received with CRC OK and not ignored + uint16_t nRxAdvIgnored; //!< Number of ADV*_IND packets received with CRC OK, but ignored + uint16_t nRxAdvNok; //!< Number of ADV*_IND packets received with CRC error + uint16_t nRxScanRspOk; //!< Number of SCAN_RSP packets received with CRC OK and not ignored + uint16_t nRxScanRspIgnored; //!< Number of SCAN_RSP packets received with CRC OK, but ignored + uint16_t nRxScanRspNok; //!< Number of SCAN_RSP packets received with CRC error + uint8_t nRxAdvBufFull; //!< Number of ADV*_IND packets received that did not fit in Rx queue + uint8_t nRxScanRspBufFull; //!< Number of SCAN_RSP packets received that did not fit in Rx queue + int8_t lastRssi; //!< The RSSI of the last received packet + uint8_t __dummy0; + ratmr_t timeStamp; //!< Time stamp of the last successfully received ADV*_IND packet that was not ignored +}; + +//! @} + +//! \addtogroup bleInitiatorOutput +//! @{ +//! Output structure for initiator (CMD_BLE_INITIATOR) + +struct __RFC_STRUCT rfc_bleInitiatorOutput_s { + uint8_t nTxConnectReq; //!< Number of transmitted CONNECT_REQ packets + uint8_t nRxAdvOk; //!< Number of ADV*_IND packets received with CRC OK and not ignored + uint16_t nRxAdvIgnored; //!< Number of ADV*_IND packets received with CRC OK, but ignored + uint16_t nRxAdvNok; //!< Number of ADV*_IND packets received with CRC error + uint8_t nRxAdvBufFull; //!< Number of ADV*_IND packets received that did not fit in Rx queue + int8_t lastRssi; //!< The RSSI of the last received packet + ratmr_t timeStamp; //!< Time stamp of the received ADV*_IND packet that caused transmission of CONNECT_REQ +}; + +//! @} + +//! \addtogroup bleGenericRxOutput +//! @{ +//! Output structure for generic Rx (CMD_BLE_GENERIC_RX) + +struct __RFC_STRUCT rfc_bleGenericRxOutput_s { + uint16_t nRxOk; //!< Number of packets received with CRC OK + uint16_t nRxNok; //!< Number of packets received with CRC error + uint16_t nRxBufFull; //!< Number of packets that have been received and discarded due to lack of buffer space + int8_t lastRssi; //!< The RSSI of the last received packet + uint8_t __dummy0; + ratmr_t timeStamp; //!< Time stamp of the last received packet +}; + +//! @} + +//! \addtogroup bleTxTestOutput +//! @{ +//! Output structure for Tx test (CMD_BLE_TX_TEST) + +struct __RFC_STRUCT rfc_bleTxTestOutput_s { + uint16_t nTx; //!< Number of packets transmitted +}; + +//! @} + +//! \addtogroup bleWhiteListEntry +//! @{ +//! White list entry structure + +struct __RFC_STRUCT rfc_bleWhiteListEntry_s { + uint8_t size; //!< Number of while list entries. Used in the first entry of the list only + struct { + uint8_t bEnable:1; //!< 1 if the entry is in use, 0 if the entry is not in use + uint8_t addrType:1; //!< The type address in the entry – public (0) or random (1) + uint8_t bWlIgn:1; //!< \brief 1 if the entry is to be ignored by a scanner, 0 otherwise. Used to mask out + //!< entries that have already been scanned and reported. + } conf; + uint16_t address; //!< Least significant 16 bits of the address contained in the entry + uint32_t addressHi; //!< Most significant 32 bits of the address contained in the entry +}; + +//! @} + +//! \addtogroup bleRxStatus +//! @{ +//! Receive status byte that may be appended to message in receive buffer + +struct __RFC_STRUCT rfc_bleRxStatus_s { + struct { + uint8_t channel:6; //!< \brief The channel on which the packet was received, provided channel is in the range + //!< 0–39; otherwise 0x3F + uint8_t bIgnore:1; //!< 1 if the packet is marked as ignored, 0 otherwise + uint8_t bCrcErr:1; //!< 1 if the packet was received with CRC error, 0 otherwise + } status; +}; + +//! @} + +//! @} +//! @} +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ble_cmd_field.h b/cpu/cc26xx/dev/rfc-api/ble_cmd_field.h new file mode 100755 index 000000000..307e67dc6 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ble_cmd_field.h @@ -0,0 +1,623 @@ +/****************************************************************************** +* Filename: ble_cmd_field.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for Bluetooth Low Energy commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef __BLE_CMD_FIELD_H +#define __BLE_CMD_FIELD_H + +#include +#include "mailbox.h" +#include "common_cmd.h" + +#define _POSITION_bleRadioOp_channel 14 +#define _TYPE_bleRadioOp_channel uint8_t +#define _POSITION_bleRadioOp_whitening 15 +#define _TYPE_bleRadioOp_whitening uint8_t +#define _BITPOS_bleRadioOp_whitening_init 0 +#define _NBITS_bleRadioOp_whitening_init 7 +#define _BITPOS_bleRadioOp_whitening_bOverride 7 +#define _NBITS_bleRadioOp_whitening_bOverride 1 +#define _POSITION_bleRadioOp_pParams 16 +#define _TYPE_bleRadioOp_pParams uint8_t* +#define _POSITION_bleRadioOp_pOutput 20 +#define _TYPE_bleRadioOp_pOutput uint8_t* +#define _SIZEOF_bleRadioOp 24 + +#define _SIZEOF_CMD_BLE_SLAVE 24 + +#define _SIZEOF_CMD_BLE_MASTER 24 + +#define _SIZEOF_CMD_BLE_ADV 24 + +#define _SIZEOF_CMD_BLE_ADV_DIR 24 + +#define _SIZEOF_CMD_BLE_ADV_NC 24 + +#define _SIZEOF_CMD_BLE_ADV_SCAN 24 + +#define _SIZEOF_CMD_BLE_SCANNER 24 + +#define _SIZEOF_CMD_BLE_INITIATOR 24 + +#define _SIZEOF_CMD_BLE_GENERIC_RX 24 + +#define _SIZEOF_CMD_BLE_TX_TEST 24 + +#define _POSITION_CMD_BLE_ADV_PAYLOAD_payloadType 2 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_payloadType uint8_t +#define _POSITION_CMD_BLE_ADV_PAYLOAD_newLen 3 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_newLen uint8_t +#define _POSITION_CMD_BLE_ADV_PAYLOAD_pNewData 4 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_pNewData uint8_t* +#define _POSITION_CMD_BLE_ADV_PAYLOAD_pParams 8 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_pParams uint8_t* +#define _SIZEOF_CMD_BLE_ADV_PAYLOAD 12 + +#define _POSITION_bleMasterSlavePar_pRxQ 0 +#define _TYPE_bleMasterSlavePar_pRxQ dataQueue_t* +#define _POSITION_bleMasterSlavePar_pTxQ 4 +#define _TYPE_bleMasterSlavePar_pTxQ dataQueue_t* +#define _POSITION_bleMasterSlavePar_rxConfig 8 +#define _TYPE_bleMasterSlavePar_rxConfig uint8_t +#define _BITPOS_bleMasterSlavePar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleMasterSlavePar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleMasterSlavePar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleMasterSlavePar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleMasterSlavePar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleMasterSlavePar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAppendRssi 5 +#define _NBITS_bleMasterSlavePar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAppendStatus 6 +#define _NBITS_bleMasterSlavePar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleMasterSlavePar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleMasterSlavePar_seqStat 9 +#define _TYPE_bleMasterSlavePar_seqStat uint8_t +#define _BITPOS_bleMasterSlavePar_seqStat_lastRxSn 0 +#define _NBITS_bleMasterSlavePar_seqStat_lastRxSn 1 +#define _BITPOS_bleMasterSlavePar_seqStat_lastTxSn 1 +#define _NBITS_bleMasterSlavePar_seqStat_lastTxSn 1 +#define _BITPOS_bleMasterSlavePar_seqStat_nextTxSn 2 +#define _NBITS_bleMasterSlavePar_seqStat_nextTxSn 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bFirstPkt 3 +#define _NBITS_bleMasterSlavePar_seqStat_bFirstPkt 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bAutoEmpty 4 +#define _NBITS_bleMasterSlavePar_seqStat_bAutoEmpty 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bLlCtrlTx 5 +#define _NBITS_bleMasterSlavePar_seqStat_bLlCtrlTx 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bLlCtrlAckRx 6 +#define _NBITS_bleMasterSlavePar_seqStat_bLlCtrlAckRx 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bLlCtrlAckPending 7 +#define _NBITS_bleMasterSlavePar_seqStat_bLlCtrlAckPending 1 +#define _POSITION_bleMasterSlavePar_maxNack 10 +#define _TYPE_bleMasterSlavePar_maxNack uint8_t +#define _POSITION_bleMasterSlavePar_maxPkt 11 +#define _TYPE_bleMasterSlavePar_maxPkt uint8_t +#define _POSITION_bleMasterSlavePar_accessAddress 12 +#define _TYPE_bleMasterSlavePar_accessAddress uint32_t +#define _POSITION_bleMasterSlavePar_crcInit0 16 +#define _TYPE_bleMasterSlavePar_crcInit0 uint8_t +#define _POSITION_bleMasterSlavePar_crcInit1 17 +#define _TYPE_bleMasterSlavePar_crcInit1 uint8_t +#define _POSITION_bleMasterSlavePar_crcInit2 18 +#define _TYPE_bleMasterSlavePar_crcInit2 uint8_t +#define _POSITION_bleMasterSlavePar_crcInit 16 +#define _TYPE_bleMasterSlavePar_crcInit uint32_t +#define _SIZEOF_bleMasterSlavePar 20 + +#define _POSITION_bleMasterPar_endTrigger 19 +#define _TYPE_bleMasterPar_endTrigger uint8_t +#define _BITPOS_bleMasterPar_endTrigger_triggerType 0 +#define _NBITS_bleMasterPar_endTrigger_triggerType 4 +#define _BITPOS_bleMasterPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleMasterPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleMasterPar_endTrigger_triggerNo 5 +#define _NBITS_bleMasterPar_endTrigger_triggerNo 2 +#define _BITPOS_bleMasterPar_endTrigger_pastTrig 7 +#define _NBITS_bleMasterPar_endTrigger_pastTrig 1 +#define _POSITION_bleMasterPar_endTime 20 +#define _TYPE_bleMasterPar_endTime ratmr_t +#define _SIZEOF_bleMasterPar 24 + +#define _POSITION_bleSlavePar_timeoutTrigger 19 +#define _TYPE_bleSlavePar_timeoutTrigger uint8_t +#define _BITPOS_bleSlavePar_timeoutTrigger_triggerType 0 +#define _NBITS_bleSlavePar_timeoutTrigger_triggerType 4 +#define _BITPOS_bleSlavePar_timeoutTrigger_bEnaCmd 4 +#define _NBITS_bleSlavePar_timeoutTrigger_bEnaCmd 1 +#define _BITPOS_bleSlavePar_timeoutTrigger_triggerNo 5 +#define _NBITS_bleSlavePar_timeoutTrigger_triggerNo 2 +#define _BITPOS_bleSlavePar_timeoutTrigger_pastTrig 7 +#define _NBITS_bleSlavePar_timeoutTrigger_pastTrig 1 +#define _POSITION_bleSlavePar_timeoutTime 20 +#define _TYPE_bleSlavePar_timeoutTime ratmr_t +#define _POSITION_bleSlavePar_endTrigger 27 +#define _TYPE_bleSlavePar_endTrigger uint8_t +#define _BITPOS_bleSlavePar_endTrigger_triggerType 0 +#define _NBITS_bleSlavePar_endTrigger_triggerType 4 +#define _BITPOS_bleSlavePar_endTrigger_bEnaCmd 4 +#define _NBITS_bleSlavePar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleSlavePar_endTrigger_triggerNo 5 +#define _NBITS_bleSlavePar_endTrigger_triggerNo 2 +#define _BITPOS_bleSlavePar_endTrigger_pastTrig 7 +#define _NBITS_bleSlavePar_endTrigger_pastTrig 1 +#define _POSITION_bleSlavePar_endTime 28 +#define _TYPE_bleSlavePar_endTime ratmr_t +#define _SIZEOF_bleSlavePar 32 + +#define _POSITION_bleAdvPar_pRxQ 0 +#define _TYPE_bleAdvPar_pRxQ dataQueue_t* +#define _POSITION_bleAdvPar_rxConfig 4 +#define _TYPE_bleAdvPar_rxConfig uint8_t +#define _BITPOS_bleAdvPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleAdvPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleAdvPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleAdvPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleAdvPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleAdvPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleAdvPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleAdvPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleAdvPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleAdvPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleAdvPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleAdvPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleAdvPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleAdvPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleAdvPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleAdvPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleAdvPar_advConfig 5 +#define _TYPE_bleAdvPar_advConfig uint8_t +#define _BITPOS_bleAdvPar_advConfig_advFilterPolicy 0 +#define _NBITS_bleAdvPar_advConfig_advFilterPolicy 2 +#define _BITPOS_bleAdvPar_advConfig_deviceAddrType 2 +#define _NBITS_bleAdvPar_advConfig_deviceAddrType 1 +#define _BITPOS_bleAdvPar_advConfig_peerAddrType 3 +#define _NBITS_bleAdvPar_advConfig_peerAddrType 1 +#define _BITPOS_bleAdvPar_advConfig_bStrictLenFilter 4 +#define _NBITS_bleAdvPar_advConfig_bStrictLenFilter 1 +#define _POSITION_bleAdvPar_advLen 6 +#define _TYPE_bleAdvPar_advLen uint8_t +#define _POSITION_bleAdvPar_scanRspLen 7 +#define _TYPE_bleAdvPar_scanRspLen uint8_t +#define _POSITION_bleAdvPar_pAdvData 8 +#define _TYPE_bleAdvPar_pAdvData uint8_t* +#define _POSITION_bleAdvPar_pScanRspData 12 +#define _TYPE_bleAdvPar_pScanRspData uint8_t* +#define _POSITION_bleAdvPar_pDeviceAddress 16 +#define _TYPE_bleAdvPar_pDeviceAddress uint16_t* +#define _POSITION_bleAdvPar_pWhiteList 20 +#define _TYPE_bleAdvPar_pWhiteList uint32_t* +#define _POSITION_bleAdvPar_endTrigger 27 +#define _TYPE_bleAdvPar_endTrigger uint8_t +#define _BITPOS_bleAdvPar_endTrigger_triggerType 0 +#define _NBITS_bleAdvPar_endTrigger_triggerType 4 +#define _BITPOS_bleAdvPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleAdvPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleAdvPar_endTrigger_triggerNo 5 +#define _NBITS_bleAdvPar_endTrigger_triggerNo 2 +#define _BITPOS_bleAdvPar_endTrigger_pastTrig 7 +#define _NBITS_bleAdvPar_endTrigger_pastTrig 1 +#define _POSITION_bleAdvPar_endTime 28 +#define _TYPE_bleAdvPar_endTime ratmr_t +#define _SIZEOF_bleAdvPar 32 + +#define _POSITION_bleScannerPar_pRxQ 0 +#define _TYPE_bleScannerPar_pRxQ dataQueue_t* +#define _POSITION_bleScannerPar_rxConfig 4 +#define _TYPE_bleScannerPar_rxConfig uint8_t +#define _BITPOS_bleScannerPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleScannerPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleScannerPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleScannerPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleScannerPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleScannerPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleScannerPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleScannerPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleScannerPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleScannerPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleScannerPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleScannerPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleScannerPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleScannerPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleScannerPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleScannerPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleScannerPar_scanConfig 5 +#define _TYPE_bleScannerPar_scanConfig uint8_t +#define _BITPOS_bleScannerPar_scanConfig_scanFilterPolicy 0 +#define _NBITS_bleScannerPar_scanConfig_scanFilterPolicy 1 +#define _BITPOS_bleScannerPar_scanConfig_bActiveScan 1 +#define _NBITS_bleScannerPar_scanConfig_bActiveScan 1 +#define _BITPOS_bleScannerPar_scanConfig_deviceAddrType 2 +#define _NBITS_bleScannerPar_scanConfig_deviceAddrType 1 +#define _BITPOS_bleScannerPar_scanConfig_bStrictLenFilter 4 +#define _NBITS_bleScannerPar_scanConfig_bStrictLenFilter 1 +#define _BITPOS_bleScannerPar_scanConfig_bAutoWlIgnore 5 +#define _NBITS_bleScannerPar_scanConfig_bAutoWlIgnore 1 +#define _BITPOS_bleScannerPar_scanConfig_bEndOnRpt 6 +#define _NBITS_bleScannerPar_scanConfig_bEndOnRpt 1 +#define _POSITION_bleScannerPar_randomState 6 +#define _TYPE_bleScannerPar_randomState uint16_t +#define _POSITION_bleScannerPar_backoffCount 8 +#define _TYPE_bleScannerPar_backoffCount uint16_t +#define _POSITION_bleScannerPar_backoffPar 10 +#define _TYPE_bleScannerPar_backoffPar uint8_t +#define _BITPOS_bleScannerPar_backoffPar_logUpperLimit 0 +#define _NBITS_bleScannerPar_backoffPar_logUpperLimit 4 +#define _BITPOS_bleScannerPar_backoffPar_bLastSucceeded 4 +#define _NBITS_bleScannerPar_backoffPar_bLastSucceeded 1 +#define _BITPOS_bleScannerPar_backoffPar_bLastFailed 5 +#define _NBITS_bleScannerPar_backoffPar_bLastFailed 1 +#define _POSITION_bleScannerPar_scanReqLen 11 +#define _TYPE_bleScannerPar_scanReqLen uint8_t +#define _POSITION_bleScannerPar_pScanReqData 12 +#define _TYPE_bleScannerPar_pScanReqData uint8_t* +#define _POSITION_bleScannerPar_pDeviceAddress 16 +#define _TYPE_bleScannerPar_pDeviceAddress uint16_t* +#define _POSITION_bleScannerPar_pWhiteList 20 +#define _TYPE_bleScannerPar_pWhiteList uint32_t* +#define _POSITION_bleScannerPar_timeoutTrigger 26 +#define _TYPE_bleScannerPar_timeoutTrigger uint8_t +#define _BITPOS_bleScannerPar_timeoutTrigger_triggerType 0 +#define _NBITS_bleScannerPar_timeoutTrigger_triggerType 4 +#define _BITPOS_bleScannerPar_timeoutTrigger_bEnaCmd 4 +#define _NBITS_bleScannerPar_timeoutTrigger_bEnaCmd 1 +#define _BITPOS_bleScannerPar_timeoutTrigger_triggerNo 5 +#define _NBITS_bleScannerPar_timeoutTrigger_triggerNo 2 +#define _BITPOS_bleScannerPar_timeoutTrigger_pastTrig 7 +#define _NBITS_bleScannerPar_timeoutTrigger_pastTrig 1 +#define _POSITION_bleScannerPar_endTrigger 27 +#define _TYPE_bleScannerPar_endTrigger uint8_t +#define _BITPOS_bleScannerPar_endTrigger_triggerType 0 +#define _NBITS_bleScannerPar_endTrigger_triggerType 4 +#define _BITPOS_bleScannerPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleScannerPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleScannerPar_endTrigger_triggerNo 5 +#define _NBITS_bleScannerPar_endTrigger_triggerNo 2 +#define _BITPOS_bleScannerPar_endTrigger_pastTrig 7 +#define _NBITS_bleScannerPar_endTrigger_pastTrig 1 +#define _POSITION_bleScannerPar_timeoutTime 28 +#define _TYPE_bleScannerPar_timeoutTime ratmr_t +#define _POSITION_bleScannerPar_endTime 32 +#define _TYPE_bleScannerPar_endTime ratmr_t +#define _SIZEOF_bleScannerPar 36 + +#define _POSITION_bleInitiatorPar_pRxQ 0 +#define _TYPE_bleInitiatorPar_pRxQ dataQueue_t* +#define _POSITION_bleInitiatorPar_rxConfig 4 +#define _TYPE_bleInitiatorPar_rxConfig uint8_t +#define _BITPOS_bleInitiatorPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleInitiatorPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleInitiatorPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleInitiatorPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleInitiatorPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleInitiatorPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleInitiatorPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleInitiatorPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleInitiatorPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleInitiatorPar_initConfig 5 +#define _TYPE_bleInitiatorPar_initConfig uint8_t +#define _BITPOS_bleInitiatorPar_initConfig_bUseWhiteList 0 +#define _NBITS_bleInitiatorPar_initConfig_bUseWhiteList 1 +#define _BITPOS_bleInitiatorPar_initConfig_bDynamicWinOffset 1 +#define _NBITS_bleInitiatorPar_initConfig_bDynamicWinOffset 1 +#define _BITPOS_bleInitiatorPar_initConfig_deviceAddrType 2 +#define _NBITS_bleInitiatorPar_initConfig_deviceAddrType 1 +#define _BITPOS_bleInitiatorPar_initConfig_peerAddrType 3 +#define _NBITS_bleInitiatorPar_initConfig_peerAddrType 1 +#define _BITPOS_bleInitiatorPar_initConfig_bStrictLenFilter 4 +#define _NBITS_bleInitiatorPar_initConfig_bStrictLenFilter 1 +#define _POSITION_bleInitiatorPar_connectReqLen 7 +#define _TYPE_bleInitiatorPar_connectReqLen uint8_t +#define _POSITION_bleInitiatorPar_pConnectReqData 8 +#define _TYPE_bleInitiatorPar_pConnectReqData uint8_t* +#define _POSITION_bleInitiatorPar_pDeviceAddress 12 +#define _TYPE_bleInitiatorPar_pDeviceAddress uint16_t* +#define _POSITION_bleInitiatorPar_pWhiteList 16 +#define _TYPE_bleInitiatorPar_pWhiteList uint32_t* +#define _POSITION_bleInitiatorPar_connectTime 20 +#define _TYPE_bleInitiatorPar_connectTime ratmr_t +#define _POSITION_bleInitiatorPar_timeoutTrigger 26 +#define _TYPE_bleInitiatorPar_timeoutTrigger uint8_t +#define _BITPOS_bleInitiatorPar_timeoutTrigger_triggerType 0 +#define _NBITS_bleInitiatorPar_timeoutTrigger_triggerType 4 +#define _BITPOS_bleInitiatorPar_timeoutTrigger_bEnaCmd 4 +#define _NBITS_bleInitiatorPar_timeoutTrigger_bEnaCmd 1 +#define _BITPOS_bleInitiatorPar_timeoutTrigger_triggerNo 5 +#define _NBITS_bleInitiatorPar_timeoutTrigger_triggerNo 2 +#define _BITPOS_bleInitiatorPar_timeoutTrigger_pastTrig 7 +#define _NBITS_bleInitiatorPar_timeoutTrigger_pastTrig 1 +#define _POSITION_bleInitiatorPar_endTrigger 27 +#define _TYPE_bleInitiatorPar_endTrigger uint8_t +#define _BITPOS_bleInitiatorPar_endTrigger_triggerType 0 +#define _NBITS_bleInitiatorPar_endTrigger_triggerType 4 +#define _BITPOS_bleInitiatorPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleInitiatorPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleInitiatorPar_endTrigger_triggerNo 5 +#define _NBITS_bleInitiatorPar_endTrigger_triggerNo 2 +#define _BITPOS_bleInitiatorPar_endTrigger_pastTrig 7 +#define _NBITS_bleInitiatorPar_endTrigger_pastTrig 1 +#define _POSITION_bleInitiatorPar_timeoutTime 28 +#define _TYPE_bleInitiatorPar_timeoutTime ratmr_t +#define _POSITION_bleInitiatorPar_endTime 32 +#define _TYPE_bleInitiatorPar_endTime ratmr_t +#define _SIZEOF_bleInitiatorPar 36 + +#define _POSITION_bleGenericRxPar_pRxQ 0 +#define _TYPE_bleGenericRxPar_pRxQ dataQueue_t* +#define _POSITION_bleGenericRxPar_rxConfig 4 +#define _TYPE_bleGenericRxPar_rxConfig uint8_t +#define _BITPOS_bleGenericRxPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleGenericRxPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleGenericRxPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleGenericRxPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleGenericRxPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleGenericRxPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleGenericRxPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleGenericRxPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleGenericRxPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleGenericRxPar_bRepeat 5 +#define _TYPE_bleGenericRxPar_bRepeat uint8_t +#define _POSITION_bleGenericRxPar_accessAddress 8 +#define _TYPE_bleGenericRxPar_accessAddress uint32_t +#define _POSITION_bleGenericRxPar_crcInit0 12 +#define _TYPE_bleGenericRxPar_crcInit0 uint8_t +#define _POSITION_bleGenericRxPar_crcInit1 13 +#define _TYPE_bleGenericRxPar_crcInit1 uint8_t +#define _POSITION_bleGenericRxPar_crcInit2 14 +#define _TYPE_bleGenericRxPar_crcInit2 uint8_t +#define _POSITION_bleGenericRxPar_crcInit 12 +#define _TYPE_bleGenericRxPar_crcInit uint32_t +#define _POSITION_bleGenericRxPar_endTrigger 15 +#define _TYPE_bleGenericRxPar_endTrigger uint8_t +#define _BITPOS_bleGenericRxPar_endTrigger_triggerType 0 +#define _NBITS_bleGenericRxPar_endTrigger_triggerType 4 +#define _BITPOS_bleGenericRxPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleGenericRxPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleGenericRxPar_endTrigger_triggerNo 5 +#define _NBITS_bleGenericRxPar_endTrigger_triggerNo 2 +#define _BITPOS_bleGenericRxPar_endTrigger_pastTrig 7 +#define _NBITS_bleGenericRxPar_endTrigger_pastTrig 1 +#define _POSITION_bleGenericRxPar_endTime 16 +#define _TYPE_bleGenericRxPar_endTime ratmr_t +#define _SIZEOF_bleGenericRxPar 20 + +#define _POSITION_bleTxTestPar_numPackets 0 +#define _TYPE_bleTxTestPar_numPackets uint16_t +#define _POSITION_bleTxTestPar_payloadLength 2 +#define _TYPE_bleTxTestPar_payloadLength uint8_t +#define _POSITION_bleTxTestPar_packetType 3 +#define _TYPE_bleTxTestPar_packetType uint8_t +#define _POSITION_bleTxTestPar_period 4 +#define _TYPE_bleTxTestPar_period ratmr_t +#define _POSITION_bleTxTestPar_config 8 +#define _TYPE_bleTxTestPar_config uint8_t +#define _BITPOS_bleTxTestPar_config_bOverrideDefault 0 +#define _NBITS_bleTxTestPar_config_bOverrideDefault 1 +#define _BITPOS_bleTxTestPar_config_bUsePrbs9 1 +#define _NBITS_bleTxTestPar_config_bUsePrbs9 1 +#define _BITPOS_bleTxTestPar_config_bUsePrbs15 2 +#define _NBITS_bleTxTestPar_config_bUsePrbs15 1 +#define _POSITION_bleTxTestPar_byteVal 9 +#define _TYPE_bleTxTestPar_byteVal uint8_t +#define _POSITION_bleTxTestPar_endTrigger 11 +#define _TYPE_bleTxTestPar_endTrigger uint8_t +#define _BITPOS_bleTxTestPar_endTrigger_triggerType 0 +#define _NBITS_bleTxTestPar_endTrigger_triggerType 4 +#define _BITPOS_bleTxTestPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleTxTestPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleTxTestPar_endTrigger_triggerNo 5 +#define _NBITS_bleTxTestPar_endTrigger_triggerNo 2 +#define _BITPOS_bleTxTestPar_endTrigger_pastTrig 7 +#define _NBITS_bleTxTestPar_endTrigger_pastTrig 1 +#define _POSITION_bleTxTestPar_endTime 12 +#define _TYPE_bleTxTestPar_endTime ratmr_t +#define _SIZEOF_bleTxTestPar 16 + +#define _POSITION_bleMasterSlaveOutput_nTx 0 +#define _TYPE_bleMasterSlaveOutput_nTx uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxAck 1 +#define _TYPE_bleMasterSlaveOutput_nTxAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxCtrl 2 +#define _TYPE_bleMasterSlaveOutput_nTxCtrl uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxCtrlAck 3 +#define _TYPE_bleMasterSlaveOutput_nTxCtrlAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxCtrlAckAck 4 +#define _TYPE_bleMasterSlaveOutput_nTxCtrlAckAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxRetrans 5 +#define _TYPE_bleMasterSlaveOutput_nTxRetrans uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxEntryDone 6 +#define _TYPE_bleMasterSlaveOutput_nTxEntryDone uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxOk 7 +#define _TYPE_bleMasterSlaveOutput_nRxOk uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxCtrl 8 +#define _TYPE_bleMasterSlaveOutput_nRxCtrl uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxCtrlAck 9 +#define _TYPE_bleMasterSlaveOutput_nRxCtrlAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxNok 10 +#define _TYPE_bleMasterSlaveOutput_nRxNok uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxIgnored 11 +#define _TYPE_bleMasterSlaveOutput_nRxIgnored uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxEmpty 12 +#define _TYPE_bleMasterSlaveOutput_nRxEmpty uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxBufFull 13 +#define _TYPE_bleMasterSlaveOutput_nRxBufFull uint8_t +#define _POSITION_bleMasterSlaveOutput_lastRssi 14 +#define _TYPE_bleMasterSlaveOutput_lastRssi int8_t +#define _POSITION_bleMasterSlaveOutput_pktStatus 15 +#define _TYPE_bleMasterSlaveOutput_pktStatus uint8_t +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bTimeStampValid 0 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bTimeStampValid 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastCrcErr 1 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastCrcErr 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastIgnored 2 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastIgnored 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastEmpty 3 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastEmpty 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastCtrl 4 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastCtrl 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastMd 5 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastMd 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastAck 6 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastAck 1 +#define _POSITION_bleMasterSlaveOutput_timeStamp 16 +#define _TYPE_bleMasterSlaveOutput_timeStamp ratmr_t +#define _SIZEOF_bleMasterSlaveOutput 20 + +#define _POSITION_bleAdvOutput_nTxAdvInd 0 +#define _TYPE_bleAdvOutput_nTxAdvInd uint16_t +#define _POSITION_bleAdvOutput_nTxScanRsp 2 +#define _TYPE_bleAdvOutput_nTxScanRsp uint8_t +#define _POSITION_bleAdvOutput_nRxScanReq 3 +#define _TYPE_bleAdvOutput_nRxScanReq uint8_t +#define _POSITION_bleAdvOutput_nRxConnectReq 4 +#define _TYPE_bleAdvOutput_nRxConnectReq uint8_t +#define _POSITION_bleAdvOutput_nRxNok 6 +#define _TYPE_bleAdvOutput_nRxNok uint16_t +#define _POSITION_bleAdvOutput_nRxIgnored 8 +#define _TYPE_bleAdvOutput_nRxIgnored uint16_t +#define _POSITION_bleAdvOutput_nRxBufFull 10 +#define _TYPE_bleAdvOutput_nRxBufFull uint8_t +#define _POSITION_bleAdvOutput_lastRssi 11 +#define _TYPE_bleAdvOutput_lastRssi int8_t +#define _POSITION_bleAdvOutput_timeStamp 12 +#define _TYPE_bleAdvOutput_timeStamp ratmr_t +#define _SIZEOF_bleAdvOutput 16 + +#define _POSITION_bleScannerOutput_nTxScanReq 0 +#define _TYPE_bleScannerOutput_nTxScanReq uint16_t +#define _POSITION_bleScannerOutput_nBackedOffScanReq 2 +#define _TYPE_bleScannerOutput_nBackedOffScanReq uint16_t +#define _POSITION_bleScannerOutput_nRxAdvOk 4 +#define _TYPE_bleScannerOutput_nRxAdvOk uint16_t +#define _POSITION_bleScannerOutput_nRxAdvIgnored 6 +#define _TYPE_bleScannerOutput_nRxAdvIgnored uint16_t +#define _POSITION_bleScannerOutput_nRxAdvNok 8 +#define _TYPE_bleScannerOutput_nRxAdvNok uint16_t +#define _POSITION_bleScannerOutput_nRxScanRspOk 10 +#define _TYPE_bleScannerOutput_nRxScanRspOk uint16_t +#define _POSITION_bleScannerOutput_nRxScanRspIgnored 12 +#define _TYPE_bleScannerOutput_nRxScanRspIgnored uint16_t +#define _POSITION_bleScannerOutput_nRxScanRspNok 14 +#define _TYPE_bleScannerOutput_nRxScanRspNok uint16_t +#define _POSITION_bleScannerOutput_nRxAdvBufFull 16 +#define _TYPE_bleScannerOutput_nRxAdvBufFull uint8_t +#define _POSITION_bleScannerOutput_nRxScanRspBufFull 17 +#define _TYPE_bleScannerOutput_nRxScanRspBufFull uint8_t +#define _POSITION_bleScannerOutput_lastRssi 18 +#define _TYPE_bleScannerOutput_lastRssi int8_t +#define _POSITION_bleScannerOutput_timeStamp 20 +#define _TYPE_bleScannerOutput_timeStamp ratmr_t +#define _SIZEOF_bleScannerOutput 24 + +#define _POSITION_bleInitiatorOutput_nTxConnectReq 0 +#define _TYPE_bleInitiatorOutput_nTxConnectReq uint8_t +#define _POSITION_bleInitiatorOutput_nRxAdvOk 1 +#define _TYPE_bleInitiatorOutput_nRxAdvOk uint8_t +#define _POSITION_bleInitiatorOutput_nRxAdvIgnored 2 +#define _TYPE_bleInitiatorOutput_nRxAdvIgnored uint16_t +#define _POSITION_bleInitiatorOutput_nRxAdvNok 4 +#define _TYPE_bleInitiatorOutput_nRxAdvNok uint16_t +#define _POSITION_bleInitiatorOutput_nRxAdvBufFull 6 +#define _TYPE_bleInitiatorOutput_nRxAdvBufFull uint8_t +#define _POSITION_bleInitiatorOutput_lastRssi 7 +#define _TYPE_bleInitiatorOutput_lastRssi int8_t +#define _POSITION_bleInitiatorOutput_timeStamp 8 +#define _TYPE_bleInitiatorOutput_timeStamp ratmr_t +#define _SIZEOF_bleInitiatorOutput 12 + +#define _POSITION_bleGenericRxOutput_nRxOk 0 +#define _TYPE_bleGenericRxOutput_nRxOk uint16_t +#define _POSITION_bleGenericRxOutput_nRxNok 2 +#define _TYPE_bleGenericRxOutput_nRxNok uint16_t +#define _POSITION_bleGenericRxOutput_nRxBufFull 4 +#define _TYPE_bleGenericRxOutput_nRxBufFull uint16_t +#define _POSITION_bleGenericRxOutput_lastRssi 6 +#define _TYPE_bleGenericRxOutput_lastRssi int8_t +#define _POSITION_bleGenericRxOutput_timeStamp 8 +#define _TYPE_bleGenericRxOutput_timeStamp ratmr_t +#define _SIZEOF_bleGenericRxOutput 12 + +#define _POSITION_bleTxTestOutput_nTx 0 +#define _TYPE_bleTxTestOutput_nTx uint16_t +#define _SIZEOF_bleTxTestOutput 2 + +#define _POSITION_bleWhiteListEntry_size 0 +#define _TYPE_bleWhiteListEntry_size uint8_t +#define _POSITION_bleWhiteListEntry_conf 1 +#define _TYPE_bleWhiteListEntry_conf uint8_t +#define _BITPOS_bleWhiteListEntry_conf_bEnable 0 +#define _NBITS_bleWhiteListEntry_conf_bEnable 1 +#define _BITPOS_bleWhiteListEntry_conf_addrType 1 +#define _NBITS_bleWhiteListEntry_conf_addrType 1 +#define _BITPOS_bleWhiteListEntry_conf_bWlIgn 2 +#define _NBITS_bleWhiteListEntry_conf_bWlIgn 1 +#define _POSITION_bleWhiteListEntry_address 2 +#define _TYPE_bleWhiteListEntry_address uint16_t +#define _POSITION_bleWhiteListEntry_addressHi 4 +#define _TYPE_bleWhiteListEntry_addressHi uint32_t +#define _SIZEOF_bleWhiteListEntry 8 + +#define _POSITION_bleRxStatus_status 0 +#define _TYPE_bleRxStatus_status uint8_t +#define _BITPOS_bleRxStatus_status_channel 0 +#define _NBITS_bleRxStatus_status_channel 6 +#define _BITPOS_bleRxStatus_status_bIgnore 6 +#define _NBITS_bleRxStatus_status_bIgnore 1 +#define _BITPOS_bleRxStatus_status_bCrcErr 7 +#define _NBITS_bleRxStatus_status_bCrcErr 1 +#define _SIZEOF_bleRxStatus 1 + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ble_mailbox.h b/cpu/cc26xx/dev/rfc-api/ble_mailbox.h new file mode 100644 index 000000000..607a92f5d --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ble_mailbox.h @@ -0,0 +1,119 @@ +/****************************************************************************** +* Filename: ble_mailbox.h +* Revised: $ $ +* Revision: $ $ +* +* Description: Definitions for BLE interface +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef _BLE_MAILBOX_H +#define _BLE_MAILBOX_H + +#include "mailbox.h" + +/// \name CPE interrupt definitions for BLE +/// Interrupt masks for the CPE interrupt in RDBELL. These are new names for interrupts in mailbox.h, +/// used for compartibility with previous versions with separate interrupt numbers. +///@{ +#define IRQN_BLE_TX_DONE IRQN_TX_DONE +#define IRQN_BLE_TX_ACK IRQN_TX_ACK +#define IRQN_BLE_TX_CTRL IRQN_TX_CTRL +#define IRQN_BLE_TX_CTRL_ACK IRQN_TX_CTRL_ACK +#define IRQN_BLE_TX_CTRL_ACK_ACK IRQN_TX_CTRL_ACK_ACK +#define IRQN_BLE_TX_RETRANS IRQN_TX_RETRANS +#define IRQN_BLE_TX_ENTRY_DONE IRQN_TX_ENTRY_DONE +#define IRQN_BLE_TX_BUFFER_CHANGED IRQN_TX_BUFFER_CHANGED +#define IRQN_BLE_RX_OK IRQN_RX_OK +#define IRQN_BLE_RX_NOK IRQN_RX_NOK +#define IRQN_BLE_RX_IGNORED IRQN_RX_IGNORED +#define IRQN_BLE_RX_EMPTY IRQN_RX_EMPTY +#define IRQN_BLE_RX_CTRL IRQN_RX_CTRL +#define IRQN_BLE_RX_CTRL_ACK IRQN_RX_CTRL_ACK +#define IRQN_BLE_RX_BUF_FULL IRQN_RX_BUF_FULL +#define IRQN_BLE_RX_ENTRY_DONE IRQN_RX_ENTRY_DONE + +#define IRQ_BLE_TX_DONE (1U << IRQN_BLE_TX_DONE) +#define IRQ_BLE_TX_ACK (1U << IRQN_BLE_TX_ACK) +#define IRQ_BLE_TX_CTRL (1U << IRQN_BLE_TX_CTRL) +#define IRQ_BLE_TX_CTRL_ACK (1U << IRQN_BLE_TX_CTRL_ACK) +#define IRQ_BLE_TX_CTRL_ACK_ACK (1U << IRQN_BLE_TX_CTRL_ACK_ACK) +#define IRQ_BLE_TX_RETRANS (1U << IRQN_BLE_TX_RETRANS) +#define IRQ_BLE_TX_ENTRY_DONE (1U << IRQN_BLE_TX_ENTRY_DONE) +#define IRQ_BLE_TX_BUFFER_CHANGED (1U << IRQN_BLE_TX_BUFFER_CHANGED) +#define IRQ_BLE_RX_OK (1U << IRQN_BLE_RX_OK) +#define IRQ_BLE_RX_NOK (1U << IRQN_BLE_RX_NOK) +#define IRQ_BLE_RX_IGNORED (1U << IRQN_BLE_RX_IGNORED) +#define IRQ_BLE_RX_EMPTY (1U << IRQN_BLE_RX_EMPTY) +#define IRQ_BLE_RX_CTRL (1U << IRQN_BLE_RX_CTRL) +#define IRQ_BLE_RX_CTRL_ACK (1U << IRQN_BLE_RX_CTRL_ACK) +#define IRQ_BLE_RX_BUF_FULL (1U << IRQN_BLE_RX_BUF_FULL) +#define IRQ_BLE_RX_ENTRY_DONE (1U << IRQN_BLE_RX_ENTRY_DONE) +///@} + + + +/// \name Radio operation status +/// Radio operation status format: +/// Bits 15:12: Protocol +/// 0001: BLE +/// Bits 11:10: Type +/// 00: Not finished +/// 01: Done successfully +/// 10: Done with error +/// Bits 9:0: Identifier + +/// \name Operation finished normally +///@{ +#define BLE_DONE_OK 0x1400 ///< Operation ended normally +#define BLE_DONE_RXTIMEOUT 0x1401 ///< Timeout of first Rx of slave operation or end of scan window +#define BLE_DONE_NOSYNC 0x1402 ///< Timeout of subsequent Rx +#define BLE_DONE_RXERR 0x1403 ///< Operation ended because of receive error (CRC or other) +#define BLE_DONE_CONNECT 0x1404 ///< CONNECT_REQ received or transmitted +#define BLE_DONE_MAXNACK 0x1405 ///< Maximum number of retransmissions exceeded +#define BLE_DONE_ENDED 0x1406 ///< Operation stopped after end trigger +#define BLE_DONE_ABORT 0x1407 ///< Operation aborted by command +#define BLE_DONE_STOPPED 0x1408 ///< Operation stopped after stop command +///@} +/// \name Operation finished with error +///@{ +#define BLE_ERROR_PAR 0x1800 ///< Illegal parameter +#define BLE_ERROR_RXBUF 0x1801 ///< No available Rx buffer (Advertiser, Scanner, Initiator) +#define BLE_ERROR_NO_SETUP 0x1802 ///< Operation using Rx or Tx attemted when not in BLE mode +#define BLE_ERROR_NO_FS 0x1803 ///< Operation using Rx or Tx attemted without frequency synth configured +#define BLE_ERROR_SYNTH_PROG 0x1804 ///< Synthesizer programming failed to complete on time +#define BLE_ERROR_RXOVF 0x1805 ///< Receiver overflowed during operation +#define BLE_ERROR_TXUNF 0x1806 ///< Transmitter underflowed during operation +///@} +///@} + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/common_cmd.h b/cpu/cc26xx/dev/rfc-api/common_cmd.h new file mode 100644 index 000000000..bae0a0200 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/common_cmd.h @@ -0,0 +1,1043 @@ +/****************************************************************************** +* Filename: common_cmd.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx API for common/generic commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef __COMMON_CMD_H +#define __COMMON_CMD_H + +#ifndef __RFC_STRUCT +#ifdef __GNUC__ +#define __RFC_STRUCT __attribute__ ((aligned (4))) +#else +#define __RFC_STRUCT +#endif +#endif + +//! \addtogroup rfc +//! @{ + +//! \addtogroup common_cmd +//! @{ + +#include +#include "mailbox.h" + +typedef struct __RFC_STRUCT rfc_CMD_FG_SCH_IMM_s rfc_CMD_FG_SCH_IMM_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_FWPAR_s rfc_CMD_WRITE_FWPAR_t; +typedef struct __RFC_STRUCT rfc_CMD_TX_TEST_s rfc_CMD_TX_TEST_t; +typedef struct __RFC_STRUCT rfc_CMD_RX_TEST_s rfc_CMD_RX_TEST_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_POWERDOWN_s rfc_CMD_FS_POWERDOWN_t; +typedef struct __RFC_STRUCT rfc_CMD_DISARM_RAT_CH_s rfc_CMD_DISARM_RAT_CH_t; +typedef struct __RFC_STRUCT rfc_CMD_SCH_IMM_s rfc_CMD_SCH_IMM_t; +typedef struct __RFC_STRUCT rfc_CMD_ANALOG_POWERDOWN_s rfc_CMD_ANALOG_POWERDOWN_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_RAT_CMP_s rfc_CMD_SET_RAT_CMP_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_OFF_s rfc_CMD_FS_OFF_t; +typedef struct __RFC_STRUCT rfc_CMD_ENABLE_DBG_s rfc_CMD_ENABLE_DBG_t; +typedef struct __RFC_STRUCT rfc_CMD_CLEAR_RX_s rfc_CMD_CLEAR_RX_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_s rfc_CMD_FS_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_COUNT_BRANCH_s rfc_CMD_FG_COUNT_BRANCH_t; +typedef struct __RFC_STRUCT rfc_CMD_GET_FW_INFO_s rfc_CMD_GET_FW_INFO_t; +typedef struct __RFC_STRUCT rfc_CMD_TOPSM_COPY_s rfc_CMD_TOPSM_COPY_t; +typedef struct __RFC_STRUCT rfc_CMD_USER_FUN_s rfc_CMD_USER_FUN_t; +typedef struct __RFC_STRUCT rfc_command_s rfc_command_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_ADI0REG_s rfc_CMD_WRITE_ADI0REG_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_POWERUP_s rfc_CMD_FS_POWERUP_t; +typedef struct __RFC_STRUCT rfc_CMD_SYNC_STOP_RAT_s rfc_CMD_SYNC_STOP_RAT_t; +typedef struct __RFC_STRUCT rfc_CMD_ADD_DATA_ENTRY_s rfc_CMD_ADD_DATA_ENTRY_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_COUNT_s rfc_CMD_FG_COUNT_t; +typedef struct __RFC_STRUCT rfc_CMD_MEMCPY_s rfc_CMD_MEMCPY_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_RAT_CPT_s rfc_CMD_SET_RAT_CPT_t; +typedef struct __RFC_STRUCT rfc_CMD_DISABLE_DBG_s rfc_CMD_DISABLE_DBG_t; +typedef struct __RFC_STRUCT rfc_CMD_SYNC_START_RAT_s rfc_CMD_SYNC_START_RAT_t; +typedef struct __RFC_STRUCT rfc_CMD_COUNT_s rfc_CMD_COUNT_t; +typedef struct __RFC_STRUCT rfc_CMD_PATTERN_CHECK_s rfc_CMD_PATTERN_CHECK_t; +typedef struct __RFC_STRUCT rfc_CMD_MODIFY_RFREG_s rfc_CMD_MODIFY_RFREG_t; +typedef struct __RFC_STRUCT rfc_CMD_REMOVE_PENDING_ENTRIES_s rfc_CMD_REMOVE_PENDING_ENTRIES_t; +typedef struct __RFC_STRUCT rfc_CMD_UPDATE_RADIO_SETUP_s rfc_CMD_UPDATE_RADIO_SETUP_t; +typedef struct __RFC_STRUCT rfc_CMD_NOP_s rfc_CMD_NOP_t; +typedef struct __RFC_STRUCT rfc_CMD_STOP_s rfc_CMD_STOP_t; +typedef struct __RFC_STRUCT rfc_CMD_TRIGGER_s rfc_CMD_TRIGGER_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_TRIM_s rfc_CMD_SET_TRIM_t; +typedef struct __RFC_STRUCT rfc_CMD_UPDATE_BAW_FREQ_s rfc_CMD_UPDATE_BAW_FREQ_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_FWPAR_s rfc_CMD_READ_FWPAR_t; +typedef struct __RFC_STRUCT rfc_CMD_REMOVE_DATA_ENTRY_s rfc_CMD_REMOVE_DATA_ENTRY_t; +typedef struct __RFC_STRUCT rfc_CMD_UPDATE_FS_s rfc_CMD_UPDATE_FS_t; +typedef struct __RFC_STRUCT rfc_CMD_ARM_RAT_CH_s rfc_CMD_ARM_RAT_CH_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_RFREG_s rfc_CMD_WRITE_RFREG_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_TX_SHAPE_s rfc_CMD_SET_TX_SHAPE_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_ADI1REG_s rfc_CMD_READ_ADI1REG_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_ADDR_s rfc_CMD_WRITE_ADDR_t; +typedef struct __RFC_STRUCT rfc_CMD_PING_s rfc_CMD_PING_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_RAT_OUTPUT_s rfc_CMD_SET_RAT_OUTPUT_t; +typedef struct __RFC_STRUCT rfc_CMD_DISABLE_RAT_CH_s rfc_CMD_DISABLE_RAT_CH_t; +typedef struct __RFC_STRUCT rfc_CMD_GET_RSSI_s rfc_CMD_GET_RSSI_t; +typedef struct __RFC_STRUCT rfc_CMD_MEMSET_s rfc_CMD_MEMSET_t; +typedef struct __RFC_STRUCT rfc_CMD_COUNT_BRANCH_s rfc_CMD_COUNT_BRANCH_t; +typedef struct __RFC_STRUCT rfc_CMD_ABORT_s rfc_CMD_ABORT_t; +typedef struct __RFC_STRUCT rfc_CMD_TX_s rfc_CMD_TX_t; +typedef struct __RFC_STRUCT rfc_radioOp_s rfc_radioOp_t; +typedef struct __RFC_STRUCT rfc_CMD_FORCE_CLK_ENA_s rfc_CMD_FORCE_CLK_ENA_t; +typedef struct __RFC_STRUCT rfc_CMD_START_RAT_s rfc_CMD_START_RAT_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_RFREG_s rfc_CMD_READ_RFREG_t; +typedef struct __RFC_STRUCT rfc_CMD_RX_s rfc_CMD_RX_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_PATTERN_CHECK_s rfc_CMD_FG_PATTERN_CHECK_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_TX_POWER_s rfc_CMD_SET_TX_POWER_t; +typedef struct __RFC_STRUCT rfc_CMD_BUS_REQUEST_s rfc_CMD_BUS_REQUEST_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_TRIM_s rfc_CMD_READ_TRIM_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_ADI0REG_s rfc_CMD_READ_ADI0REG_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_ADI1REG_s rfc_CMD_WRITE_ADI1REG_t; +typedef struct __RFC_STRUCT rfc_CMD_RADIO_SETUP_s rfc_CMD_RADIO_SETUP_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_FS_CAL_s rfc_CMD_READ_FS_CAL_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_NOP_s rfc_CMD_FG_NOP_t; +typedef struct __RFC_STRUCT rfc_CMD_FLUSH_QUEUE_s rfc_CMD_FLUSH_QUEUE_t; + +//! \addtogroup command +//! @{ +struct __RFC_STRUCT rfc_command_s { + uint16_t commandNo; //!< The command ID number +}; + +//! @} + +//! \addtogroup radioOp +//! @{ +//! Common definition for radio operation commands + +struct __RFC_STRUCT rfc_radioOp_s { + uint16_t commandNo; //!< The command ID number + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_NOP +//! @{ +#define CMD_NOP 0x0801 +struct __RFC_STRUCT rfc_CMD_NOP_s { + uint16_t commandNo; //!< The command ID number 0x0801 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_RADIO_SETUP +//! @{ +#define CMD_RADIO_SETUP 0x0802 +struct __RFC_STRUCT rfc_CMD_RADIO_SETUP_s { + uint16_t commandNo; //!< The command ID number 0x0802 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t mode; //!< \brief The main mode to use
+ //!< 0x00: BLE
+ //!< 0x01: IEEE 802.15.4
+ //!< 0x02: 2 Mbps GFSK
+ //!< 0x05: 5 Mbps coded 8-FSK
+ //!< 0x06: ANT
+ //!< 0xFF: Keep existing mode; update overrides only
+ //!< Others: Reserved + uint8_t __dummy0; + struct { + uint16_t frontEndMode:3; //!< \brief 0x00: Differential mode
+ //!< 0x01: Single-ended mode RFP
+ //!< 0x02: Single-ended mode RFN
+ //!< 0x03: Antenna diversity (start RFP)
+ //!< 0x04: Antenna diversity (start RFN)
+ //!< 0x05 Single-ended mode RFP with external frontend control on RF pins
+ //!< 0x06 Single-ended mode RFN with external frontend control on RF pins
+ //!< Others: Reserved + uint16_t biasMode:1; //!< \brief 0: Internal bias
+ //!< 1: External bias + uint16_t bNoAdi0Setup:1; //!< \brief 0: Program ADI 0 with default values
+ //!< 1: Do not program ADI 0 + uint16_t bNoAdi0Trim:1; //!< \brief 0: Apply trim values to ADI 0
+ //!< 1: Use default values for ADI 0 + uint16_t bNoAdi0Ovr:1; //!< \brief 0: Apply ADI 0 overrides
+ //!< 1: Ignore ADI 0 overrides + uint16_t bNoAdi1Setup:1; //!< \brief 0: Program ADI 1 with default values
+ //!< 1: Do not program ADI 1 + uint16_t bNoAdi1Trim:1; //!< \brief 0: Apply trim values to ADI 1
+ //!< 1: Use default values for ADI 1 + uint16_t bNoAdi1Ovr:1; //!< \brief 0: Apply ADI 1 overrides
+ //!< 1: Ignore ADI 1 overrides + uint16_t bNoFsPowerUp:1; //!< \brief 0: Power up frequency synth
+ //!< 1: Do not power up frequency synth + } config; //!< Configuration options + struct { + uint16_t IB:6; //!< Value to write to the PA power control field at 25 °C + uint16_t GC:2; //!< Value to write to the gain control of the 1st stage of the PA + uint16_t tempCoeff:8; //!< Temperature coefficient for IB. 0: No temperature compensation + } txPower; //!< Transmit power + uint32_t* pRegOverride; //!< \brief Pointer to a list of hardware and configuration registers to override. If NULL, no + //!< override is used. +}; + +//! @} + +//! \addtogroup CMD_FS +//! @{ +#define CMD_FS 0x0803 +struct __RFC_STRUCT rfc_CMD_FS_s { + uint16_t commandNo; //!< The command ID number 0x0803 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t frequency; //!< The frequency in MHz to tune to + uint16_t fractFreq; //!< Fractional part of the frequency to tune to + struct { + uint8_t bTxMode:1; //!< \brief 0: Start synth in Rx mode
+ //!< 1: Start synth in Tx mode + uint8_t refFreq:6; //!< Reserved + } synthConf; + struct { + uint8_t bOverrideCalib:1; //!< \brief 0: Use standard calibration settings (ignore calibration settings given in command)
+ //!< 1: Override calibration settings + uint8_t bSkipTdcCalib:1; //!< \brief 0: Perform TDC calibration
+ //!< 1: Skip TDC calibration + uint8_t bSkipCoarseCalib:1; //!< \brief 0: Perform coarse calibration
+ //!< 1: Skip coarse calibration + uint8_t bSkipMidCalib:1; //!< \brief 0: Perform mid calibration
+ //!< 1: Skip mid calibration + uint8_t coarsePrecal:4; //!< \brief Coarse pre-calibration value to use when bOverrideCalib and + //!< bSkipCoarseCalib are both 1 + } calibConf; + uint8_t midPrecal; //!< Mid pre-calibration value to use when bOverrideCalib and bSkipCoarseCalib are both 1 + uint8_t ktPrecal; //!< KT pre-calibration value to use when bOverrideCalib and bSkipCoarseCalib are both 1 + uint16_t tdcPrecal; //!< TDC pre-calibration value to use when bOverrideCalib and bSkipCoarseCalib are both 1 +}; + +//! @} + +//! \addtogroup CMD_FS_OFF +//! @{ +#define CMD_FS_OFF 0x0804 +struct __RFC_STRUCT rfc_CMD_FS_OFF_s { + uint16_t commandNo; //!< The command ID number 0x0804 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_RX +//! @{ +#define CMD_RX 0x0805 +struct __RFC_STRUCT rfc_CMD_RX_s { + uint16_t commandNo; //!< The command ID number 0x0805 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint16_t endianness:1; //!< \brief 0: Least significant bit first
+ //!< 1: Most significant bit first + uint16_t numHdrBits:6; //!< Number of bits in the header + uint16_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint16_t bUseCrc:1; //!< \brief 0: No CRC
+ //!< 1: The last bytes of the packet are a CRC + uint16_t bCrcIncSw:1; //!< \brief 0: Do not include sync word in CRC calculation
+ //!< 1: Include sync word in CRC calculation + uint16_t bCrcIncHdr:1; //!< \brief 0: Do not include header in CRC calculation
+ //!< 1: Include header in CRC calculation + uint16_t bReportCrc:1; //!< \brief 0: Do not write CRC to receive buffer
+ //!< 1: Write received CRC to receive buffer + uint16_t endType:1; //!< \brief 0: Packet is received to the end if end trigger happens after sync is obtained
+ //!< 1: Packet reception is stopped if end trigger happens + uint16_t bDualSw:1; //!< \brief 0: Single sync word
+ //!< 1: Dual sync word. + } pktConfig; + uint32_t syncWord; //!< Sync word to receive + uint32_t syncWord2; //!< Secondary sync word to receive if pktConfig.bDualSw = 1 + struct { + uint16_t numLenBits:4; //!< Number of bits in the length field + uint16_t lenFieldPos:5; //!< Bit position of the first bit in the length field + uint16_t lenOffset:7; //!< Signed number to add to the received length field + } lenConfig; + uint16_t maxLen; //!< Maximum number of bytes in the received packet (including header, excluding CRC) + uint8_t* pRecPkt; //!< Pointer to buffer for received packet. NULL: Do not store the contents. + ratmr_t endTime; //!< Time to end the operation + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger classifier for ending the operation + int8_t rssi; //!< RSSI of received packet + uint16_t recLen; //!< Number of bytes written to receive buffer + ratmr_t timeStamp; //!< Time stamp of received packet + uint16_t nRxOk; //!< Counter of number of received packets with CRC OK and first sync word + uint16_t nRxNok; //!< Counter of number of received packets with CRC error and first sync word + uint16_t nRx2Ok; //!< \brief Counter of number of received packets with CRC OK and second sync word; may safely be + //!< omitted if pktConfig.bDualSw is 0 + uint16_t nRx2Nok; //!< \brief Counter of number of received packets with CRC error and second sync word; may safely be + //!< omitted if pktConfig.bDualSw is 0 +}; + +//! @} + +//! \addtogroup CMD_TX +//! @{ +#define CMD_TX 0x0806 +struct __RFC_STRUCT rfc_CMD_TX_s { + uint16_t commandNo; //!< The command ID number 0x0806 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint16_t endianness:1; //!< \brief 0: Least significant bit first
+ //!< 1: Most significant bit first + uint16_t numHdrBits:6; //!< Number of bits in the header + uint16_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint16_t bUseCrc:1; //!< \brief 0: No CRC
+ //!< 1: Append a CRC to the packet + uint16_t bCrcIncSw:1; //!< \brief 0: Do not include sync word in CRC calculation
+ //!< 1: Include sync word in CRC calculation + uint16_t bCrcIncHdr:1; //!< \brief 0: Do not include header in CRC calculation
+ //!< 1: Include header in CRC calculation + } pktConfig; + uint32_t syncWord; //!< Sync word to transmit + uint8_t* pTxPkt; //!< Pointer to buffer for transmitted packet. + uint16_t pktLen; //!< Number of bytes in the transmitted packet +}; + +//! @} + +//! \addtogroup CMD_RX_TEST +//! @{ +#define CMD_RX_TEST 0x0807 +struct __RFC_STRUCT rfc_CMD_RX_TEST_s { + uint16_t commandNo; //!< The command ID number 0x0807 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint8_t bEnaFifo:1; //!< \brief 0: Do not enable FIFO in modem, so that received data is not available
+ //!< 1: Enable FIFO in modem – the data must be read out by the application + uint8_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint8_t bNoSync:1; //!< \brief 0: Run sync search as normal for the configured mode
+ //!< 1: Write correlation thresholds to the maximum value to avoid getting sync + } config; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger classifier for ending the operation + uint32_t syncWord; //!< Sync word to use for receiver + ratmr_t endTime; //!< Time to end the operation +}; + +//! @} + +//! \addtogroup CMD_TX_TEST +//! @{ +#define CMD_TX_TEST 0x0808 +struct __RFC_STRUCT rfc_CMD_TX_TEST_s { + uint16_t commandNo; //!< The command ID number 0x0808 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint8_t bUseCw:1; //!< \brief 0: Send modulated signal
+ //!< 1: Send continuous wave + uint8_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint8_t whitenMode:2; //!< \brief 0: No whitening
+ //!< 1: Default whitening
+ //!< 2: PRBS-15
+ //!< 3: PRBS-32 + } config; + uint8_t __dummy0; + uint16_t txWord; //!< Value to send to the modem before whitening + uint8_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger classifier for ending the operation + uint32_t syncWord; //!< Sync word to use for transmitter + ratmr_t endTime; //!< Time to end the operation +}; + +//! @} + +//! \addtogroup CMD_SYNC_STOP_RAT +//! @{ +#define CMD_SYNC_STOP_RAT 0x0809 +struct __RFC_STRUCT rfc_CMD_SYNC_STOP_RAT_s { + uint16_t commandNo; //!< The command ID number 0x0809 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + ratmr_t rat0; //!< \brief The returned RAT timer value corresponding to the value the RAT would have had when the + //!< RTC was zero +}; + +//! @} + +//! \addtogroup CMD_SYNC_START_RAT +//! @{ +#define CMD_SYNC_START_RAT 0x080A +struct __RFC_STRUCT rfc_CMD_SYNC_START_RAT_s { + uint16_t commandNo; //!< The command ID number 0x080A + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + ratmr_t rat0; //!< \brief The desired RAT timer value corresponding to the value the RAT would have had when the + //!< RTC was zero. This parameter is returned by CMD_SYNC_STOP_RAT +}; + +//! @} + +//! \addtogroup CMD_COUNT +//! @{ +#define CMD_COUNT 0x080B +struct __RFC_STRUCT rfc_CMD_COUNT_s { + uint16_t commandNo; //!< The command ID number 0x080B + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t counter; //!< \brief Counter. On start, the radio CPU decrements the value, and the end status of the operation + //!< differs if the result is zero +}; + +//! @} + +//! \addtogroup CMD_FS_POWERUP +//! @{ +#define CMD_FS_POWERUP 0x080C +struct __RFC_STRUCT rfc_CMD_FS_POWERUP_s { + uint16_t commandNo; //!< The command ID number 0x080C + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + uint32_t* pRegOverride; //!< Pointer to a list of hardware and configuration registers to override. If NULL, no override is used. +}; + +//! @} + +//! \addtogroup CMD_FS_POWERDOWN +//! @{ +#define CMD_FS_POWERDOWN 0x080D +struct __RFC_STRUCT rfc_CMD_FS_POWERDOWN_s { + uint16_t commandNo; //!< The command ID number 0x080D + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_SCH_IMM +//! @{ +#define CMD_SCH_IMM 0x0810 +struct __RFC_STRUCT rfc_CMD_SCH_IMM_s { + uint16_t commandNo; //!< The command ID number 0x0810 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + uint32_t cmdrVal; //!< Value as would be written to CMDR + uint32_t cmdstaVal; //!< Value as would be returned in CMDSTA +}; + +//! @} + +//! \addtogroup CMD_COUNT_BRANCH +//! @{ +#define CMD_COUNT_BRANCH 0x0812 +struct __RFC_STRUCT rfc_CMD_COUNT_BRANCH_s { + uint16_t commandNo; //!< The command ID number 0x0812 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t counter; //!< \brief Counter. On start, the radio CPU decrements the value, and the end status of the operation + //!< differs if the result is zero + rfc_radioOp_t *pNextOpIfOk; //!< Pointer to next operation if counter did not expire +}; + +//! @} + +//! \addtogroup CMD_PATTERN_CHECK +//! @{ +#define CMD_PATTERN_CHECK 0x0813 +struct __RFC_STRUCT rfc_CMD_PATTERN_CHECK_s { + uint16_t commandNo; //!< The command ID number 0x0813 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint16_t operation:2; //!< \brief Operation to perform
+ //!< 0: True if value == compareVal
+ //!< 1: True if value < compareVal
+ //!< 2: True if value > compareVal
+ //!< 3: Reserved + uint16_t bByteRev:1; //!< \brief If 1, interchange the four bytes of the value, so that they are read + //!< most-significant-byte-first. + uint16_t bBitRev:1; //!< If 1, perform bit reversal of the value + uint16_t signExtend:5; //!< \brief 0: Treat value and compareVal as unsigned
+ //!< 1–31: Treat value and compareVal as signed, where the value + //!< gives the number of the most significant bit in the signed number. + uint16_t bRxVal:1; //!< \brief 0: Use pValue as a pointer
+ //!< 1: Use pValue as a signed offset to the start of the last + //!< committed Rx entry element + } patternOpt; //!< Options for comparison + rfc_radioOp_t *pNextOpIfOk; //!< Pointer to next operation if comparison result was true + uint8_t* pValue; //!< Pointer to read from, or offset from last Rx entry if patternOpt.bRxVal == 1 + uint32_t mask; //!< Bit mask to apply before comparison + uint32_t compareVal; //!< Value to compare to +}; + +//! @} + +//! \addtogroup CMD_ABORT +//! @{ +#define CMD_ABORT 0x0401 +struct __RFC_STRUCT rfc_CMD_ABORT_s { + uint16_t commandNo; //!< The command ID number 0x0401 +}; + +//! @} + +//! \addtogroup CMD_STOP +//! @{ +#define CMD_STOP 0x0402 +struct __RFC_STRUCT rfc_CMD_STOP_s { + uint16_t commandNo; //!< The command ID number 0x0402 +}; + +//! @} + +//! \addtogroup CMD_GET_RSSI +//! @{ +#define CMD_GET_RSSI 0x0403 +struct __RFC_STRUCT rfc_CMD_GET_RSSI_s { + uint16_t commandNo; //!< The command ID number 0x0403 +}; + +//! @} + +//! \addtogroup CMD_UPDATE_RADIO_SETUP +//! @{ +#define CMD_UPDATE_RADIO_SETUP 0x0001 +struct __RFC_STRUCT rfc_CMD_UPDATE_RADIO_SETUP_s { + uint16_t commandNo; //!< The command ID number 0x0001 + uint16_t __dummy0; + uint32_t* pRegOverride; //!< Pointer to a list of hardware and configuration registers to override +}; + +//! @} + +//! \addtogroup CMD_TRIGGER +//! @{ +#define CMD_TRIGGER 0x0404 +struct __RFC_STRUCT rfc_CMD_TRIGGER_s { + uint16_t commandNo; //!< The command ID number 0x0404 + uint8_t triggerNo; //!< Command trigger number +}; + +//! @} + +//! \addtogroup CMD_GET_FW_INFO +//! @{ +#define CMD_GET_FW_INFO 0x0002 +struct __RFC_STRUCT rfc_CMD_GET_FW_INFO_s { + uint16_t commandNo; //!< The command ID number 0x0002 + uint16_t versionNo; //!< Firmware version number + uint16_t startOffset; //!< The start of free RAM + uint16_t freeRamSz; //!< The size of free RAM + uint16_t availRatCh; //!< Bitmap of available RAT channels +}; + +//! @} + +//! \addtogroup CMD_START_RAT +//! @{ +#define CMD_START_RAT 0x0405 +struct __RFC_STRUCT rfc_CMD_START_RAT_s { + uint16_t commandNo; //!< The command ID number 0x0405 +}; + +//! @} + +//! \addtogroup CMD_PING +//! @{ +#define CMD_PING 0x0406 +struct __RFC_STRUCT rfc_CMD_PING_s { + uint16_t commandNo; //!< The command ID number 0x0406 +}; + +//! @} + +//! \addtogroup CMD_ADD_DATA_ENTRY +//! @{ +#define CMD_ADD_DATA_ENTRY 0x0005 +struct __RFC_STRUCT rfc_CMD_ADD_DATA_ENTRY_s { + uint16_t commandNo; //!< The command ID number 0x0005 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to which the entry will be added + uint8_t* pEntry; //!< Pointer to the entry +}; + +//! @} + +//! \addtogroup CMD_REMOVE_DATA_ENTRY +//! @{ +#define CMD_REMOVE_DATA_ENTRY 0x0006 +struct __RFC_STRUCT rfc_CMD_REMOVE_DATA_ENTRY_s { + uint16_t commandNo; //!< The command ID number 0x0006 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure from which the entry will be removed + uint8_t* pEntry; //!< Pointer to the entry that was removed +}; + +//! @} + +//! \addtogroup CMD_FLUSH_QUEUE +//! @{ +#define CMD_FLUSH_QUEUE 0x0007 +struct __RFC_STRUCT rfc_CMD_FLUSH_QUEUE_s { + uint16_t commandNo; //!< The command ID number 0x0007 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to be flushed + uint8_t* pFirstEntry; //!< Pointer to the first entry that was removed +}; + +//! @} + +//! \addtogroup CMD_CLEAR_RX +//! @{ +#define CMD_CLEAR_RX 0x0008 +struct __RFC_STRUCT rfc_CMD_CLEAR_RX_s { + uint16_t commandNo; //!< The command ID number 0x0008 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to be cleared +}; + +//! @} + +//! \addtogroup CMD_REMOVE_PENDING_ENTRIES +//! @{ +#define CMD_REMOVE_PENDING_ENTRIES 0x0009 +struct __RFC_STRUCT rfc_CMD_REMOVE_PENDING_ENTRIES_s { + uint16_t commandNo; //!< The command ID number 0x0009 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to be flushed + uint8_t* pFirstEntry; //!< Pointer to the first entry that was removed +}; + +//! @} + +//! \addtogroup CMD_SET_RAT_CMP +//! @{ +#define CMD_SET_RAT_CMP 0x000A +struct __RFC_STRUCT rfc_CMD_SET_RAT_CMP_s { + uint16_t commandNo; //!< The command ID number 0x000A + uint8_t ratCh; //!< The radio timer channel number + uint8_t __dummy0; + ratmr_t compareTime; //!< The time at which the compare occurs +}; + +//! @} + +//! \addtogroup CMD_SET_RAT_CPT +//! @{ +#define CMD_SET_RAT_CPT 0x0603 +struct __RFC_STRUCT rfc_CMD_SET_RAT_CPT_s { + uint16_t commandNo; //!< The command ID number 0x0603 + struct { + uint16_t :3; + uint16_t inputSrc:5; //!< Input source indicator + uint16_t ratCh:4; //!< The radio timer channel number + uint16_t bRepeated:1; //!< \brief 0: Single capture mode
+ //!< 1: Repeated capture mode + uint16_t inputMode:2; //!< \brief Input mode:
+ //!< 0: Capture on rising edge
+ //!< 1: Capture on falling edge
+ //!< 2: Capture on both edges
+ //!< 3: Reserved + } config; +}; + +//! @} + +//! \addtogroup CMD_DISABLE_RAT_CH +//! @{ +#define CMD_DISABLE_RAT_CH 0x0408 +struct __RFC_STRUCT rfc_CMD_DISABLE_RAT_CH_s { + uint16_t commandNo; //!< The command ID number 0x0408 + uint8_t ratCh; //!< The radio timer channel number +}; + +//! @} + +//! \addtogroup CMD_SET_RAT_OUTPUT +//! @{ +#define CMD_SET_RAT_OUTPUT 0x0604 +struct __RFC_STRUCT rfc_CMD_SET_RAT_OUTPUT_s { + uint16_t commandNo; //!< The command ID number 0x0604 + struct { + uint16_t :2; + uint16_t outputSel:3; //!< Output event indicator + uint16_t outputMode:3; //!< \brief 0: Set output line low as default; and pulse on event. Duration of pulse is one RF Core clock period (ca. 41.67 ns).
+ //!< 1: Set output line high on event
+ //!< 2: Set output line low on event
+ //!< 3: Toggle (invert) output line state on event
+ //!< 4: Immediately set output line to low (does not change upon event)
+ //!< 5: Immediately set output line to high (does not change upon event)
+ //!< Others: Reserved + uint16_t ratCh:4; //!< The radio timer channel number + } config; +}; + +//! @} + +//! \addtogroup CMD_ARM_RAT_CH +//! @{ +#define CMD_ARM_RAT_CH 0x0409 +struct __RFC_STRUCT rfc_CMD_ARM_RAT_CH_s { + uint16_t commandNo; //!< The command ID number 0x0409 + uint8_t ratCh; //!< The radio timer channel number +}; + +//! @} + +//! \addtogroup CMD_DISARM_RAT_CH +//! @{ +#define CMD_DISARM_RAT_CH 0x040A +struct __RFC_STRUCT rfc_CMD_DISARM_RAT_CH_s { + uint16_t commandNo; //!< The command ID number 0x040A + uint8_t ratCh; //!< The radio timer channel number +}; + +//! @} + +//! \addtogroup CMD_SET_TX_POWER +//! @{ +#define CMD_SET_TX_POWER 0x0010 +struct __RFC_STRUCT rfc_CMD_SET_TX_POWER_s { + uint16_t commandNo; //!< The command ID number 0x0010 + struct { + uint16_t IB:6; //!< Value to write to the PA power control field at 25 °C + uint16_t GC:2; //!< Value to write to the gain control of the 1st stage of the PA + uint16_t tempCoeff:8; //!< Temperature coefficient for IB. 0: No temperature compensation + } txPower; //!< New Tx power setting +}; + +//! @} + +//! \addtogroup CMD_UPDATE_FS +//! @{ +#define CMD_UPDATE_FS 0x0011 +struct __RFC_STRUCT rfc_CMD_UPDATE_FS_s { + uint16_t commandNo; //!< The command ID number 0x0011 + uint16_t frequency; //!< The frequency in MHz to tune to + uint16_t fractFreq; //!< Fractional part of the frequency to tune to +}; + +//! @} + +//! \addtogroup CMD_BUS_REQUEST +//! @{ +#define CMD_BUS_REQUEST 0x040E +struct __RFC_STRUCT rfc_CMD_BUS_REQUEST_s { + uint16_t commandNo; //!< The command ID number 0x040E + uint8_t bSysBusNeeded; //!< \brief 0: System bus may sleep
+ //!< 1: System bus access needed +}; + +//! @} + +//! @} +//! @} +#endif diff --git a/cpu/cc26xx/dev/rfc-api/common_cmd_field.h b/cpu/cc26xx/dev/rfc-api/common_cmd_field.h new file mode 100755 index 000000000..d9e9431f6 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/common_cmd_field.h @@ -0,0 +1,448 @@ +/****************************************************************************** +* Filename: common_cmd_field.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx API for common/generic commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef __COMMON_CMD_FIELD_H +#define __COMMON_CMD_FIELD_H + +#include +#include "mailbox.h" + +#define _POSITION_command_commandNo 0 +#define _TYPE_command_commandNo uint16_t +#define _SIZEOF_command 2 + +#define _POSITION_radioOp_commandNo 0 +#define _TYPE_radioOp_commandNo uint16_t +#define _POSITION_radioOp_status 2 +#define _TYPE_radioOp_status uint16_t +#define _POSITION_radioOp_pNextOp 4 +#define _TYPE_radioOp_pNextOp uint8_t* +#define _POSITION_radioOp_startTime 8 +#define _TYPE_radioOp_startTime ratmr_t +#define _POSITION_radioOp_startTrigger 12 +#define _TYPE_radioOp_startTrigger uint8_t +#define _BITPOS_radioOp_startTrigger_triggerType 0 +#define _NBITS_radioOp_startTrigger_triggerType 4 +#define _BITPOS_radioOp_startTrigger_bEnaCmd 4 +#define _NBITS_radioOp_startTrigger_bEnaCmd 1 +#define _BITPOS_radioOp_startTrigger_triggerNo 5 +#define _NBITS_radioOp_startTrigger_triggerNo 2 +#define _BITPOS_radioOp_startTrigger_pastTrig 7 +#define _NBITS_radioOp_startTrigger_pastTrig 1 +#define _POSITION_radioOp_condition 13 +#define _TYPE_radioOp_condition uint8_t +#define _BITPOS_radioOp_condition_rule 0 +#define _NBITS_radioOp_condition_rule 4 +#define _BITPOS_radioOp_condition_nSkip 4 +#define _NBITS_radioOp_condition_nSkip 4 +#define _SIZEOF_radioOp 14 + +#define _SIZEOF_CMD_NOP 14 + +#define _POSITION_CMD_RADIO_SETUP_mode 14 +#define _TYPE_CMD_RADIO_SETUP_mode uint8_t +#define _POSITION_CMD_RADIO_SETUP_config 16 +#define _TYPE_CMD_RADIO_SETUP_config uint16_t +#define _BITPOS_CMD_RADIO_SETUP_config_frontEndMode 0 +#define _NBITS_CMD_RADIO_SETUP_config_frontEndMode 3 +#define _BITPOS_CMD_RADIO_SETUP_config_biasMode 3 +#define _NBITS_CMD_RADIO_SETUP_config_biasMode 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi0Setup 4 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi0Setup 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi0Trim 5 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi0Trim 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi0Ovr 6 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi0Ovr 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi1Setup 7 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi1Setup 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi1Trim 8 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi1Trim 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi1Ovr 9 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi1Ovr 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoFsPowerUp 10 +#define _NBITS_CMD_RADIO_SETUP_config_bNoFsPowerUp 1 +#define _POSITION_CMD_RADIO_SETUP_txPower 18 +#define _TYPE_CMD_RADIO_SETUP_txPower uint16_t +#define _BITPOS_CMD_RADIO_SETUP_txPower_IB 0 +#define _NBITS_CMD_RADIO_SETUP_txPower_IB 6 +#define _BITPOS_CMD_RADIO_SETUP_txPower_GC 6 +#define _NBITS_CMD_RADIO_SETUP_txPower_GC 2 +#define _BITPOS_CMD_RADIO_SETUP_txPower_tempCoeff 8 +#define _NBITS_CMD_RADIO_SETUP_txPower_tempCoeff 8 +#define _POSITION_CMD_RADIO_SETUP_pRegOverride 20 +#define _TYPE_CMD_RADIO_SETUP_pRegOverride uint32_t* +#define _SIZEOF_CMD_RADIO_SETUP 24 + +#define _POSITION_CMD_FS_frequency 14 +#define _TYPE_CMD_FS_frequency uint16_t +#define _POSITION_CMD_FS_fractFreq 16 +#define _TYPE_CMD_FS_fractFreq uint16_t +#define _POSITION_CMD_FS_synthConf 18 +#define _TYPE_CMD_FS_synthConf uint8_t +#define _BITPOS_CMD_FS_synthConf_bTxMode 0 +#define _NBITS_CMD_FS_synthConf_bTxMode 1 +#define _BITPOS_CMD_FS_synthConf_refFreq 1 +#define _NBITS_CMD_FS_synthConf_refFreq 6 +#define _POSITION_CMD_FS_calibConf 19 +#define _TYPE_CMD_FS_calibConf uint8_t +#define _BITPOS_CMD_FS_calibConf_bOverrideCalib 0 +#define _NBITS_CMD_FS_calibConf_bOverrideCalib 1 +#define _BITPOS_CMD_FS_calibConf_bSkipTdcCalib 1 +#define _NBITS_CMD_FS_calibConf_bSkipTdcCalib 1 +#define _BITPOS_CMD_FS_calibConf_bSkipCoarseCalib 2 +#define _NBITS_CMD_FS_calibConf_bSkipCoarseCalib 1 +#define _BITPOS_CMD_FS_calibConf_bSkipMidCalib 3 +#define _NBITS_CMD_FS_calibConf_bSkipMidCalib 1 +#define _BITPOS_CMD_FS_calibConf_coarsePrecal 4 +#define _NBITS_CMD_FS_calibConf_coarsePrecal 4 +#define _POSITION_CMD_FS_midPrecal 20 +#define _TYPE_CMD_FS_midPrecal uint8_t +#define _POSITION_CMD_FS_ktPrecal 21 +#define _TYPE_CMD_FS_ktPrecal uint8_t +#define _POSITION_CMD_FS_tdcPrecal 22 +#define _TYPE_CMD_FS_tdcPrecal uint16_t +#define _SIZEOF_CMD_FS 24 + +#define _SIZEOF_CMD_FS_OFF 14 + +#define _POSITION_CMD_RX_pktConfig 14 +#define _TYPE_CMD_RX_pktConfig uint16_t +#define _BITPOS_CMD_RX_pktConfig_endianness 0 +#define _NBITS_CMD_RX_pktConfig_endianness 1 +#define _BITPOS_CMD_RX_pktConfig_numHdrBits 1 +#define _NBITS_CMD_RX_pktConfig_numHdrBits 6 +#define _BITPOS_CMD_RX_pktConfig_bFsOff 7 +#define _NBITS_CMD_RX_pktConfig_bFsOff 1 +#define _BITPOS_CMD_RX_pktConfig_bUseCrc 8 +#define _NBITS_CMD_RX_pktConfig_bUseCrc 1 +#define _BITPOS_CMD_RX_pktConfig_bCrcIncSw 9 +#define _NBITS_CMD_RX_pktConfig_bCrcIncSw 1 +#define _BITPOS_CMD_RX_pktConfig_bCrcIncHdr 10 +#define _NBITS_CMD_RX_pktConfig_bCrcIncHdr 1 +#define _BITPOS_CMD_RX_pktConfig_bReportCrc 11 +#define _NBITS_CMD_RX_pktConfig_bReportCrc 1 +#define _BITPOS_CMD_RX_pktConfig_endType 12 +#define _NBITS_CMD_RX_pktConfig_endType 1 +#define _BITPOS_CMD_RX_pktConfig_bDualSw 13 +#define _NBITS_CMD_RX_pktConfig_bDualSw 1 +#define _POSITION_CMD_RX_syncWord 16 +#define _TYPE_CMD_RX_syncWord uint32_t +#define _POSITION_CMD_RX_syncWord2 20 +#define _TYPE_CMD_RX_syncWord2 uint32_t +#define _POSITION_CMD_RX_lenConfig 24 +#define _TYPE_CMD_RX_lenConfig uint16_t +#define _BITPOS_CMD_RX_lenConfig_numLenBits 0 +#define _NBITS_CMD_RX_lenConfig_numLenBits 4 +#define _BITPOS_CMD_RX_lenConfig_lenFieldPos 4 +#define _NBITS_CMD_RX_lenConfig_lenFieldPos 5 +#define _BITPOS_CMD_RX_lenConfig_lenOffset 9 +#define _NBITS_CMD_RX_lenConfig_lenOffset 7 +#define _POSITION_CMD_RX_maxLen 26 +#define _TYPE_CMD_RX_maxLen uint16_t +#define _POSITION_CMD_RX_pRecPkt 28 +#define _TYPE_CMD_RX_pRecPkt uint8_t* +#define _POSITION_CMD_RX_endTime 32 +#define _TYPE_CMD_RX_endTime ratmr_t +#define _POSITION_CMD_RX_endTrigger 36 +#define _TYPE_CMD_RX_endTrigger uint8_t +#define _BITPOS_CMD_RX_endTrigger_triggerType 0 +#define _NBITS_CMD_RX_endTrigger_triggerType 4 +#define _BITPOS_CMD_RX_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_RX_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_RX_endTrigger_triggerNo 5 +#define _NBITS_CMD_RX_endTrigger_triggerNo 2 +#define _BITPOS_CMD_RX_endTrigger_pastTrig 7 +#define _NBITS_CMD_RX_endTrigger_pastTrig 1 +#define _POSITION_CMD_RX_rssi 37 +#define _TYPE_CMD_RX_rssi int8_t +#define _POSITION_CMD_RX_recLen 38 +#define _TYPE_CMD_RX_recLen uint16_t +#define _POSITION_CMD_RX_timeStamp 40 +#define _TYPE_CMD_RX_timeStamp ratmr_t +#define _POSITION_CMD_RX_nRxOk 44 +#define _TYPE_CMD_RX_nRxOk uint16_t +#define _POSITION_CMD_RX_nRxNok 46 +#define _TYPE_CMD_RX_nRxNok uint16_t +#define _POSITION_CMD_RX_nRx2Ok 48 +#define _TYPE_CMD_RX_nRx2Ok uint16_t +#define _POSITION_CMD_RX_nRx2Nok 50 +#define _TYPE_CMD_RX_nRx2Nok uint16_t +#define _SIZEOF_CMD_RX 52 + +#define _POSITION_CMD_TX_pktConfig 14 +#define _TYPE_CMD_TX_pktConfig uint16_t +#define _BITPOS_CMD_TX_pktConfig_endianness 0 +#define _NBITS_CMD_TX_pktConfig_endianness 1 +#define _BITPOS_CMD_TX_pktConfig_numHdrBits 1 +#define _NBITS_CMD_TX_pktConfig_numHdrBits 6 +#define _BITPOS_CMD_TX_pktConfig_bFsOff 7 +#define _NBITS_CMD_TX_pktConfig_bFsOff 1 +#define _BITPOS_CMD_TX_pktConfig_bUseCrc 8 +#define _NBITS_CMD_TX_pktConfig_bUseCrc 1 +#define _BITPOS_CMD_TX_pktConfig_bCrcIncSw 9 +#define _NBITS_CMD_TX_pktConfig_bCrcIncSw 1 +#define _BITPOS_CMD_TX_pktConfig_bCrcIncHdr 10 +#define _NBITS_CMD_TX_pktConfig_bCrcIncHdr 1 +#define _POSITION_CMD_TX_syncWord 16 +#define _TYPE_CMD_TX_syncWord uint32_t +#define _POSITION_CMD_TX_pTxPkt 20 +#define _TYPE_CMD_TX_pTxPkt uint8_t* +#define _POSITION_CMD_TX_pktLen 24 +#define _TYPE_CMD_TX_pktLen uint16_t +#define _SIZEOF_CMD_TX 26 + +#define _POSITION_CMD_RX_TEST_config 14 +#define _TYPE_CMD_RX_TEST_config uint8_t +#define _BITPOS_CMD_RX_TEST_config_bEnaFifo 0 +#define _NBITS_CMD_RX_TEST_config_bEnaFifo 1 +#define _BITPOS_CMD_RX_TEST_config_bFsOff 1 +#define _NBITS_CMD_RX_TEST_config_bFsOff 1 +#define _BITPOS_CMD_RX_TEST_config_bNoSync 2 +#define _NBITS_CMD_RX_TEST_config_bNoSync 1 +#define _POSITION_CMD_RX_TEST_endTrigger 15 +#define _TYPE_CMD_RX_TEST_endTrigger uint8_t +#define _BITPOS_CMD_RX_TEST_endTrigger_triggerType 0 +#define _NBITS_CMD_RX_TEST_endTrigger_triggerType 4 +#define _BITPOS_CMD_RX_TEST_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_RX_TEST_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_RX_TEST_endTrigger_triggerNo 5 +#define _NBITS_CMD_RX_TEST_endTrigger_triggerNo 2 +#define _BITPOS_CMD_RX_TEST_endTrigger_pastTrig 7 +#define _NBITS_CMD_RX_TEST_endTrigger_pastTrig 1 +#define _POSITION_CMD_RX_TEST_syncWord 16 +#define _TYPE_CMD_RX_TEST_syncWord uint32_t +#define _POSITION_CMD_RX_TEST_endTime 20 +#define _TYPE_CMD_RX_TEST_endTime ratmr_t +#define _SIZEOF_CMD_RX_TEST 24 + +#define _POSITION_CMD_TX_TEST_config 14 +#define _TYPE_CMD_TX_TEST_config uint8_t +#define _BITPOS_CMD_TX_TEST_config_bUseCw 0 +#define _NBITS_CMD_TX_TEST_config_bUseCw 1 +#define _BITPOS_CMD_TX_TEST_config_bFsOff 1 +#define _NBITS_CMD_TX_TEST_config_bFsOff 1 +#define _BITPOS_CMD_TX_TEST_config_whitenMode 2 +#define _NBITS_CMD_TX_TEST_config_whitenMode 2 +#define _POSITION_CMD_TX_TEST_txWord 16 +#define _TYPE_CMD_TX_TEST_txWord uint16_t +#define _POSITION_CMD_TX_TEST_endTrigger 19 +#define _TYPE_CMD_TX_TEST_endTrigger uint8_t +#define _BITPOS_CMD_TX_TEST_endTrigger_triggerType 0 +#define _NBITS_CMD_TX_TEST_endTrigger_triggerType 4 +#define _BITPOS_CMD_TX_TEST_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_TX_TEST_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_TX_TEST_endTrigger_triggerNo 5 +#define _NBITS_CMD_TX_TEST_endTrigger_triggerNo 2 +#define _BITPOS_CMD_TX_TEST_endTrigger_pastTrig 7 +#define _NBITS_CMD_TX_TEST_endTrigger_pastTrig 1 +#define _POSITION_CMD_TX_TEST_syncWord 20 +#define _TYPE_CMD_TX_TEST_syncWord uint32_t +#define _POSITION_CMD_TX_TEST_endTime 24 +#define _TYPE_CMD_TX_TEST_endTime ratmr_t +#define _SIZEOF_CMD_TX_TEST 28 + +#define _POSITION_CMD_SYNC_STOP_RAT_rat0 16 +#define _TYPE_CMD_SYNC_STOP_RAT_rat0 ratmr_t +#define _SIZEOF_CMD_SYNC_STOP_RAT 20 + +#define _POSITION_CMD_SYNC_START_RAT_rat0 16 +#define _TYPE_CMD_SYNC_START_RAT_rat0 ratmr_t +#define _SIZEOF_CMD_SYNC_START_RAT 20 + +#define _POSITION_CMD_COUNT_counter 14 +#define _TYPE_CMD_COUNT_counter uint16_t +#define _SIZEOF_CMD_COUNT 16 + +#define _POSITION_CMD_FS_POWERUP_pRegOverride 16 +#define _TYPE_CMD_FS_POWERUP_pRegOverride uint32_t* +#define _SIZEOF_CMD_FS_POWERUP 20 + +#define _SIZEOF_CMD_FS_POWERDOWN 14 + +#define _POSITION_CMD_SCH_IMM_cmdrVal 16 +#define _TYPE_CMD_SCH_IMM_cmdrVal uint32_t +#define _POSITION_CMD_SCH_IMM_cmdstaVal 20 +#define _TYPE_CMD_SCH_IMM_cmdstaVal uint32_t +#define _SIZEOF_CMD_SCH_IMM 24 + +#define _POSITION_CMD_COUNT_BRANCH_counter 14 +#define _TYPE_CMD_COUNT_BRANCH_counter uint16_t +#define _POSITION_CMD_COUNT_BRANCH_pNextOpIfOk 16 +#define _TYPE_CMD_COUNT_BRANCH_pNextOpIfOk uint8_t* +#define _SIZEOF_CMD_COUNT_BRANCH 20 + +#define _POSITION_CMD_PATTERN_CHECK_patternOpt 14 +#define _TYPE_CMD_PATTERN_CHECK_patternOpt uint16_t +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_operation 0 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_operation 2 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_bByteRev 2 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_bByteRev 1 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_bBitRev 3 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_bBitRev 1 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_signExtend 4 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_signExtend 5 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_bRxVal 9 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_bRxVal 1 +#define _POSITION_CMD_PATTERN_CHECK_pNextOpIfOk 16 +#define _TYPE_CMD_PATTERN_CHECK_pNextOpIfOk uint8_t* +#define _POSITION_CMD_PATTERN_CHECK_pValue 20 +#define _TYPE_CMD_PATTERN_CHECK_pValue uint8_t* +#define _POSITION_CMD_PATTERN_CHECK_mask 24 +#define _TYPE_CMD_PATTERN_CHECK_mask uint32_t +#define _POSITION_CMD_PATTERN_CHECK_compareVal 28 +#define _TYPE_CMD_PATTERN_CHECK_compareVal uint32_t +#define _SIZEOF_CMD_PATTERN_CHECK 32 + +#define _SIZEOF_CMD_ABORT 2 + +#define _SIZEOF_CMD_STOP 2 + +#define _SIZEOF_CMD_GET_RSSI 2 + +#define _POSITION_CMD_UPDATE_RADIO_SETUP_pRegOverride 4 +#define _TYPE_CMD_UPDATE_RADIO_SETUP_pRegOverride uint32_t* +#define _SIZEOF_CMD_UPDATE_RADIO_SETUP 8 + +#define _POSITION_CMD_TRIGGER_triggerNo 2 +#define _TYPE_CMD_TRIGGER_triggerNo uint8_t +#define _SIZEOF_CMD_TRIGGER 3 + +#define _POSITION_CMD_GET_FW_INFO_versionNo 2 +#define _TYPE_CMD_GET_FW_INFO_versionNo uint16_t +#define _POSITION_CMD_GET_FW_INFO_startOffset 4 +#define _TYPE_CMD_GET_FW_INFO_startOffset uint16_t +#define _POSITION_CMD_GET_FW_INFO_freeRamSz 6 +#define _TYPE_CMD_GET_FW_INFO_freeRamSz uint16_t +#define _POSITION_CMD_GET_FW_INFO_availRatCh 8 +#define _TYPE_CMD_GET_FW_INFO_availRatCh uint16_t +#define _SIZEOF_CMD_GET_FW_INFO 10 + +#define _SIZEOF_CMD_START_RAT 2 + +#define _SIZEOF_CMD_PING 2 + +#define _POSITION_CMD_ADD_DATA_ENTRY_pQueue 4 +#define _TYPE_CMD_ADD_DATA_ENTRY_pQueue dataQueue_t* +#define _POSITION_CMD_ADD_DATA_ENTRY_pEntry 8 +#define _TYPE_CMD_ADD_DATA_ENTRY_pEntry uint8_t* +#define _SIZEOF_CMD_ADD_DATA_ENTRY 12 + +#define _POSITION_CMD_REMOVE_DATA_ENTRY_pQueue 4 +#define _TYPE_CMD_REMOVE_DATA_ENTRY_pQueue dataQueue_t* +#define _POSITION_CMD_REMOVE_DATA_ENTRY_pEntry 8 +#define _TYPE_CMD_REMOVE_DATA_ENTRY_pEntry uint8_t* +#define _SIZEOF_CMD_REMOVE_DATA_ENTRY 12 + +#define _POSITION_CMD_FLUSH_QUEUE_pQueue 4 +#define _TYPE_CMD_FLUSH_QUEUE_pQueue dataQueue_t* +#define _POSITION_CMD_FLUSH_QUEUE_pFirstEntry 8 +#define _TYPE_CMD_FLUSH_QUEUE_pFirstEntry uint8_t* +#define _SIZEOF_CMD_FLUSH_QUEUE 12 + +#define _POSITION_CMD_CLEAR_RX_pQueue 4 +#define _TYPE_CMD_CLEAR_RX_pQueue dataQueue_t* +#define _SIZEOF_CMD_CLEAR_RX 8 + +#define _POSITION_CMD_REMOVE_PENDING_ENTRIES_pQueue 4 +#define _TYPE_CMD_REMOVE_PENDING_ENTRIES_pQueue dataQueue_t* +#define _POSITION_CMD_REMOVE_PENDING_ENTRIES_pFirstEntry 8 +#define _TYPE_CMD_REMOVE_PENDING_ENTRIES_pFirstEntry uint8_t* +#define _SIZEOF_CMD_REMOVE_PENDING_ENTRIES 12 + +#define _POSITION_CMD_SET_RAT_CMP_ratCh 2 +#define _TYPE_CMD_SET_RAT_CMP_ratCh uint8_t +#define _POSITION_CMD_SET_RAT_CMP_compareTime 4 +#define _TYPE_CMD_SET_RAT_CMP_compareTime ratmr_t +#define _SIZEOF_CMD_SET_RAT_CMP 8 + +#define _POSITION_CMD_SET_RAT_CPT_config 2 +#define _TYPE_CMD_SET_RAT_CPT_config uint16_t +#define _BITPOS_CMD_SET_RAT_CPT_config_inputSrc 3 +#define _NBITS_CMD_SET_RAT_CPT_config_inputSrc 5 +#define _BITPOS_CMD_SET_RAT_CPT_config_ratCh 8 +#define _NBITS_CMD_SET_RAT_CPT_config_ratCh 4 +#define _BITPOS_CMD_SET_RAT_CPT_config_bRepeated 12 +#define _NBITS_CMD_SET_RAT_CPT_config_bRepeated 1 +#define _BITPOS_CMD_SET_RAT_CPT_config_inputMode 13 +#define _NBITS_CMD_SET_RAT_CPT_config_inputMode 2 +#define _SIZEOF_CMD_SET_RAT_CPT 4 + +#define _POSITION_CMD_DISABLE_RAT_CH_ratCh 2 +#define _TYPE_CMD_DISABLE_RAT_CH_ratCh uint8_t +#define _SIZEOF_CMD_DISABLE_RAT_CH 3 + +#define _POSITION_CMD_SET_RAT_OUTPUT_config 2 +#define _TYPE_CMD_SET_RAT_OUTPUT_config uint16_t +#define _BITPOS_CMD_SET_RAT_OUTPUT_config_outputSel 2 +#define _NBITS_CMD_SET_RAT_OUTPUT_config_outputSel 3 +#define _BITPOS_CMD_SET_RAT_OUTPUT_config_outputMode 5 +#define _NBITS_CMD_SET_RAT_OUTPUT_config_outputMode 3 +#define _BITPOS_CMD_SET_RAT_OUTPUT_config_ratCh 8 +#define _NBITS_CMD_SET_RAT_OUTPUT_config_ratCh 4 +#define _SIZEOF_CMD_SET_RAT_OUTPUT 4 + +#define _POSITION_CMD_ARM_RAT_CH_ratCh 2 +#define _TYPE_CMD_ARM_RAT_CH_ratCh uint8_t +#define _SIZEOF_CMD_ARM_RAT_CH 3 + +#define _POSITION_CMD_DISARM_RAT_CH_ratCh 2 +#define _TYPE_CMD_DISARM_RAT_CH_ratCh uint8_t +#define _SIZEOF_CMD_DISARM_RAT_CH 3 + +#define _POSITION_CMD_SET_TX_POWER_txPower 2 +#define _TYPE_CMD_SET_TX_POWER_txPower uint16_t +#define _BITPOS_CMD_SET_TX_POWER_txPower_IB 0 +#define _NBITS_CMD_SET_TX_POWER_txPower_IB 6 +#define _BITPOS_CMD_SET_TX_POWER_txPower_GC 6 +#define _NBITS_CMD_SET_TX_POWER_txPower_GC 2 +#define _BITPOS_CMD_SET_TX_POWER_txPower_tempCoeff 8 +#define _NBITS_CMD_SET_TX_POWER_txPower_tempCoeff 8 +#define _SIZEOF_CMD_SET_TX_POWER 4 + +#define _POSITION_CMD_UPDATE_FS_frequency 2 +#define _TYPE_CMD_UPDATE_FS_frequency uint16_t +#define _POSITION_CMD_UPDATE_FS_fractFreq 4 +#define _TYPE_CMD_UPDATE_FS_fractFreq uint16_t +#define _SIZEOF_CMD_UPDATE_FS 6 + +#define _POSITION_CMD_BUS_REQUEST_bSysBusNeeded 2 +#define _TYPE_CMD_BUS_REQUEST_bSysBusNeeded uint8_t +#define _SIZEOF_CMD_BUS_REQUEST 3 + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/data_entry.h b/cpu/cc26xx/dev/rfc-api/data_entry.h new file mode 100644 index 000000000..91c1826de --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/data_entry.h @@ -0,0 +1,91 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#ifndef __DATA_ENTRY_H +#define __DATA_ENTRY_H + +#include +#include "mailbox.h" + +typedef struct rfc_dataEntry_s rfc_dataEntry_t; + +#define _POSITION_dataEntry_pNextEntry 0 +#define _TYPE_dataEntry_pNextEntry uint8_t* +#define _POSITION_dataEntry_status 4 +#define _TYPE_dataEntry_status uint8_t +#define _POSITION_dataEntry_config 5 +#define _TYPE_dataEntry_config uint8_t +#define _BITPOS_dataEntry_config_type 0 +#define _NBITS_dataEntry_config_type 2 +#define _BITPOS_dataEntry_config_lenSz 2 +#define _NBITS_dataEntry_config_lenSz 2 +#define _BITPOS_dataEntry_config_irqIntv 4 +#define _NBITS_dataEntry_config_irqIntv 4 +#define _POSITION_dataEntry_length 6 +#define _TYPE_dataEntry_length uint16_t +#define _POSITION_dataEntry_data 8 +#define _TYPE_dataEntry_data uint8_t +#define _POSITION_dataEntry_pData 8 +#define _TYPE_dataEntry_pData uint8_t* +#define _POSITION_dataEntry_numElements 8 +#define _TYPE_dataEntry_numElements uint16_t +#define _POSITION_dataEntry_pktStatus 8 +#define _TYPE_dataEntry_pktStatus uint16_t +#define _BITPOS_dataEntry_pktStatus_numElements 0 +#define _NBITS_dataEntry_pktStatus_numElements 13 +#define _BITPOS_dataEntry_pktStatus_bEntryOpen 13 +#define _NBITS_dataEntry_pktStatus_bEntryOpen 1 +#define _BITPOS_dataEntry_pktStatus_bFirstCont 14 +#define _NBITS_dataEntry_pktStatus_bFirstCont 1 +#define _BITPOS_dataEntry_pktStatus_bLastCont 15 +#define _NBITS_dataEntry_pktStatus_bLastCont 1 +#define _POSITION_dataEntry_nextIndex 10 +#define _TYPE_dataEntry_nextIndex uint16_t +#define _POSITION_dataEntry_rxData 12 +#define _TYPE_dataEntry_rxData uint8_t +#define _LAST_POSITION_dataEntry 12 +#define _LAST_TYPE_dataEntry uint8_t + +struct rfc_dataEntry_s { + uint8_t* pNextEntry; + uint8_t status; + struct { + uint8_t type:2; + uint8_t lenSz:2; + uint8_t irqIntv:4; + } config; + uint16_t length; + uint8_t data; + uint8_t __dummy0; + uint16_t nextIndex; + uint8_t rxData; +}; + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ieee_cmd.h b/cpu/cc26xx/dev/rfc-api/ieee_cmd.h new file mode 100644 index 000000000..e06207053 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ieee_cmd.h @@ -0,0 +1,614 @@ +/****************************************************************************** +* Filename: ieee_cmd.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for IEEE 802.15.4 commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef __IEEE_CMD_H +#define __IEEE_CMD_H + +#ifndef __RFC_STRUCT +#ifdef __GNUC__ +#define __RFC_STRUCT __attribute__ ((aligned (4))) +#else +#define __RFC_STRUCT +#endif +#endif + +//! \addtogroup rfc +//! @{ + +//! \addtogroup ieee_cmd +//! @{ + +#include +#include "mailbox.h" +#include "common_cmd.h" + +typedef struct __RFC_STRUCT rfc_CMD_IEEE_RX_s rfc_CMD_IEEE_RX_t; +typedef struct __RFC_STRUCT rfc_shortAddrEntry_s rfc_shortAddrEntry_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_CSMA_s rfc_CMD_IEEE_CSMA_t; +typedef struct __RFC_STRUCT rfc_ieeeAuxSecCtrl_s rfc_ieeeAuxSecCtrl_t; +typedef struct __RFC_STRUCT rfc_ieeeRxCorrCrc_s rfc_ieeeRxCorrCrc_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_RX_ACK_s rfc_CMD_IEEE_RX_ACK_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_BG_s rfc_CMD_IEEE_ABORT_BG_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_ED_SCAN_s rfc_CMD_IEEE_ED_SCAN_t; +typedef struct __RFC_STRUCT rfc_ieeeMacHdr_s rfc_ieeeMacHdr_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_FG_s rfc_CMD_IEEE_ABORT_FG_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_CCA_REQ_s rfc_CMD_IEEE_CCA_REQ_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_SETUP_s rfc_CMD_IEEE_SETUP_t; +typedef struct __RFC_STRUCT rfc_ieeeRxOutput_s rfc_ieeeRxOutput_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_MOD_SRC_MATCH_s rfc_CMD_IEEE_MOD_SRC_MATCH_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_STOP_FG_s rfc_CMD_IEEE_STOP_FG_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_TX_s rfc_CMD_IEEE_TX_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_MOD_FILT_s rfc_CMD_IEEE_MOD_FILT_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_MOD_CCA_s rfc_CMD_IEEE_MOD_CCA_t; + +//! \addtogroup CMD_IEEE_RX +//! @{ +#define CMD_IEEE_RX 0x2801 +struct __RFC_STRUCT rfc_CMD_IEEE_RX_s { + uint16_t commandNo; //!< The command ID number 0x2801 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to tune to in the start of the operation
+ //!< 0: Use existing channel
+ //!< 11–26: Use as IEEE 802.15.4 channel, i.e. frequency is (2405 + 5 × (channel - 11)) MHz
+ //!< 60–207: Frequency is (2300 + channel) MHz
+ //!< Others: Reserved + struct { + uint8_t bAutoFlushCrc:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushIgn:1; //!< If 1, automatically remove packets that can be ignored according to frame filtering from Rx queue + uint8_t bIncludePhyHdr:1; //!< If 1, include the received PHY header field in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendCorrCrc:1; //!< If 1, append a correlation value and CRC result byte to the packet in the Rx queue + uint8_t bAppendSrcInd:1; //!< If 1, append an index from the source matching algorithm + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; + dataQueue_t* pRxQ; //!< Pointer to receive queue + rfc_ieeeRxOutput_t *pOutput; //!< Pointer to output structure (NULL: Do not store results) + struct { + uint16_t frameFiltEn:1; //!< \brief 0: Disable frame filtering
+ //!< 1: Enable frame filtering + uint16_t frameFiltStop:1; //!< \brief 0: Receive all packets to the end
+ //!< 1: Stop receiving frame once frame filtering has caused the frame to be rejected. + uint16_t autoAckEn:1; //!< \brief 0: Disable auto ACK
+ //!< 1: Enable auto ACK. + uint16_t slottedAckEn:1; //!< \brief 0: Non-slotted ACK
+ //!< 1: Slotted ACK. + uint16_t autoPendEn:1; //!< \brief 0: Auto-pend disabled
+ //!< 1: Auto-pend enabled + uint16_t defaultPend:1; //!< The value of the pending data bit in auto ACK packets that are not subject to auto-pend + uint16_t bPendDataReqOnly:1; //!< \brief 0: Use auto-pend for any packet
+ //!< 1: Use auto-pend for data request packets only + uint16_t bPanCoord:1; //!< \brief 0: Device is not PAN coordinator
+ //!< 1: Device is PAN coordinator + uint16_t maxFrameVersion:2; //!< Reject frames where the frame version field in the FCF is greater than this value + uint16_t fcfReservedMask:3; //!< Value to be AND-ed with the reserved part of the FCF; frame rejected if result is non-zero + uint16_t modifyFtFilter:2; //!< \brief Treatment of MSB of frame type field before frame-type filtering:
+ //!< 0: No modification
+ //!< 1: Invert MSB
+ //!< 2: Set MSB to 0
+ //!< 3: Set MSB to 1 + uint16_t bStrictLenFilter:1; //!< \brief 0: Accept acknowledgement frames of any length >= 5
+ //!< 1: Accept only acknowledgement frames of length 5 + } frameFiltOpt; //!< Frame filtering options + struct { + uint8_t bAcceptFt0Beacon:1; //!< \brief Treatment of frames with frame type 000 (beacon):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt1Data:1; //!< \brief Treatment of frames with frame type 001 (data):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt2Ack:1; //!< \brief Treatment of frames with frame type 010 (ACK):
+ //!< 0: Reject, unless running ACK receive command
+ //!< 1: Always accept + uint8_t bAcceptFt3MacCmd:1; //!< \brief Treatment of frames with frame type 011 (MAC command):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt4Reserved:1; //!< \brief Treatment of frames with frame type 100 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt5Reserved:1; //!< \brief Treatment of frames with frame type 101 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt6Reserved:1; //!< \brief Treatment of frames with frame type 110 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt7Reserved:1; //!< \brief Treatment of frames with frame type 111 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + } frameTypes; //!< Frame types to receive in frame filtering + struct { + uint8_t ccaEnEnergy:1; //!< Enable energy scan as CCA source + uint8_t ccaEnCorr:1; //!< Enable correlator based carrier sense as CCA source + uint8_t ccaEnSync:1; //!< Enable sync found based carrier sense as CCA source + uint8_t ccaCorrOp:1; //!< \brief Operator to use between energy based and correlator based CCA
+ //!< 0: Report busy channel if either ccaEnergy or ccaCorr are busy
+ //!< 1: Report busy channel if both ccaEnergy and ccaCorr are busy + uint8_t ccaSyncOp:1; //!< \brief Operator to use between sync found based CCA and the others
+ //!< 0: Always report busy channel if ccaSync is busy
+ //!< 1: Always report idle channel if ccaSync is idle + uint8_t ccaCorrThr:2; //!< Threshold for number of correlation peaks in correlator based carrier sense + } ccaOpt; //!< CCA options + int8_t ccaRssiThr; //!< RSSI threshold for CCA + uint8_t __dummy0; + uint8_t numExtEntries; //!< Number of extended address entries + uint8_t numShortEntries; //!< Number of short address entries + uint32_t* pExtEntryList; //!< Pointer to list of extended address entries + rfc_shortAddrEntry_t *pShortEntryList;//!< Pointer to list of short address entries + uint64_t localExtAddr; //!< The extended address of the local device + uint16_t localShortAddr; //!< The short address of the local device + uint16_t localPanID; //!< The PAN ID of the local device + uint16_t __dummy1; + uint8_t __dummy2; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Rx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the Rx + //!< operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_ED_SCAN +//! @{ +#define CMD_IEEE_ED_SCAN 0x2802 +struct __RFC_STRUCT rfc_CMD_IEEE_ED_SCAN_s { + uint16_t commandNo; //!< The command ID number 0x2802 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to tune to in the start of the operation
+ //!< 0: Use existing channel
+ //!< 11–26: Use as IEEE 802.15.4 channel, i.e. frequency is (2405 + 5 × (channel - 11)) MHz
+ //!< 60–207: Frequency is (2300 + channel) MHz
+ //!< Others: Reserved + struct { + uint8_t ccaEnEnergy:1; //!< Enable energy scan as CCA source + uint8_t ccaEnCorr:1; //!< Enable correlator based carrier sense as CCA source + uint8_t ccaEnSync:1; //!< Enable sync found based carrier sense as CCA source + uint8_t ccaCorrOp:1; //!< \brief Operator to use between energy based and correlator based CCA
+ //!< 0: Report busy channel if either ccaEnergy or ccaCorr are busy
+ //!< 1: Report busy channel if both ccaEnergy and ccaCorr are busy + uint8_t ccaSyncOp:1; //!< \brief Operator to use between sync found based CCA and the others
+ //!< 0: Always report busy channel if ccaSync is busy
+ //!< 1: Always report idle channel if ccaSync is idle + uint8_t ccaCorrThr:2; //!< Threshold for number of correlation peaks in correlator based carrier sense + } ccaOpt; //!< CCA options + int8_t ccaRssiThr; //!< RSSI threshold for CCA + uint8_t __dummy0; + int8_t maxRssi; //!< The maximum RSSI recorded during the ED scan + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Rx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the Rx + //!< operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_TX +//! @{ +#define CMD_IEEE_TX 0x2C01 +struct __RFC_STRUCT rfc_CMD_IEEE_TX_s { + uint16_t commandNo; //!< The command ID number 0x2C01 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint8_t bIncludePhyHdr:1; //!< \brief 0: Find PHY header automatically
+ //!< 1: Insert PHY header from the buffer + uint8_t bIncludeCrc:1; //!< \brief 0: Append automatically calculated CRC
+ //!< 1: Insert FCS (CRC) from the buffer + uint8_t :1; + uint8_t payloadLenMsb:5; //!< \brief Most significant bits of payload length. Should only be non-zero to create long + //!< non-standard packets for test purposes + } txOpt; + uint8_t payloadLen; //!< Number of bytes in the payload + uint8_t* pPayload; //!< Pointer to payload buffer of size payloadLen + ratmr_t timeStamp; //!< Time stamp of transmitted frame +}; + +//! @} + +//! \addtogroup CMD_IEEE_CSMA +//! @{ +#define CMD_IEEE_CSMA 0x2C02 +struct __RFC_STRUCT rfc_CMD_IEEE_CSMA_s { + uint16_t commandNo; //!< The command ID number 0x2C02 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t randomState; //!< The state of the pseudo-random generator + uint8_t macMaxBE; //!< The IEEE 802.15.4 MAC parameter macMaxBE + uint8_t macMaxCSMABackoffs; //!< The IEEE 802.15.4 MAC parameter macMaxCSMABackoffs + struct { + uint8_t initCW:5; //!< The initialization value for the CW parameter + uint8_t bSlotted:1; //!< \brief 0: non-slotted CSMA
+ //!< 1: slotted CSMA + uint8_t rxOffMode:2; //!< \brief 0: RX stays on during CSMA backoffs
+ //!< 1: The CSMA-CA algorithm will suspend the receiver if no frame is being received
+ //!< 2: The CSMA-CA algorithm will suspend the receiver if no frame is being received, + //!< or after finishing it (including auto ACK) otherwise
+ //!< 3: The CSMA-CA algorithm will suspend the receiver immediately during back-offs + } csmaConfig; + uint8_t NB; //!< The NB parameter from the IEEE 802.15.4 CSMA-CA algorithm + uint8_t BE; //!< The BE parameter from the IEEE 802.15.4 CSMA-CA algorithm + uint8_t remainingPeriods; //!< The number of remaining periods from a paused backoff countdown + int8_t lastRssi; //!< RSSI measured at the last CCA operation + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the CSMA-CA operation + ratmr_t lastTimeStamp; //!< Time of the last CCA operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< CSMA-CA operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_RX_ACK +//! @{ +#define CMD_IEEE_RX_ACK 0x2C03 +struct __RFC_STRUCT rfc_CMD_IEEE_RX_ACK_s { + uint16_t commandNo; //!< The command ID number 0x2C03 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t seqNo; //!< Sequence number to expect + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to give up acknowledgement reception + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to give up + //!< acknowledgement reception +}; + +//! @} + +//! \addtogroup CMD_IEEE_ABORT_BG +//! @{ +#define CMD_IEEE_ABORT_BG 0x2C04 +struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_BG_s { + uint16_t commandNo; //!< The command ID number 0x2C04 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_IEEE_MOD_CCA +//! @{ +#define CMD_IEEE_MOD_CCA 0x2001 +struct __RFC_STRUCT rfc_CMD_IEEE_MOD_CCA_s { + uint16_t commandNo; //!< The command ID number 0x2001 + struct { + uint8_t ccaEnEnergy:1; //!< Enable energy scan as CCA source + uint8_t ccaEnCorr:1; //!< Enable correlator based carrier sense as CCA source + uint8_t ccaEnSync:1; //!< Enable sync found based carrier sense as CCA source + uint8_t ccaCorrOp:1; //!< \brief Operator to use between energy based and correlator based CCA
+ //!< 0: Report busy channel if either ccaEnergy or ccaCorr are busy
+ //!< 1: Report busy channel if both ccaEnergy and ccaCorr are busy + uint8_t ccaSyncOp:1; //!< \brief Operator to use between sync found based CCA and the others
+ //!< 0: Always report busy channel if ccaSync is busy
+ //!< 1: Always report idle channel if ccaSync is idle + uint8_t ccaCorrThr:2; //!< Threshold for number of correlation peaks in correlator based carrier sense + } newCcaOpt; //!< New value of ccaOpt for the running background level operation + int8_t newCcaRssiThr; //!< New value of ccaRssiThr for the running background level operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_MOD_FILT +//! @{ +#define CMD_IEEE_MOD_FILT 0x2002 +struct __RFC_STRUCT rfc_CMD_IEEE_MOD_FILT_s { + uint16_t commandNo; //!< The command ID number 0x2002 + struct { + uint16_t frameFiltEn:1; //!< \brief 0: Disable frame filtering
+ //!< 1: Enable frame filtering + uint16_t frameFiltStop:1; //!< \brief 0: Receive all packets to the end
+ //!< 1: Stop receiving frame once frame filtering has caused the frame to be rejected. + uint16_t autoAckEn:1; //!< \brief 0: Disable auto ACK
+ //!< 1: Enable auto ACK. + uint16_t slottedAckEn:1; //!< \brief 0: Non-slotted ACK
+ //!< 1: Slotted ACK. + uint16_t autoPendEn:1; //!< \brief 0: Auto-pend disabled
+ //!< 1: Auto-pend enabled + uint16_t defaultPend:1; //!< The value of the pending data bit in auto ACK packets that are not subject to auto-pend + uint16_t bPendDataReqOnly:1; //!< \brief 0: Use auto-pend for any packet
+ //!< 1: Use auto-pend for data request packets only + uint16_t bPanCoord:1; //!< \brief 0: Device is not PAN coordinator
+ //!< 1: Device is PAN coordinator + uint16_t maxFrameVersion:2; //!< Reject frames where the frame version field in the FCF is greater than this value + uint16_t fcfReservedMask:3; //!< Value to be AND-ed with the reserved part of the FCF; frame rejected if result is non-zero + uint16_t modifyFtFilter:2; //!< \brief Treatment of MSB of frame type field before frame-type filtering:
+ //!< 0: No modification
+ //!< 1: Invert MSB
+ //!< 2: Set MSB to 0
+ //!< 3: Set MSB to 1 + uint16_t bStrictLenFilter:1; //!< \brief 0: Accept acknowledgement frames of any length >= 5
+ //!< 1: Accept only acknowledgement frames of length 5 + } newFrameFiltOpt; //!< New value of frameFiltOpt for the running background level operation + struct { + uint8_t bAcceptFt0Beacon:1; //!< \brief Treatment of frames with frame type 000 (beacon):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt1Data:1; //!< \brief Treatment of frames with frame type 001 (data):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt2Ack:1; //!< \brief Treatment of frames with frame type 010 (ACK):
+ //!< 0: Reject, unless running ACK receive command
+ //!< 1: Always accept + uint8_t bAcceptFt3MacCmd:1; //!< \brief Treatment of frames with frame type 011 (MAC command):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt4Reserved:1; //!< \brief Treatment of frames with frame type 100 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt5Reserved:1; //!< \brief Treatment of frames with frame type 101 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt6Reserved:1; //!< \brief Treatment of frames with frame type 110 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt7Reserved:1; //!< \brief Treatment of frames with frame type 111 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + } newFrameTypes; //!< New value of frameTypes for the running background level operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_MOD_SRC_MATCH +//! @{ +#define CMD_IEEE_MOD_SRC_MATCH 0x2003 +struct __RFC_STRUCT rfc_CMD_IEEE_MOD_SRC_MATCH_s { + uint16_t commandNo; //!< The command ID number 0x2003 + struct { + uint8_t bEnable:1; //!< \brief 0: Disable entry
+ //!< 1: Enable entry + uint8_t srcPend:1; //!< New value of the pending bit for the entry + uint8_t entryType:1; //!< \brief 0: Extended address
+ //!< 1: Short address + } options; + uint8_t entryNo; //!< Index of entry to enable or disable +}; + +//! @} + +//! \addtogroup CMD_IEEE_ABORT_FG +//! @{ +#define CMD_IEEE_ABORT_FG 0x2401 +struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_FG_s { + uint16_t commandNo; //!< The command ID number 0x2401 +}; + +//! @} + +//! \addtogroup CMD_IEEE_STOP_FG +//! @{ +#define CMD_IEEE_STOP_FG 0x2402 +struct __RFC_STRUCT rfc_CMD_IEEE_STOP_FG_s { + uint16_t commandNo; //!< The command ID number 0x2402 +}; + +//! @} + +//! \addtogroup CMD_IEEE_CCA_REQ +//! @{ +#define CMD_IEEE_CCA_REQ 0x2403 +struct __RFC_STRUCT rfc_CMD_IEEE_CCA_REQ_s { + uint16_t commandNo; //!< The command ID number 0x2403 + int8_t currentRssi; //!< The RSSI currently observed on the channel + int8_t maxRssi; //!< The maximum RSSI observed on the channel since Rx was started + struct { + uint8_t ccaState:2; //!< \brief Value of the current CCA state
+ //!< 0: Idle
+ //!< 1: Busy
+ //!< 2: Invalid + uint8_t ccaEnergy:2; //!< \brief Value of the current energy detect CCA state
+ //!< 0: Idle
+ //!< 1: Busy
+ //!< 2: Invalid + uint8_t ccaCorr:2; //!< \brief Value of the current correlator based carrier sense CCA state
+ //!< 0: Idle
+ //!< 1: Busy
+ //!< 2: Invalid + uint8_t ccaSync:1; //!< \brief Value of the current sync found based carrier sense CCA state
+ //!< 0: Idle
+ //!< 1: Busy + } ccaInfo; +}; + +//! @} + +//! \addtogroup ieeeRxOutput +//! @{ +//! Output structure for CMD_IEEE_RX + +struct __RFC_STRUCT rfc_ieeeRxOutput_s { + uint8_t nTxAck; //!< Total number of transmitted ACK frames + uint8_t nRxBeacon; //!< Number of received beacon frames + uint8_t nRxData; //!< Number of received data frames + uint8_t nRxAck; //!< Number of received acknowledgement frames + uint8_t nRxMacCmd; //!< Number of received MAC command frames + uint8_t nRxReserved; //!< Number of received frames with reserved frame type + uint8_t nRxNok; //!< Number of received frames with CRC error + uint8_t nRxIgnored; //!< Number of frames received that are to be ignored + uint8_t nRxBufFull; //!< Number of received frames discarded because the Rx buffer was full + int8_t lastRssi; //!< RSSI of last received frame + int8_t maxRssi; //!< Highest RSSI observed in the operation + uint8_t __dummy0; + ratmr_t beaconTimeStamp; //!< Time stamp of last received beacon frame +}; + +//! @} + +//! \addtogroup shortAddrEntry +//! @{ +//! Structure for short address entries + +struct __RFC_STRUCT rfc_shortAddrEntry_s { + uint16_t shortAddr; //!< Short address + uint16_t panId; //!< PAN ID +}; + +//! @} + +//! \addtogroup ieeeRxCorrCrc +//! @{ +//! Receive status byte that may be appended to message in receive buffer + +struct __RFC_STRUCT rfc_ieeeRxCorrCrc_s { + struct { + uint8_t corr:6; //!< The correlation value + uint8_t bIgnore:1; //!< 1 if the packet should be rejected by frame filtering, 0 otherwise + uint8_t bCrcErr:1; //!< 1 if the packet was received with CRC error, 0 otherwise + } status; +}; + +//! @} + +//! @} +//! @} +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ieee_cmd_field.h b/cpu/cc26xx/dev/rfc-api/ieee_cmd_field.h new file mode 100755 index 000000000..149940f79 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ieee_cmd_field.h @@ -0,0 +1,403 @@ +/****************************************************************************** +* Filename: ieee_cmd_field.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for IEEE 802.15.4 commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef __IEEE_CMD_FIELD_H +#define __IEEE_CMD_FIELD_H + +#include +#include "mailbox.h" +#include "common_cmd.h" + +#define _POSITION_CMD_IEEE_RX_channel 14 +#define _TYPE_CMD_IEEE_RX_channel uint8_t +#define _POSITION_CMD_IEEE_RX_rxConfig 15 +#define _TYPE_CMD_IEEE_RX_rxConfig uint8_t +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAutoFlushCrc 0 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAutoFlushCrc 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAutoFlushIgn 1 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAutoFlushIgn 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bIncludePhyHdr 2 +#define _NBITS_CMD_IEEE_RX_rxConfig_bIncludePhyHdr 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bIncludeCrc 3 +#define _NBITS_CMD_IEEE_RX_rxConfig_bIncludeCrc 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendRssi 4 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendRssi 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendCorrCrc 5 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendCorrCrc 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendSrcInd 6 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendSrcInd 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendTimestamp 7 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendTimestamp 1 +#define _POSITION_CMD_IEEE_RX_pRxQ 16 +#define _TYPE_CMD_IEEE_RX_pRxQ dataQueue_t* +#define _POSITION_CMD_IEEE_RX_pOutput 20 +#define _TYPE_CMD_IEEE_RX_pOutput uint8_t* +#define _POSITION_CMD_IEEE_RX_frameFiltOpt 24 +#define _TYPE_CMD_IEEE_RX_frameFiltOpt uint16_t +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_frameFiltEn 0 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_frameFiltEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_frameFiltStop 1 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_frameFiltStop 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_autoAckEn 2 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_autoAckEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_slottedAckEn 3 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_slottedAckEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_autoPendEn 4 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_autoPendEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_defaultPend 5 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_defaultPend 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_bPendDataReqOnly 6 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_bPendDataReqOnly 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_bPanCoord 7 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_bPanCoord 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_maxFrameVersion 8 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_maxFrameVersion 2 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_fcfReservedMask 10 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_fcfReservedMask 3 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_modifyFtFilter 13 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_modifyFtFilter 2 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_bStrictLenFilter 15 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_bStrictLenFilter 1 +#define _POSITION_CMD_IEEE_RX_frameTypes 26 +#define _TYPE_CMD_IEEE_RX_frameTypes uint8_t +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt0Beacon 0 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt0Beacon 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt1Data 1 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt1Data 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt2Ack 2 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt2Ack 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt3MacCmd 3 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt3MacCmd 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt4Reserved 4 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt4Reserved 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt5Reserved 5 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt5Reserved 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt6Reserved 6 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt6Reserved 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt7Reserved 7 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt7Reserved 1 +#define _POSITION_CMD_IEEE_RX_ccaOpt 27 +#define _TYPE_CMD_IEEE_RX_ccaOpt uint8_t +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaEnEnergy 0 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaEnEnergy 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaEnCorr 1 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaEnCorr 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaEnSync 2 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaEnSync 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaCorrOp 3 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaCorrOp 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaSyncOp 4 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaSyncOp 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaCorrThr 5 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaCorrThr 2 +#define _POSITION_CMD_IEEE_RX_ccaRssiThr 28 +#define _TYPE_CMD_IEEE_RX_ccaRssiThr int8_t +#define _POSITION_CMD_IEEE_RX_numExtEntries 30 +#define _TYPE_CMD_IEEE_RX_numExtEntries uint8_t +#define _POSITION_CMD_IEEE_RX_numShortEntries 31 +#define _TYPE_CMD_IEEE_RX_numShortEntries uint8_t +#define _POSITION_CMD_IEEE_RX_pExtEntryList 32 +#define _TYPE_CMD_IEEE_RX_pExtEntryList uint32_t* +#define _POSITION_CMD_IEEE_RX_pShortEntryList 36 +#define _TYPE_CMD_IEEE_RX_pShortEntryList uint32_t* +#define _POSITION_CMD_IEEE_RX_localExtAddr 40 +#define _TYPE_CMD_IEEE_RX_localExtAddr uint64_t +#define _POSITION_CMD_IEEE_RX_localShortAddr 48 +#define _TYPE_CMD_IEEE_RX_localShortAddr uint16_t +#define _POSITION_CMD_IEEE_RX_localPanID 50 +#define _TYPE_CMD_IEEE_RX_localPanID uint16_t +#define _POSITION_CMD_IEEE_RX_endTrigger 55 +#define _TYPE_CMD_IEEE_RX_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_RX_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_RX_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_RX_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_RX_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_RX_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_RX_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_RX_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_RX_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_RX_endTime 56 +#define _TYPE_CMD_IEEE_RX_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_RX 60 + +#define _POSITION_CMD_IEEE_ED_SCAN_channel 14 +#define _TYPE_CMD_IEEE_ED_SCAN_channel uint8_t +#define _POSITION_CMD_IEEE_ED_SCAN_ccaOpt 15 +#define _TYPE_CMD_IEEE_ED_SCAN_ccaOpt uint8_t +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnEnergy 0 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnEnergy 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnCorr 1 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnCorr 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnSync 2 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnSync 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrOp 3 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrOp 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaSyncOp 4 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaSyncOp 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrThr 5 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrThr 2 +#define _POSITION_CMD_IEEE_ED_SCAN_ccaRssiThr 16 +#define _TYPE_CMD_IEEE_ED_SCAN_ccaRssiThr int8_t +#define _POSITION_CMD_IEEE_ED_SCAN_maxRssi 18 +#define _TYPE_CMD_IEEE_ED_SCAN_maxRssi int8_t +#define _POSITION_CMD_IEEE_ED_SCAN_endTrigger 19 +#define _TYPE_CMD_IEEE_ED_SCAN_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_ED_SCAN_endTime 20 +#define _TYPE_CMD_IEEE_ED_SCAN_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_ED_SCAN 24 + +#define _POSITION_CMD_IEEE_TX_txOpt 14 +#define _TYPE_CMD_IEEE_TX_txOpt uint8_t +#define _BITPOS_CMD_IEEE_TX_txOpt_bIncludePhyHdr 0 +#define _NBITS_CMD_IEEE_TX_txOpt_bIncludePhyHdr 1 +#define _BITPOS_CMD_IEEE_TX_txOpt_bIncludeCrc 1 +#define _NBITS_CMD_IEEE_TX_txOpt_bIncludeCrc 1 +#define _BITPOS_CMD_IEEE_TX_txOpt_payloadLenMsb 3 +#define _NBITS_CMD_IEEE_TX_txOpt_payloadLenMsb 5 +#define _POSITION_CMD_IEEE_TX_payloadLen 15 +#define _TYPE_CMD_IEEE_TX_payloadLen uint8_t +#define _POSITION_CMD_IEEE_TX_pPayload 16 +#define _TYPE_CMD_IEEE_TX_pPayload uint8_t* +#define _POSITION_CMD_IEEE_TX_timeStamp 20 +#define _TYPE_CMD_IEEE_TX_timeStamp ratmr_t +#define _SIZEOF_CMD_IEEE_TX 24 + +#define _POSITION_CMD_IEEE_CSMA_randomState 14 +#define _TYPE_CMD_IEEE_CSMA_randomState uint16_t +#define _POSITION_CMD_IEEE_CSMA_macMaxBE 16 +#define _TYPE_CMD_IEEE_CSMA_macMaxBE uint8_t +#define _POSITION_CMD_IEEE_CSMA_macMaxCSMABackoffs 17 +#define _TYPE_CMD_IEEE_CSMA_macMaxCSMABackoffs uint8_t +#define _POSITION_CMD_IEEE_CSMA_csmaConfig 18 +#define _TYPE_CMD_IEEE_CSMA_csmaConfig uint8_t +#define _BITPOS_CMD_IEEE_CSMA_csmaConfig_initCW 0 +#define _NBITS_CMD_IEEE_CSMA_csmaConfig_initCW 5 +#define _BITPOS_CMD_IEEE_CSMA_csmaConfig_bSlotted 5 +#define _NBITS_CMD_IEEE_CSMA_csmaConfig_bSlotted 1 +#define _BITPOS_CMD_IEEE_CSMA_csmaConfig_rxOffMode 6 +#define _NBITS_CMD_IEEE_CSMA_csmaConfig_rxOffMode 2 +#define _POSITION_CMD_IEEE_CSMA_NB 19 +#define _TYPE_CMD_IEEE_CSMA_NB uint8_t +#define _POSITION_CMD_IEEE_CSMA_BE 20 +#define _TYPE_CMD_IEEE_CSMA_BE uint8_t +#define _POSITION_CMD_IEEE_CSMA_remainingPeriods 21 +#define _TYPE_CMD_IEEE_CSMA_remainingPeriods uint8_t +#define _POSITION_CMD_IEEE_CSMA_lastRssi 22 +#define _TYPE_CMD_IEEE_CSMA_lastRssi int8_t +#define _POSITION_CMD_IEEE_CSMA_endTrigger 23 +#define _TYPE_CMD_IEEE_CSMA_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_CSMA_lastTimeStamp 24 +#define _TYPE_CMD_IEEE_CSMA_lastTimeStamp ratmr_t +#define _POSITION_CMD_IEEE_CSMA_endTime 28 +#define _TYPE_CMD_IEEE_CSMA_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_CSMA 32 + +#define _POSITION_CMD_IEEE_RX_ACK_seqNo 14 +#define _TYPE_CMD_IEEE_RX_ACK_seqNo uint8_t +#define _POSITION_CMD_IEEE_RX_ACK_endTrigger 15 +#define _TYPE_CMD_IEEE_RX_ACK_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_RX_ACK_endTime 16 +#define _TYPE_CMD_IEEE_RX_ACK_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_RX_ACK 20 + +#define _SIZEOF_CMD_IEEE_ABORT_BG 14 + +#define _POSITION_CMD_IEEE_MOD_CCA_newCcaOpt 2 +#define _TYPE_CMD_IEEE_MOD_CCA_newCcaOpt uint8_t +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnEnergy 0 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnEnergy 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnCorr 1 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnCorr 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnSync 2 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnSync 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrOp 3 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrOp 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaSyncOp 4 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaSyncOp 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrThr 5 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrThr 2 +#define _POSITION_CMD_IEEE_MOD_CCA_newCcaRssiThr 3 +#define _TYPE_CMD_IEEE_MOD_CCA_newCcaRssiThr int8_t +#define _SIZEOF_CMD_IEEE_MOD_CCA 4 + +#define _POSITION_CMD_IEEE_MOD_FILT_newFrameFiltOpt 2 +#define _TYPE_CMD_IEEE_MOD_FILT_newFrameFiltOpt uint16_t +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltEn 0 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltStop 1 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltStop 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoAckEn 2 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoAckEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_slottedAckEn 3 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_slottedAckEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoPendEn 4 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoPendEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_defaultPend 5 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_defaultPend 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPendDataReqOnly 6 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPendDataReqOnly 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPanCoord 7 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPanCoord 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_maxFrameVersion 8 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_maxFrameVersion 2 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_fcfReservedMask 10 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_fcfReservedMask 3 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_modifyFtFilter 13 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_modifyFtFilter 2 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bStrictLenFilter 15 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bStrictLenFilter 1 +#define _POSITION_CMD_IEEE_MOD_FILT_newFrameTypes 4 +#define _TYPE_CMD_IEEE_MOD_FILT_newFrameTypes uint8_t +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt0Beacon 0 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt0Beacon 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt1Data 1 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt1Data 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt2Ack 2 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt2Ack 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt3MacCmd 3 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt3MacCmd 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt4Reserved 4 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt4Reserved 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt5Reserved 5 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt5Reserved 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt6Reserved 6 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt6Reserved 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt7Reserved 7 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt7Reserved 1 +#define _SIZEOF_CMD_IEEE_MOD_FILT 5 + +#define _POSITION_CMD_IEEE_MOD_SRC_MATCH_options 2 +#define _TYPE_CMD_IEEE_MOD_SRC_MATCH_options uint8_t +#define _BITPOS_CMD_IEEE_MOD_SRC_MATCH_options_bEnable 0 +#define _NBITS_CMD_IEEE_MOD_SRC_MATCH_options_bEnable 1 +#define _BITPOS_CMD_IEEE_MOD_SRC_MATCH_options_srcPend 1 +#define _NBITS_CMD_IEEE_MOD_SRC_MATCH_options_srcPend 1 +#define _BITPOS_CMD_IEEE_MOD_SRC_MATCH_options_entryType 2 +#define _NBITS_CMD_IEEE_MOD_SRC_MATCH_options_entryType 1 +#define _POSITION_CMD_IEEE_MOD_SRC_MATCH_entryNo 3 +#define _TYPE_CMD_IEEE_MOD_SRC_MATCH_entryNo uint8_t +#define _SIZEOF_CMD_IEEE_MOD_SRC_MATCH 4 + +#define _SIZEOF_CMD_IEEE_ABORT_FG 2 + +#define _SIZEOF_CMD_IEEE_STOP_FG 2 + +#define _POSITION_CMD_IEEE_CCA_REQ_currentRssi 2 +#define _TYPE_CMD_IEEE_CCA_REQ_currentRssi int8_t +#define _POSITION_CMD_IEEE_CCA_REQ_maxRssi 3 +#define _TYPE_CMD_IEEE_CCA_REQ_maxRssi int8_t +#define _POSITION_CMD_IEEE_CCA_REQ_ccaInfo 4 +#define _TYPE_CMD_IEEE_CCA_REQ_ccaInfo uint8_t +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaState 0 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaState 2 +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaEnergy 2 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaEnergy 2 +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaCorr 4 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaCorr 2 +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaSync 6 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaSync 1 +#define _SIZEOF_CMD_IEEE_CCA_REQ 5 + +#define _POSITION_ieeeRxOutput_nTxAck 0 +#define _TYPE_ieeeRxOutput_nTxAck uint8_t +#define _POSITION_ieeeRxOutput_nRxBeacon 1 +#define _TYPE_ieeeRxOutput_nRxBeacon uint8_t +#define _POSITION_ieeeRxOutput_nRxData 2 +#define _TYPE_ieeeRxOutput_nRxData uint8_t +#define _POSITION_ieeeRxOutput_nRxAck 3 +#define _TYPE_ieeeRxOutput_nRxAck uint8_t +#define _POSITION_ieeeRxOutput_nRxMacCmd 4 +#define _TYPE_ieeeRxOutput_nRxMacCmd uint8_t +#define _POSITION_ieeeRxOutput_nRxReserved 5 +#define _TYPE_ieeeRxOutput_nRxReserved uint8_t +#define _POSITION_ieeeRxOutput_nRxNok 6 +#define _TYPE_ieeeRxOutput_nRxNok uint8_t +#define _POSITION_ieeeRxOutput_nRxIgnored 7 +#define _TYPE_ieeeRxOutput_nRxIgnored uint8_t +#define _POSITION_ieeeRxOutput_nRxBufFull 8 +#define _TYPE_ieeeRxOutput_nRxBufFull uint8_t +#define _POSITION_ieeeRxOutput_lastRssi 9 +#define _TYPE_ieeeRxOutput_lastRssi int8_t +#define _POSITION_ieeeRxOutput_maxRssi 10 +#define _TYPE_ieeeRxOutput_maxRssi int8_t +#define _POSITION_ieeeRxOutput_beaconTimeStamp 12 +#define _TYPE_ieeeRxOutput_beaconTimeStamp ratmr_t +#define _SIZEOF_ieeeRxOutput 16 + +#define _POSITION_shortAddrEntry_shortAddr 0 +#define _TYPE_shortAddrEntry_shortAddr uint16_t +#define _POSITION_shortAddrEntry_panId 2 +#define _TYPE_shortAddrEntry_panId uint16_t +#define _SIZEOF_shortAddrEntry 4 + +#define _POSITION_ieeeRxCorrCrc_status 0 +#define _TYPE_ieeeRxCorrCrc_status uint8_t +#define _BITPOS_ieeeRxCorrCrc_status_corr 0 +#define _NBITS_ieeeRxCorrCrc_status_corr 6 +#define _BITPOS_ieeeRxCorrCrc_status_bIgnore 6 +#define _NBITS_ieeeRxCorrCrc_status_bIgnore 1 +#define _BITPOS_ieeeRxCorrCrc_status_bCrcErr 7 +#define _NBITS_ieeeRxCorrCrc_status_bCrcErr 1 +#define _SIZEOF_ieeeRxCorrCrc 1 + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ieee_mailbox.h b/cpu/cc26xx/dev/rfc-api/ieee_mailbox.h new file mode 100644 index 000000000..772c4c219 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ieee_mailbox.h @@ -0,0 +1,107 @@ +/****************************************************************************** +* Filename: ieee_mailbox.h +* Revised: $ $ +* Revision: $ $ +* +* Description: Definitions for IEEE 802.15.4 interface +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef _IEEE_MAILBOX_H +#define _IEEE_MAILBOX_H + +#include "mailbox.h" + +/// \name CPE interrupt definitions for IEEE 802.15.4 +/// Interrupt masks for the CPE interrupt in RDBELL. These are new names for interrupts in mailbox.h, +/// used for compartibility with previous versions with separate interrupt numbers. +///@{ +#define IRQN_IEEE_BG_COMMAND_SUSPENDED IRQN_BG_COMMAND_SUSPENDED +#define IRQN_IEEE_TX_FRAME IRQN_TX_DONE +#define IRQN_IEEE_TX_ACK IRQN_TX_ACK + +#define IRQN_IEEE_RX_FRAME IRQN_RX_OK +#define IRQN_IEEE_RX_NOK IRQN_RX_NOK +#define IRQN_IEEE_RX_IGNORED IRQN_RX_IGNORED +#define IRQN_IEEE_RX_BUF_FULL IRQN_RX_BUF_FULL +#define IRQN_IEEE_RX_ENTRY_DONE IRQN_RX_ENTRY_DONE + +#define IRQ_IEEE_BG_COMMAND_SUSPENDED (1U << IRQN_IEEE_BG_COMMAND_SUSPENDED) +#define IRQ_IEEE_TX_FRAME (1U << IRQN_IEEE_TX_FRAME) +#define IRQ_IEEE_TX_ACK (1U << IRQN_IEEE_TX_ACK) +#define IRQ_IEEE_RX_FRAME (1U << IRQN_IEEE_RX_FRAME) +#define IRQ_IEEE_RX_NOK (1U << IRQN_IEEE_RX_NOK) +#define IRQ_IEEE_RX_IGNORED (1U << IRQN_IEEE_RX_IGNORED) +#define IRQ_IEEE_RX_BUF_FULL (1U << IRQN_IEEE_RX_BUF_FULL) +#define IRQ_IEEE_RX_ENTRY_DONE (1U << IRQN_IEEE_RX_ENTRY_DONE) +///@} + + + +/// \name Radio operation status +/// Radio operation status format: +/// Bits 15:12: Protocol +/// 0010: IEEE 802.15.4 +/// Bits 11:10: Type +/// 00: Not finished +/// 01: Done successfully +/// 10: Done with error +/// Bits 9:0: Identifier + +/// \name Operation not finished +///@{ +#define IEEE_SUSPENDED 0x2001 ///< Operation suspended +///@} +/// \name Operation finished normally +///@{ +#define IEEE_DONE_OK 0x2400 ///< Operation ended normally +#define IEEE_DONE_BUSY 0x2401 ///< CSMA-CA operation ended with failure +#define IEEE_DONE_STOPPED 0x2402 ///< Operation stopped after stop command +#define IEEE_DONE_ACK 0x2403 ///< ACK packet received with pending data bit cleared +#define IEEE_DONE_ACKPEND 0x2404 ///< ACK packet received with pending data bit set +#define IEEE_DONE_TIMEOUT 0x2405 ///< Operation ended due to timeout +#define IEEE_DONE_BGEND 0x2406 ///< FG operation ended because necessary background level + ///< operation ended +#define IEEE_DONE_ABORT 0x2407 ///< Operation aborted by command +///@} +/// \name Operation finished with error +///@{ +#define IEEE_ERROR_PAR 0x2800 ///< Illegal parameter +#define IEEE_ERROR_NO_SETUP 0x2801 ///< Operation using Rx or Tx attemted when not in 15.4 mode +#define IEEE_ERROR_NO_FS 0x2802 ///< Operation using Rx or Tx attemted without frequency synth configured +#define IEEE_ERROR_SYNTH_PROG 0x2803 ///< Synthesizer programming failed to complete on time +#define IEEE_ERROR_RXOVF 0x2804 ///< Receiver overflowed during operation +#define IEEE_ERROR_TXUNF 0x2805 ///< Transmitter underflowed during operation +///@} +///@} + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/mailbox.h b/cpu/cc26xx/dev/rfc-api/mailbox.h new file mode 100644 index 000000000..b11d72f08 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/mailbox.h @@ -0,0 +1,580 @@ +/****************************************************************************** +* Filename: mailbox.h +* Revised: $ $ +* Revision: $ $ +* +* Description: Definitions for interface between system and radio CPU +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 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. +* +* Neither the name of Texas Instruments Incorporated 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 +* OWNER 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. +* +******************************************************************************/ + +#ifndef _MAILBOX_H +#define _MAILBOX_H + +#include +#include + +/// Type definition for RAT +typedef uint32_t ratmr_t; + + + +/// Type definition for a data queue +typedef struct { + uint8_t *pCurrEntry; ///< Pointer to the data queue entry to be used, NULL for an empty queue + uint8_t *pLastEntry; ///< Pointer to the last entry in the queue, NULL for a circular queue +} dataQueue_t; + + + +/// \name CPE interrupt definitions +/// Interrupt masks for the CPE interrupt in RDBELL. +///@{ +#define IRQN_COMMAND_DONE 0 ///< Radio operation command finished +#define IRQN_LAST_COMMAND_DONE 1 ///< Last radio operation command in a chain finished +#define IRQN_FG_COMMAND_DONE 2 ///< FG level Radio operation command finished +#define IRQN_LAST_FG_COMMAND_DONE 3 ///< Last FG level radio operation command in a chain finished +#define IRQN_TX_DONE 4 ///< Packet transmitted +#define IRQN_TX_ACK 5 ///< ACK packet transmitted +#define IRQN_TX_CTRL 6 ///< Control packet transmitted +#define IRQN_TX_CTRL_ACK 7 ///< Acknowledgement received on a transmitted control packet +#define IRQN_TX_CTRL_ACK_ACK 8 ///< Acknowledgement received on a transmitted control packet, and acknowledgement transmitted for that packet +#define IRQN_TX_RETRANS 9 ///< Packet retransmitted +#define IRQN_TX_ENTRY_DONE 10 ///< Tx queue data entry state changed to Finished +#define IRQN_TX_BUFFER_CHANGED 11 ///< A buffer change is complete +#define IRQN_BG_COMMAND_SUSPENDED 12 ///< A background level radio operation command has been suspended +#define IRQN_RX_OK 16 ///< Packet received with CRC OK, payload, and not to be ignored +#define IRQN_RX_NOK 17 ///< Packet received with CRC error +#define IRQN_RX_IGNORED 18 ///< Packet received with CRC OK, but to be ignored +#define IRQN_RX_EMPTY 19 ///< Packet received with CRC OK, not to be ignored, no payload +#define IRQN_RX_CTRL 20 ///< Control packet received with CRC OK, not to be ignored +#define IRQN_RX_CTRL_ACK 21 ///< Control packet received with CRC OK, not to be ignored, then ACK sent +#define IRQN_RX_BUF_FULL 22 ///< Packet received that did not fit in the Rx queue +#define IRQN_RX_ENTRY_DONE 23 ///< Rx queue data entry changing state to Finished +#define IRQN_RX_DATA_WRITTEN 24 ///< Data written to partial read Rx buffer +#define IRQN_RX_N_DATA_WRITTEN 25 ///< Specified number of bytes written to partial read Rx buffer +#define IRQN_RX_ABORTED 26 ///< Packet reception stopped before packet was done +#define IRQN_SYNTH_NO_LOCK 28 ///< The synth has gone out of lock after calibration +#define IRQN_MODULES_UNLOCKED 29 ///< As part of the boot process, the CM0 has opened access to RF core modules and memories +#define IRQN_BOOT_DONE 30 ///< The RF core CPU boot is finished + +#define IRQN_INTERNAL_ERROR 31 ///< Internal error observed + +#define IRQ_COMMAND_DONE (1U << IRQN_COMMAND_DONE) +#define IRQ_LAST_COMMAND_DONE (1U << IRQN_LAST_COMMAND_DONE) +#define IRQ_FG_COMMAND_DONE (1U << IRQN_FG_COMMAND_DONE) +#define IRQ_LAST_FG_COMMAND_DONE (1U << IRQN_LAST_FG_COMMAND_DONE) + +#define IRQ_TX_DONE (1U << IRQN_TX_DONE) +#define IRQ_TX_ACK (1U << IRQN_TX_ACK) +#define IRQ_TX_CTRL (1U << IRQN_TX_CTRL) +#define IRQ_TX_CTRL_ACK (1U << IRQN_TX_CTRL_ACK) +#define IRQ_TX_CTRL_ACK_ACK (1U << IRQN_TX_CTRL_ACK_ACK) +#define IRQ_TX_RETRANS (1U << IRQN_TX_RETRANS) + +#define IRQ_TX_ENTRY_DONE (1U << IRQN_TX_ENTRY_DONE) +#define IRQ_TX_BUFFER_CHANGED (1U << IRQN_TX_BUFFER_CHANGED) + +#define IRQ_BG_COMMAND_SUSPENDED (1U << IRQN_BG_COMMAND_SUSPENDED) + +#define IRQ_RX_OK (1U << IRQN_RX_OK) +#define IRQ_RX_NOK (1U << IRQN_RX_NOK) +#define IRQ_RX_IGNORED (1U << IRQN_RX_IGNORED) +#define IRQ_RX_EMPTY (1U << IRQN_RX_EMPTY) +#define IRQ_RX_CTRL (1U << IRQN_RX_CTRL) +#define IRQ_RX_CTRL_ACK (1U << IRQN_RX_CTRL_ACK) +#define IRQ_RX_BUF_FULL (1U << IRQN_RX_BUF_FULL) +#define IRQ_RX_ENTRY_DONE (1U << IRQN_RX_ENTRY_DONE) +#define IRQ_RX_DATA_WRITTEN (1U << IRQN_RX_DATA_WRITTEN) +#define IRQ_RX_N_DATA_WRITTEN (1U << IRQN_RX_N_DATA_WRITTEN) +#define IRQ_RX_ABORTED (1U << IRQN_RX_ABORTED) + +#define IRQ_SYNTH_NO_LOCK (1U << IRQN_SYNTH_NO_LOCK) +#define IRQ_MODULES_UNLOCKED (1U << IRQN_MODULES_UNLOCKED) +#define IRQ_BOOT_DONE (1U << IRQN_BOOT_DONE) +#define IRQ_INTERNAL_ERROR (1U << IRQN_INTERNAL_ERROR) +///@} + + + +/// \name CMDSTA values +/// Values returned in result byte of CMDSTA +///@{ +#define CMDSTA_Pending 0x00 ///< The command has not yet been parsed +#define CMDSTA_Done 0x01 ///< Command successfully parsed + +#define CMDSTA_IllegalPointer 0x81 ///< The pointer signaled in CMDR is not valid +#define CMDSTA_UnknownCommand 0x82 ///< The command number in the command structure is unknown +#define CMDSTA_UnknownDirCommand 0x83 ///< The command number for a direct command is unknown, or the + ///< command is not a direct command +#define CMDSTA_ContextError 0x85 ///< An immediate or direct command was issued in a context + ///< where it is not supported +#define CMDSTA_SchedulingError 0x86 ///< A radio operation command was attempted to be scheduled + ///< while another operation was already running in the RF core +#define CMDSTA_ParError 0x87 ///< There were errors in the command parameters that are parsed + ///< on submission. +#define CMDSTA_QueueError 0x88 ///< An operation on a data entry queue was attempted that was + ///< not supported by the queue in its current state +#define CMDSTA_QueueBusy 0x89 ///< An operation on a data entry was attempted while that entry + ///< was busy +///@} + +/// \name Macros for use with command definition files +/// The script create_command.pl generates header files from command and structure definitions in the +/// *_def.txt files. These are the macros to access the definitions +///@{ + +/// Get a field from a structure +// +/// Gets a field from a structure defined in a _def.txt file. This may be used both in assignments and +/// references (e.g. GET_FIELD(pCmd1, CMD_TEST, testParam) = GET_FIELD(pCmd2, CMD_DUMMY, dummyParam);) +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD(ptr, cmd, field) \ +(*((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) + +/// Get a field from a structure, reading as volatile +// +/// Gets a field from a structure defined in a _def.txt file, reading it as a volatile parameter, which +/// takes into account that it may be changed by the other side. This may be used both in assignments and +/// references (e.g. GET_FIELD(pCmd1, CMD_TEST, testParam) = GET_FIELD(pCmd2, CMD_DUMMY, dummyParam);) +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD_V(ptr, cmd, field) \ +(*((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) + +/// Get the pointer to a field from a structure +// +/// Gets the pointer to a field from a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD_PTR(ptr, cmd, field) \ +((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field))) + +/// Get the volatile pointer to a field from a structure +// +/// Gets the volatile pointer to a field from a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD_VPTR(ptr, cmd, field) \ +((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field))) + +/// Get bits from a bit field +// +/// Returns bits from a bit field defined in a _def.txt file. +/// \param[in] value +/// The value of the entire field that contains the bit field +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITS(value, cmd, field, bitfield) \ +(((value) >> (_BITPOS_##cmd##_##field##_##bitfield)) & \ + ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) + +/// Get bits from a bit field as a signed value +// +/// Returns sign extended bits from a bit field defined in a _def.txt file. +/// \param[in] value +/// The value of the entire field that contains the bit field +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITS_S(value, cmd, field, bitfield) \ +(((int)(value) << (32 - ((_BITPOS_##cmd##_##field##_##bitfield) + (_NBITS_##cmd##_##field##_##bitfield)))) >> \ + (32 - (_NBITS_##cmd##_##field##_##bitfield))) + +/// Set bits in a bit field +// +/// Modifies a bit field defined in a _def.txt file. +/// \param[in,out] value +/// The value of the entire field that contains the bit field +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] bvalue +/// The value to set in the bitfield +/// +#define SET_BITS(value, cmd, field, bitfield, bvalue) \ +(((value) = ((value) & \ + (~(((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1) << (_BITPOS_##cmd##_##field##_##bitfield))) | \ + ((bvalue) << (_BITPOS_##cmd##_##field##_##bitfield))))) + + +/// Get bits from a bit field in a structure +// +/// Returns bits from a bit field in a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITFIELD(ptr, cmd, field, bitfield) \ +((*((_TYPE_##cmd##_##field *) ((((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) >> \ + ((_BITPOS_##cmd##_##field##_##bitfield))) & \ + ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) + +/// Get bits from a bit field in a structure, reading as volatile +// +/// Returns bits from a bit field in a structure defined in a _def.txt file, reading it as a +/// volatile parameter. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITFIELD_V(ptr, cmd, field, bitfield) \ +((*((volatile _TYPE_##cmd##_##field *) ((((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) >> \ + ((_BITPOS_##cmd##_##field##_##bitfield))) & \ + ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) + + +/// Set bits in a bit field in a structure +// +/// Modifies a bit field in a field in a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] value +/// The value to set in the bitfield +/// +#define SET_BITFIELD(ptr, cmd, field, bitfield, value) \ +((*((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) = \ + ((*((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) & \ + (~(((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1) << (_BITPOS_##cmd##_##field##_##bitfield))) | \ + (((uint32_t)(value)) << (_BITPOS_##cmd##_##field##_##bitfield)))) + +/// Set bits in a bit field in a structure, reading and writing as volatile +// +/// Modifies a bit field in a field in a structure defined in a _def.txt file, accessing it as a volatile +/// parameter. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] value +/// The value to set in the bitfield +/// +#define SET_BITFIELD_V(ptr, cmd, field, bitfield, value) \ +((*((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) = \ + ((*((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) & \ + (~(((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1) << (_BITPOS_##cmd##_##field##_##bitfield))) | \ + (((uint32_t)(value)) << (_BITPOS_##cmd##_##field##_##bitfield)))) + +/// Get the value of specific bifield in a field with the remaining bits set to 0 +// +/// Returns a bitfield so that the value of the full field can be obtained by bitwise +/// OR between these +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] value +/// The value to use in the bitfield +/// +#define BITVALUE(cmd, field, bitfield, value) \ +((((uint32_t)(value)) & ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) << \ + (_BITPOS_##cmd##_##field##_##bitfield)) + +/// Get the size of a structure +// +/// Gets the size of a structure defined in a _def.txt file. +/// +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// +#define SIZEOF_STRUCT(cmd) \ +(_SIZEOF_##cmd) + +/// Get the size of a radio operation command structure +// +/// Gets the size of a radio operation command structure defined in a _def.txt file. The difference from +/// SIZEOF_STRUCT is for legacy reasons only. +/// +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// +#define SIZEOF_RADIO_OP(cmd) \ +(_SIZEOF_##cmd) + +/// Initializes a structure to an initialization set +// +/// Sets the value of a structure to its given initialization values +/// \param[in] ptr +/// Pointer to the structure, must be word aligned +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] set +/// Index of the set of initializations to use +/// +#define INIT_STRUCT(ptr, cmd, set) \ +(memcpy(((uint32_t *)(ptr)) + (_START_INIT_WIDX_##cmd), (__init_##cmd[(set)]), \ + (_N_INIT_WORDS_##cmd) * sizeof(uint32_t))) + +///@} + + +/// \name Macros for sending direct commands +///@{ +/// Direct command with no parameter +#define CMDR_DIR_CMD(cmdId) (((cmdId) << 16) | 1) + +/// Direct command with 1-byte parameter +#define CMDR_DIR_CMD_1BYTE(cmdId, par) (((cmdId) << 16) | ((par) << 8) | 1) + +/// Direct command with 2-byte parameter +#define CMDR_DIR_CMD_2BYTE(cmdId, par) (((cmdId) << 16) | ((par) & 0xFFFC) | 1) + +///@} + + + +/// \name Definitions for trigger types +///@{ +#define TRIG_NOW 0 ///< Triggers immediately +#define TRIG_NEVER 1 ///< Never trigs +#define TRIG_ABSTIME 2 ///< Trigs at an absolute time +#define TRIG_REL_SUBMIT 3 ///< Trigs at a time relative to the command was submitted +#define TRIG_REL_START 4 ///< Trigs at a time relative to the command started +#define TRIG_REL_PREVSTART 5 ///< Trigs at a time relative to the previous command in the chain started +#define TRIG_REL_FIRSTSTART 6 ///< Trigs at a time relative to the first command in the chain started +#define TRIG_REL_PREVEND 7 ///< Trigs at a time relative to the previous command in the chain ended +#define TRIG_REL_EVT1 8 ///< Trigs at a time relative to the context defined "Event 1" +#define TRIG_REL_EVT2 9 ///< Trigs at a time relative to the context defined "Event 2" +#define TRIG_EXTERNAL 10 ///< Trigs at an external event to the radio timer +#define TRIG_PAST_BM 0x80 ///< Bitmask for setting pastTrig bit in order to trig immediately if + ///< trigger happened in the past +///@} + + +/// \name Definitions for conditional execution +///@{ +#define COND_ALWAYS 0 ///< Always run next command (except in case of Abort) +#define COND_NEVER 1 ///< Never run next command +#define COND_STOP_ON_FALSE 2 ///< Run next command if this command returned True, stop if it returned + ///< False +#define COND_STOP_ON_TRUE 3 ///< Stop if this command returned True, run next command if it returned + ///< False +#define COND_SKIP_ON_FALSE 4 ///< Run next command if this command returned True, skip a number of + ///< commands if it returned False +#define COND_SKIP_ON_TRUE 5 ///< Skip a number of commands if this command returned True, run next + ///< command if it returned False +///@} + + + +/// \name Radio operation status +/// Radio operation status format: +///@{ +/// \name Operation not finished +///@{ +#define IDLE 0x0000 ///< Operation not started +#define PENDING 0x0001 ///< Start of command is pending +#define ACTIVE 0x0002 ///< Running +#define SKIPPED 0x0003 ///< Operation skipped due to condition in another command +///@} +/// \name Operation finished normally +///@{ +#define DONE_OK 0x0400 ///< Operation ended normally +#define DONE_COUNTDOWN 0x0401 ///< Counter reached zero +#define DONE_RXERR 0x0402 ///< Operation ended with CRC error +#define DONE_TIMEOUT 0x0403 ///< Operation ended with timeout +#define DONE_STOPPED 0x0404 ///< Operation stopped after CMD_STOP command +#define DONE_ABORT 0x0405 ///< Operation aborted by CMD_ABORT command +#define DONE_FAILED 0x0406 ///< Scheduled immediate command failed +///@} +/// \name Operation finished with error +///@{ +#define ERROR_PAST_START 0x0800 ///< The start trigger occurred in the past +#define ERROR_START_TRIG 0x0801 ///< Illegal start trigger parameter +#define ERROR_CONDITION 0x0802 ///< Illegal condition for next operation +#define ERROR_PAR 0x0803 ///< Error in a command specific parameter +#define ERROR_POINTER 0x0804 ///< Invalid pointer to next operation +#define ERROR_CMDID 0x0805 ///< Next operation has a command ID that is undefined or not a radio + ///< operation command +#define ERROR_WRONG_BG 0x0806 ///< FG level command not compatible with running BG level command +#define ERROR_NO_SETUP 0x0807 ///< Operation using Rx or Tx attemted without CMD_RADIO_SETUP +#define ERROR_NO_FS 0x0808 ///< Operation using Rx or Tx attemted without frequency synth configured +#define ERROR_SYNTH_PROG 0x0809 ///< Synthesizer calibration failed +#define ERROR_TXUNF 0x080A ///< Tx underflow observed +#define ERROR_RXOVF 0x080B ///< Rx overflow observed +#define ERROR_NO_RX 0x080C ///< Attempted to access data from Rx when no such data was yet received +#define ERROR_PENDING 0x080D ///< Command submitted in the future with another command at different level pending +///@} +///@} + + +/// \name Data entry types +///@{ +#define DATA_ENTRY_TYPE_GEN 0 ///< General type: Tx entry or single element Rx entry +#define DATA_ENTRY_TYPE_MULTI 1 ///< Multi-element Rx entry type +#define DATA_ENTRY_TYPE_PTR 2 ///< Pointer entry type +#define DATA_ENTRY_TYPE_PARTIAL 3 ///< Partial read entry type +///@ + + +/// \name Data entry statuses +///@{ +#define DATA_ENTRY_PENDING 0 ///< Entry not yet used +#define DATA_ENTRY_ACTIVE 1 ///< Entry in use by radio CPU +#define DATA_ENTRY_BUSY 2 ///< Entry being updated +#define DATA_ENTRY_FINISHED 3 ///< Radio CPU is finished accessing the entry +#define DATA_ENTRY_UNFINISHED 4 ///< Radio CPU is finished accessing the entry, but packet could not be finished +///@} + +/// Difference between length and size of rxData field in multi-element Rx entry +#define DATA_ENTRY_MULTI_LEN_OFFSET (_POSITION_dataEntry_rxData - _POSITION_dataEntry_data) + + +/// \name Macros for RF register override +///@{ +/// Macro for ADI half-size value-mask combination +#define ADI_VAL_MASK(addr, mask, value) \ +(((addr) & 1) ? (((mask) & 0x0F) | (((value) & 0x0F) << 4)) : \ + ((((mask) & 0x0F) << 4) | ((value) & 0x0F))) +/// 32-bit write of 16-bit value +#define HW_REG_OVERRIDE(addr, val) ((((uintptr_t) (addr)) & 0xFFFC) | ((uint32_t)(val) << 16)) +/// ADI register, full-size write +#define ADI_REG_OVERRIDE(adiNo, addr, val) (2 | ((uint32_t)(val) << 16) | \ +(((addr) & 0x3F) << 24) | (((adiNo) ? 1U : 0) << 31)) +/// 2 ADI registers, full-size write +#define ADI_2REG_OVERRIDE(adiNo, addr, val, addr2, val2) \ +(2 | ((uint32_t)(val2) << 2) | (((addr2) & 0x3F) << 10) | ((uint32_t)(val) << 16) | \ +(((addr) & 0x3F) << 24) | (((adiNo) ? 1U : 0) << 31)) +/// ADI register, half-size read-modify-write +#define ADI_HALFREG_OVERRIDE(adiNo, addr, mask, val) (2 | (ADI_VAL_MASK(addr, mask, val) << 16) | \ +(((addr) & 0x3F) << 24) | (1U << 30) | (((adiNo) ? 1U : 0) << 31)) +/// 2 ADI registers, half-size read-modify-write +#define ADI_2HALFREG_OVERRIDE(adiNo, addr, mask, val, addr2, mask2, val2) \ +(2 | (ADI_VAL_MASK(addr2, mask2, val2) << 2) | (((addr2) & 0x3F) << 10) | \ +(ADI_VAL_MASK(addr, mask, val) << 16) | (((addr) & 0x3F) << 24) | (1U << 30) | (((adiNo) ? 1U : 0) << 31)) + +/// 16-bit SW register as defined in radio_par_def.txt +#define SW_REG_OVERRIDE(cmd, field, val) (3 | ((_POSITION_##cmd##_##field) << 4) | ((uint32_t)(val) << 16)) +/// SW register as defined in radio_par_def.txt with added index (for use with registers > 16 bits). +#define SW_REG_IND_OVERRIDE(cmd, field, offset, val) (3 | \ +(((_POSITION_##cmd##_##field) + ((offset) << 1)) << 4) | ((uint32_t)(val) << 16)) +/// 8-bit SW register as defined in radio_par_def.txt +#define SW_REG_BYTE_OVERRIDE(cmd, field, val) (0x8003 | ((_POSITION_##cmd##_##field) << 4) | \ +((uint32_t)(val) << 16)) +/// Two 8-bit SW registers as defined in radio_par_def.txt; the one given by field and the next byte. +#define SW_REG_2BYTE_OVERRIDE(cmd, field, val0, val1) (3 | (((_POSITION_##cmd##_##field) & 0xFFFE) << 4) | \ + (((uint32_t)(val0) << 16) & 0x00FF0000) | ((uint32_t)(val1) << 24)) +#define HW16_ARRAY_OVERRIDE(addr, length) (1 | (((uintptr_t) (addr)) & 0xFFFC) | ((uint32_t)(length) << 16)) +#define HW32_ARRAY_OVERRIDE(addr, length) (1 | (((uintptr_t) (addr)) & 0xFFFC) | \ +((uint32_t)(length) << 16) | (1U << 30)) +#define ADI_ARRAY_OVERRIDE(adiNo, addr, bHalfSize, length) (1 | ((((addr) & 0x3F) << 2)) | \ +((!!(bHalfSize)) << 8) | ((!!(adiNo)) << 9) | ((uint32_t)(length) << 16) | (2U << 30)) +#define SW_ARRAY_OVERRIDE(cmd, firstfield, length) (1 | (((_POSITION_##cmd##_##firstfield)) << 2) | \ +((uint32_t)(length) << 16) | (3U << 30)) +#define MCE_RFE_OVERRIDE(bMceRam, mceRomBank, mceMode, bRfeRam, rfeRomBank, rfeMode) \ + (7 | ((!!(bMceRam)) << 8) | (((mceRomBank) & 0x07) << 9) | ((!!(bRfeRam)) << 12) | (((rfeRomBank) & 0x07) << 13) | \ + (((mceMode) & 0x00FF) << 16) | (((rfeMode) & 0x00FF) << 24)) +#define BAW_OVERRIDE(freqOffset) (0x000B | ((freqOffset) << 16)) +#define NEW_OVERRIDE_SEGMENT(address) (((((uintptr_t)(address)) & 0x03FFFFFC) << 6) | 0x000F | \ + (((((uintptr_t)(address) >> 24) == 0x20) ? 0x01 : \ + (((uintptr_t)(address) >> 24) == 0x21) ? 0x02 : \ + (((uintptr_t)(address) >> 24) == 0xA0) ? 0x03 : \ + (((uintptr_t)(address) >> 24) == 0x00) ? 0x04 : \ + (((uintptr_t)(address) >> 24) == 0x10) ? 0x05 : \ + (((uintptr_t)(address) >> 24) == 0x11) ? 0x06 : \ + (((uintptr_t)(address) >> 24) == 0x40) ? 0x07 : \ + (((uintptr_t)(address) >> 24) == 0x50) ? 0x08 : \ + 0x09) << 4)) // Use illegal value for illegal address range +/// End of string for override register +#define END_OVERRIDE 0xFFFFFFFF + + +#define FWPAR_8BIT_ADDR(cmd, field) (0x1800 | (_POSITION_##cmd##_##field)) +#define FWPAR_16BIT_ADDR(cmd, field) (0x1000 | (_POSITION_##cmd##_##field)) +#define FWPAR_32BIT_ADDR(cmd, field) (0x0000 | (_POSITION_##cmd##_##field)) + +/// ADI address-value pair +#define ADI_ADDR_VAL(addr, value) ((((addr) & 0x7F) << 8) | ((value) & 0xFF)) +#define ADI_ADDR_VAL_MASK(addr, mask, value) ((((addr) & 0x7F) << 8) | ADI_VAL_MASK(addr, mask, value)) + +/// Low half-word +#define LOWORD(value) ((value) & 0xFFFF) +/// High half-word +#define HIWORD(value) ((value) >> 16) +///@} + + +#endif diff --git a/cpu/cc26xx/dev/uart1.h b/cpu/cc26xx/dev/uart1.h new file mode 100644 index 000000000..76dcdcdbe --- /dev/null +++ b/cpu/cc26xx/dev/uart1.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, 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-uart + * @{ + * + * \file + * This file really only exists because some examples rely on it. + * + * For instance, some examples do uart1_set_input(f). We re-write this to + * uart_set_input + */ +#ifndef UART1_H_ +#define UART1_H_ + +#include "dev/cc26xx-uart.h" + +#define BAUD2UBR(x) x +#define uart1_set_input(f) cc26xx_uart_set_input(f) + +#endif /* UART1_H_ */ + +/** @} */ diff --git a/cpu/cc26xx/fault-handlers.c b/cpu/cc26xx/fault-handlers.c new file mode 100644 index 000000000..48dd9f204 --- /dev/null +++ b/cpu/cc26xx/fault-handlers.c @@ -0,0 +1,54 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#include "inc/hw_types.h" +#include "inc/hw_memmap.h" +#include "inc/hw_cpu_scs.h" +/*---------------------------------------------------------------------------*/ +#define fault_handlers_hard_fault_isr FaultISR +/*---------------------------------------------------------------------------*/ +void +fault_handlers_hard_fault_isr(void) +{ + /* + * Workaround for (Im)precise Bus Faults caused under unknown circumstances, + * likely by access to RFC registers while the RF PD is off (which is + * something that should never happen because we do in fact check before + * accessing) + */ + if((HWREG(CPU_SCS_BASE + CPU_SCS_O_CFSR) == CPU_SCS_CFSR_IMPRECISERR) || + (HWREG(CPU_SCS_BASE + CPU_SCS_O_CFSR) & CPU_SCS_CFSR_PRECISERR)){ + /* ToDo: Check BFARVALID and then BFAR to filter down even further */ + return; + } + + while(1); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/ieee-addr.c b/cpu/cc26xx/ieee-addr.c new file mode 100644 index 000000000..1d70aff18 --- /dev/null +++ b/cpu/cc26xx/ieee-addr.c @@ -0,0 +1,90 @@ +/* + * 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-ieee-addr + * @{ + * + * \file + * Driver for the CC26xx IEEE addresses + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "net/linkaddr.h" +#include "ieee-addr.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +void +ieee_addr_cpy_to(uint8_t *dst, uint8_t len) +{ + if(IEEE_ADDR_CONF_HARDCODED) { + uint8_t ieee_addr_hc[8] = IEEE_ADDR_CONF_ADDRESS; + + memcpy(dst, &ieee_addr_hc[8 - len], len); + } else { + int i; + + /* Reading from primary location... */ + uint8_t *location = (uint8_t *)IEEE_ADDR_LOCATION_PRIMARY; + + /* + * ...unless we can find a byte != 0xFF in secondary + * + * Intentionally checking all 8 bytes here instead of len, because we + * are checking validity of the entire IEEE address irrespective of the + * actual number of bytes the caller wants to copy over. + */ + for(i = 0; i < 8; i++) { + if(((uint8_t *)IEEE_ADDR_LOCATION_SECONDARY)[i] != 0xFF) { + /* A byte in the secondary location is not 0xFF. Use the secondary */ + location = (uint8_t *)IEEE_ADDR_LOCATION_SECONDARY; + break; + } + } + + /* + * We have chosen what address to read the IEEE address from. Do so, + * inverting byte order + */ + for(i = 0; i < len; i++) { + dst[i] = location[len - 1 - i]; + } + } + +#if IEEE_ADDR_NODE_ID + dst[len - 1] = IEEE_ADDR_NODE_ID & 0xFF; + dst[len - 2] = IEEE_ADDR_NODE_ID >> 8; +#endif +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/ieee-addr.h b/cpu/cc26xx/ieee-addr.h new file mode 100644 index 000000000..3cd97d72a --- /dev/null +++ b/cpu/cc26xx/ieee-addr.h @@ -0,0 +1,105 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-ieee-addr CC26xx IEEE Address Control + * + * Driver for the retrieval of an IEEE address from flash + * + * The user can specify a hardcoded IEEE address through the + * IEEE_ADDR_CONF_HARDCODED configuration macro. + * + * If the user does not hard-code an address, then one will be read from either + * the primary location (InfoPage) or from the secondary location (on flash). + * + * In order to allow the user to easily program nodes with addresses, the + * secondary location is given priority: If it contains a valid address then + * it will be chosen in favour of the one on InfoPage. + * + * In this context, an address is valid if at least one of the 8 bytes does not + * equal 0xFF. If all 8 bytes are 0xFF, then the primary location will be used. + * + * In all cases, the address is assumed to be written little-endian. + * + * Lastly, it is possible to override the 2 LSB's of the address by using the + * NODE_ID make variable. + * @{ + * + * \file + * Header file with register and macro declarations for the cc26xx IEEE address + * driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef IEEE_ADDR_H_ +#define IEEE_ADDR_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \name IEEE address locations + * + * The address of the secondary location can be configured by the platform + * or example + * + * @{ + */ +#define IEEE_ADDR_LOCATION_PRIMARY 0x500012F0 /**< Primary IEEE address location */ + +#ifdef IEEE_ADDR_CONF_LOCATION_SECONDARY +#define IEEE_ADDR_LOCATION_SECONDARY IEEE_ADDR_CONF_LOCATION_SECONDARY +#else +#define IEEE_ADDR_LOCATION_SECONDARY 0x0001FFC8 /**< Secondary IEEE address location */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Copy the node's IEEE address to a destination memory area + * \param dst A pointer to the destination area where the IEEE address is to be + * written + * \param len The number of bytes to write to destination area + * + * This function will copy \e len LS bytes and it will invert byte order in + * the process. The factory address on devices is normally little-endian, + * therefore you should expect dst to store the address in a big-endian order. + */ +void ieee_addr_cpy_to(uint8_t *dst, uint8_t len); +/*---------------------------------------------------------------------------*/ +#endif /* IEEE_ADDR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/lpm.c b/cpu/cc26xx/lpm.c new file mode 100644 index 000000000..0322f940c --- /dev/null +++ b/cpu/cc26xx/lpm.c @@ -0,0 +1,408 @@ +/* + * 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-lpm + * @{ + * + * Implementation of CC26xx low-power operation functionality + * + * @{ + * + * \file + * Driver for CC26xx's low-power operation + */ +/*---------------------------------------------------------------------------*/ +#include "prcm.h" +#include "contiki-conf.h" +#include "ti-lib.h" +#include "lpm.h" +#include "sys/energest.h" +#include "lib/list.h" +#include "dev/leds.h" +#include "dev/watchdog.h" +#include "dev/cc26xx-rtc.h" +/*---------------------------------------------------------------------------*/ +#if ENERGEST_CONF_ON +static unsigned long irq_energest = 0; + +#define ENERGEST_IRQ_SAVE(a) do { \ + a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0) +#define ENERGEST_IRQ_RESTORE(a) do { \ + energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0) +#else +#define ENERGEST_IRQ_SAVE(a) do {} while(0) +#define ENERGEST_IRQ_RESTORE(a) do {} while(0) +#endif +/*---------------------------------------------------------------------------*/ +LIST(modules_list); +/*---------------------------------------------------------------------------*/ +/* Control what power domains we are allow to run under what mode */ +LIST(power_domain_locks_list); + +/* PDs that may stay on in deep sleep */ +#define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)) +/*---------------------------------------------------------------------------*/ +/* + * Don't consider standby mode if the next AON RTC event is scheduled to fire + * in less than STANDBY_MIN_DURATION rtimer ticks + */ +#define STANDBY_MIN_DURATION (RTIMER_SECOND >> 8) +/*---------------------------------------------------------------------------*/ +/* Variables used by the power on/off (Power mode: SHUTDOWN) functionality */ +static uint8_t shutdown_requested; +static uint32_t pin; +/*---------------------------------------------------------------------------*/ +void +lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains) +{ + /* We only accept locks for specific PDs */ + domains &= LOCKABLE_DOMAINS; + + if(domains == 0) { + return; + } + + lock->domains = domains; + + list_add(power_domain_locks_list, lock); +} +/*---------------------------------------------------------------------------*/ +void +lpm_pd_lock_release(lpm_power_domain_lock_t *lock) +{ + lock->domains = 0; + + list_remove(power_domain_locks_list, lock); +} +/*---------------------------------------------------------------------------*/ +void +lpm_shutdown(uint32_t wakeup_pin) +{ + shutdown_requested = 1; + pin = wakeup_pin; +} +/*---------------------------------------------------------------------------*/ +static void +shutdown_now(void) +{ + lpm_registered_module_t *module; + int i; + rtimer_clock_t t0; + uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | IOC_IOPULL_UP | + IOC_WAKE_ON_LOW; + + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->shutdown) { + module->shutdown(LPM_MODE_SHUTDOWN); + } + } + + leds_off(LEDS_ALL); + + for(i = 0; i < 5; i++) { + t0 = RTIMER_NOW(); + leds_toggle(LEDS_ALL); + while(RTIMER_CLOCK_LT(RTIMER_NOW(), (t0 + (RTIMER_SECOND >> 3)))); + } + + leds_off(LEDS_ALL); + + ti_lib_gpio_dir_mode_set((1 << pin), GPIO_DIR_MODE_IN); + ti_lib_ioc_port_configure_set(pin, IOC_PORT_GPIO, io_cfg); + + ti_lib_pwr_ctrl_state_set(LPM_MODE_SHUTDOWN); +} +/*---------------------------------------------------------------------------*/ +/* + * We'll get called on three occasions: + * - While running + * - While sleeping + * - While deep sleeping + * + * For the former two, we don't need to do anything. For the latter, we + * notify all modules that we're back on and rely on them to restore clocks + * and power domains as required. + */ +void +lpm_wake_up() +{ + lpm_registered_module_t *module; + + /* Remember IRQ energest for next pass */ + ENERGEST_IRQ_SAVE(irq_energest); + ENERGEST_ON(ENERGEST_TYPE_CPU); + ENERGEST_OFF(ENERGEST_TYPE_LPM); + + /* Sync so that we get the latest values before adjusting recharge settings */ + ti_lib_sys_ctrl_aon_sync(); + + /* Adjust recharge settings */ + ti_lib_sys_ctrl_adjust_recharge_after_power_down(); + + /* + * Release the request to the uLDO + * This is likely not required, since the switch to GLDO/DCDC is automatic + * when coming back from deep sleep + */ + ti_lib_prcm_mcu_uldo_configure(false); + + /* Turn on cache again */ + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED); + ti_lib_prcm_retention_enable(PRCM_DOMAIN_VIMS); + + ti_lib_aon_ioc_freeze_disable(); + ti_lib_sys_ctrl_aon_sync(); + + /* Power up AUX and allow it to go to sleep */ + ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_ALLOW_SLEEP); + + /* Notify all registered modules that we've just woken up */ + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->wakeup) { + module->wakeup(); + } + } +} +/*---------------------------------------------------------------------------*/ +void +lpm_drop() +{ + lpm_registered_module_t *module; + lpm_power_domain_lock_t *lock; + uint8_t max_pm = LPM_MODE_MAX_SUPPORTED; + uint8_t module_pm; + + uint32_t domains = LOCKABLE_DOMAINS; + + if(shutdown_requested) { + shutdown_now(); + } + + if(RTIMER_CLOCK_LT(cc26xx_rtc_get_next_trigger(), + RTIMER_NOW() + STANDBY_MIN_DURATION)) { + lpm_sleep(); + return; + } + + /* Collect max allowed PM permission from interested modules */ + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->request_max_pm) { + module_pm = module->request_max_pm(); + if(module_pm < max_pm) { + max_pm = module_pm; + } + } + } + + /* Check if any events fired during this process. Last chance to abort */ + if(process_nevents()) { + return; + } + + /* Drop */ + if(max_pm == LPM_MODE_SLEEP) { + lpm_sleep(); + } else { + /* Critical. Don't get interrupted! */ + ti_lib_int_master_disable(); + + /* + * Notify all registered modules that we are dropping to mode X. We do not + * need to do this for simple sleep. + * + * This is a chance for modules to delay us a little bit until an ongoing + * operation has finished (e.g. uart TX) or to configure themselves for + * deep sleep. + */ + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->shutdown) { + module->shutdown(max_pm); + } + } + + /* + * Iterate PD locks to see what we can and cannot turn off. + * + * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time + * we encounter a lock we just clear the respective bits in the 'domains' + * variable as required by the lock. In the end the domains variable will + * just hold whatever has not been cleared + */ + for(lock = list_head(power_domain_locks_list); lock != NULL; + lock = lock->next) { + /* Clear the bits specified in the lock */ + domains &= ~lock->domains; + } + + /* Pat the dog: We don't want it to shout right after we wake up */ + watchdog_periodic(); + + /* Clear unacceptable bits, just in case a lock provided a bad value */ + domains &= LOCKABLE_DOMAINS; + + /* + * Freeze the IOs on the boundary between MCU and AON. We only do this if + * PERIPH is not needed + */ + if(domains & PRCM_DOMAIN_PERIPH) { + ti_lib_aon_ioc_freeze_enable(); + } + + /* + * Among LOCKABLE_DOMAINS, turn off those that are not locked + * + * If domains is != 0, pass it as-is + */ + if(domains) { + ti_lib_prcm_power_domain_off(domains); + } + + /* Configure clock sources for MCU and AUX: No clock */ + ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); + ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); + + /* Full RAM retention. */ + ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | + MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); + + /* Enable retention on the CPU domain */ + ti_lib_prcm_retention_enable(PRCM_DOMAIN_CPU); + + /* Disable retention of AUX RAM */ + ti_lib_aon_wuc_aux_sram_config(false); + + /* Disable retention in the RFCORE RAM */ + HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_RFC; + + /* Disable retention of VIMS RAM (TRAM and CRAM) */ + //TODO: This can probably be removed, we are calling ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS); further down + HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_VIMS_M; + + /* + * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off + * already + */ + ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU | + PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS); + + /* Request JTAG domain power off */ + ti_lib_aon_wuc_jtag_power_off(); + + /* Turn off AUX */ + ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + ti_lib_aon_wuc_domain_power_down_enable(); + while(ti_lib_aon_wuc_power_status() & AONWUC_AUX_POWER_ON); + + /* Configure the recharge controller */ + ti_lib_sys_ctrl_set_recharge_before_power_down(false); + + /* + * If both PERIPH and SERIAL PDs are off, request the uLDO for as the power + * source while in deep sleep. + */ + if(domains == LOCKABLE_DOMAINS) { + ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); + } + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + ENERGEST_OFF(ENERGEST_TYPE_CPU); + ENERGEST_ON(ENERGEST_TYPE_LPM); + + /* Sync the AON interface to ensure all writes have gone through. */ + ti_lib_sys_ctrl_aon_sync(); + + /* + * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of + * retention mismatch between VIMS logic and cache. We wait to do this + * until right before deep sleep to be able to use the cache for as long + * as possible. + */ + ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS); + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); + + /* Deep Sleep */ + ti_lib_prcm_deep_sleep(); + + /* + * When we reach here, some interrupt woke us up. The global interrupt + * flag is off, hence we have a chance to run things here. We will wake up + * the chip properly, and then we will enable the global interrupt without + * unpending events so the handlers can fire + */ + lpm_wake_up(); + + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +lpm_sleep(void) +{ + ENERGEST_OFF(ENERGEST_TYPE_CPU); + ENERGEST_ON(ENERGEST_TYPE_LPM); + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + + /* Just to be on the safe side, explicitly disable Deep Sleep */ + HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP); + + ti_lib_prcm_sleep(); + + /* Remember IRQ energest for next pass */ + ENERGEST_IRQ_SAVE(irq_energest); + + ENERGEST_ON(ENERGEST_TYPE_CPU); + ENERGEST_OFF(ENERGEST_TYPE_LPM); +} +/*---------------------------------------------------------------------------*/ +void +lpm_register_module(lpm_registered_module_t *module) +{ + list_add(modules_list, module); +} +/*---------------------------------------------------------------------------*/ +void +lpm_init() +{ + list_init(modules_list); + list_init(power_domain_locks_list); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/lpm.h b/cpu/cc26xx/lpm.h new file mode 100644 index 000000000..85c20e77b --- /dev/null +++ b/cpu/cc26xx/lpm.h @@ -0,0 +1,172 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-lpm CC26xx Low-Power management + * + * CC26xx low-power operation + * + * @{ + * + * \file + * Header file for the management of CC26xx low-power operation + */ +/*---------------------------------------------------------------------------*/ +#ifndef LPM_H_ +#define LPM_H_ +/*---------------------------------------------------------------------------*/ +#include "pwr_ctrl.h" + +#include +/*---------------------------------------------------------------------------*/ +#define LPM_MODE_SLEEP PWRCTRL_ACTIVE +#define LPM_MODE_DEEP_SLEEP PWRCTRL_POWER_DOWN +#define LPM_MODE_SHUTDOWN PWRCTRL_SHUTDOWN + +#define LPM_MODE_MAX_SUPPORTED LPM_MODE_DEEP_SLEEP +/*---------------------------------------------------------------------------*/ +typedef struct lpm_registered_module { + struct lpm_registered_module *next; + uint8_t (*request_max_pm)(void); + void (*shutdown)(uint8_t mode); + void (*wakeup)(void); +} lpm_registered_module_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Declare a variable to be used in order to get notifications from LPM + * \param n the variable name to be declared + * \param m A pointer to a function which will tell the LPM module the max + * PM this module is willing to handle. This function will return + * LPM_MODE_SLEEP, LPM_MODE_DEEP_SLEEP etc. The LPM module will ask all + * registered modules and will trigger the highest LPM permitted + * \param s A pointer to a function which will receive a notification just + * before entering the low power mode. The callee can prepare for the + * imminent LPM state. The argument to this function will be the + * upcoming low power mode. This function can e.g. turn off a + * peripheral before the LPM module shuts down the power domain. + * \param w A pointer to a function which will be called just after we have + * woken up. This can be used to e.g. turn a peripheral back on. This + * function is in charge of turning power domains back on. This + * function will normally be called within an interrupt context. + */ +#define LPM_MODULE(n, m, s, w) static lpm_registered_module_t n = \ + { NULL, m, s, w } +/*---------------------------------------------------------------------------*/ +/** + * + * \brief Data type used to control whether a PD will get shut down when the + * CM3 drops to deep sleep + * + * Modules using these facilities must allocate a variable of this type, but + * they must not try to manipulate it directly. Instead, the respective + * functions must be used + * + * \sa lpm_pd_lock_obtain(), lpm_pd_lock_release() + */ +typedef struct lpm_power_domain_lock { + struct lpm_power_domain_lock *next; + uint32_t domains; +} lpm_power_domain_lock_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Prohibit a PD from turning off in standby mode + * \param lock A pointer to a lpm_power_domain_lock_t + * \param domains Bitwise OR from PRCM_DOMAIN_PERIPH, PRCM_DOMAIN_SERIAL + * + * The caller is responsible for allocating lpm_power_domain_lock_t + * + * Only the domains listed above can be locked / released, but a single lock + * can be used for multiple domains + */ +void lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains); + +/** + * \brief Permit a PD to turn off in standby mode + * \param pd A pointer to a previously used lock + * + * \sa lpm_pd_lock_obtain() + */ +void lpm_pd_lock_release(lpm_power_domain_lock_t *pd); + +/** + * \brief Drop the cortex to sleep / deep sleep and shut down peripherals + * + * Whether the cortex will drop to sleep or deep sleep is configurable. The + * exact peripherals which will be shut down is also configurable + */ +void lpm_drop(void); + +/** + * \brief Enter sleep mode + */ +void lpm_sleep(void); + +/** + * \brief Put the chip in shutdown power mode + * \param wakeup_pin The GPIO pin which will wake us up. Must be IOID_0 etc... + */ +void lpm_shutdown(uint32_t wakeup_pin); + +/** + * \brief Wake up from sleep mode + * + * This function must be called at the start of any interrupt context which + * may bring us out of sleep. Current interrupts do this already, but make sure + * to do the same when adding new ISRs + */ +void lpm_wake_up(void); + +/** + * \brief Register a module for LPM notifications. + * \param module A pointer to the data structure with the module definition + * + * When the LPM module is about to drop to some low power mode, it will first + * notify all modules about this. + * + * This function must not be called before the module has been initialised + * with lpm_init(). The code does not perform checks: This is the caller's + * responsibility. + */ +void lpm_register_module(lpm_registered_module_t *module); + +/** + * \brief Initialise the low-power mode management module + */ +void lpm_init(void); +/*---------------------------------------------------------------------------*/ +#endif /* LPM_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/mtarch.h b/cpu/cc26xx/mtarch.h new file mode 100644 index 000000000..4f696669d --- /dev/null +++ b/cpu/cc26xx/mtarch.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ +/* + * \file + * Stub header file for multi-threading. It doesn't do anything, it + * just exists so that mt.c can compile cleanly. + * + * This is based on the original mtarch.h for z80 by Takahide Matsutsuka + * + * \author + * George Oikonomou - + */ +#ifndef __MTARCH_H__ +#define __MTARCH_H__ + +struct mtarch_thread { + unsigned char *sp; +}; + +#endif /* __MTARCH_H__ */ diff --git a/cpu/cc26xx/putchar.c b/cpu/cc26xx/putchar.c new file mode 100644 index 000000000..0f91deea5 --- /dev/null +++ b/cpu/cc26xx/putchar.c @@ -0,0 +1,70 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#include "cc26xx-uart.h" + +#include +/*---------------------------------------------------------------------------*/ +int +putchar(int c) +{ + cc26xx_uart_write_byte(c); + return c; +} +/*---------------------------------------------------------------------------*/ +int +puts(const char *str) +{ + int i; + if(str == NULL) { + return 0; + } + for(i = 0; i < strlen(str); i++) { + putchar(str[i]); + } + putchar('\n'); + return i; +} +/*---------------------------------------------------------------------------*/ +unsigned int +dbg_send_bytes(const unsigned char *s, unsigned int len) +{ + unsigned int i = 0; + + while(s && *s != 0) { + if(i >= len) { + break; + } + putchar(*s++); + i++; + } + return i; +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/rtimer-arch.c b/cpu/cc26xx/rtimer-arch.c new file mode 100644 index 000000000..37077f1b3 --- /dev/null +++ b/cpu/cc26xx/rtimer-arch.c @@ -0,0 +1,92 @@ +/* + * 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-rtimer + * @{ + * + * \file + * Implementation of the arch-specific rtimer functions for the cc26xx + * + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/energest.h" +#include "sys/rtimer.h" +#include "cpu.h" +#include "dev/cc26xx-rtc.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief We don't need to do anything special here. The RTC is initialised + * elsewhere + */ +void +rtimer_arch_init(void) +{ + return; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Schedules an rtimer task to be triggered at time t + * \param t The time when the task will need executed. + * + * \e t is an absolute time, in other words the task will be executed AT + * time \e t, not IN \e t rtimer ticks. + * + * This function schedules a one-shot event with the AON RTC. + * + * This functions converts \e to a value suitable for the AON RTC. + */ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + /* Convert the rtimer tick value to a value suitable for the AON RTC */ + cc26xx_rtc_schedule_one_shot(t); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the current real-time clock time + * \return The current rtimer time in ticks + * + * The value is read from the AON RTC counter and converted to a number of + * rtimer ticks + * + */ +rtimer_clock_t +rtimer_arch_now() +{ + return ti_lib_aon_rtc_current_compare_value_get(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/rtimer-arch.h b/cpu/cc26xx/rtimer-arch.h new file mode 100644 index 000000000..1a4a50c09 --- /dev/null +++ b/cpu/cc26xx/rtimer-arch.h @@ -0,0 +1,65 @@ +/* + * 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-clocks + * @{ + * + * \defgroup cc26xx-rtimer CC26xx rtimer + * + * Implementation of the rtimer module for the CC26xx + * + * The rtimer runs on the AON RTC. We set the RTC's channel 2 to continuous + * compare mode, instead of scheduling the next tick interrupt by software. + * This gives us completely equidistant events. + * + * The RTC runs in all power modes (except shutdown) + * @{ + */ +/** + * \file + * Header file for the CC26xx rtimer driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef RTIMER_ARCH_H_ +#define RTIMER_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +#define RTIMER_ARCH_SECOND 65536 +/*---------------------------------------------------------------------------*/ +rtimer_clock_t rtimer_arch_now(void); +/*---------------------------------------------------------------------------*/ +#endif /* RTIMER_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/slip-arch.c b/cpu/cc26xx/slip-arch.c new file mode 100644 index 000000000..268c84548 --- /dev/null +++ b/cpu/cc26xx/slip-arch.c @@ -0,0 +1,65 @@ +/* + * 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-char-io + * @{ + * + * \file + * Arch-specific SLIP functions for the cc26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "dev/cc26xx-uart.h" +#include "dev/slip.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Write a byte over SLIP + * \param c the byte + */ +void +slip_arch_writeb(unsigned char c) +{ + cc26xx_uart_write_byte(c); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the arch-specific SLIP driver + * \param ubr Ignored for the cc26xx + */ +void +slip_arch_init(unsigned long ubr) +{ + cc26xx_uart_set_input(slip_input_byte); +} +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/cpu/cc26xx/ti-lib.h b/cpu/cc26xx/ti-lib.h new file mode 100644 index 000000000..df5e2cf39 --- /dev/null +++ b/cpu/cc26xx/ti-lib.h @@ -0,0 +1,667 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-ti-lib TI CC26xxware Glue + * + * Glue file which renames TI CC26xxware functions. Thus, for example, + * PowerCtrlIOFreezeDisable() becomes power_ctrl_io_freeze_disable() + * + * This is not strictly required and a call to the former will work perfectly + * correctly. However, in using those macros, we make the core of the Contiki + * port match the naming convention. + * + * Since all functions are prefixed with ti_lib, it also becomes clear to the + * reader that this is a call to TI driverlib's sources and not a call to a + * function inside Contiki + * + * @{ + * + * \file + * Header file with macros which rename TI CC26xxware functions. + */ +#ifndef TI_LIB_H_ +#define TI_LIB_H_ +/*---------------------------------------------------------------------------*/ +/* aon_batmon.h */ +#include "driverlib/aon_batmon.h" + +#define ti_lib_aon_batmon_enable(...) AONBatMonEnable(__VA_ARGS__) +#define ti_lib_aon_batmon_disable(...) AONBatMonDisable(__VA_ARGS__) +#define ti_lib_aon_batmon_measurement_cycle_set(...) AONBatMonMeasurementCycleSet(__VA_ARGS__) +#define ti_lib_aon_batmon_measurement_cycle_get(...) AONBatMonMeasurementCycleGet(__VA_ARGS__) +#define ti_lib_aon_batmon_battery_trim_set(...) AONBatMonBatteryTrimSet(__VA_ARGS__) +#define ti_lib_aon_batmon_temperature_trim_set(...) AONBatMonTemperatureTrimSet(__VA_ARGS__) +#define ti_lib_aon_batmon_temperature_get(...) AONBatMonTemperatureGet(__VA_ARGS__) +#define ti_lib_aon_batmon_temp_get_deg(...) AON_BatmonTempGetDegC(__VA_ARGS__) +#define ti_lib_aon_batmon_battery_voltage_get(...) AONBatMonBatteryVoltageGet(__VA_ARGS__) +#define ti_lib_aon_batmon_new_battery_measure_ready(...) AONBatMonNewBatteryMeasureReady(__VA_ARGS__) +#define ti_lib_aon_batmon_new_temp_measure_ready(...) AONBatMonNewTempMeasureReady(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_event.h */ +#include "driverlib/aon_event.h" + +#define ti_lib_aon_event_mcu_wake_up_set(...) AONEventMcuWakeUpSet(__VA_ARGS__) +#define ti_lib_aon_event_mcu_wake_up_get(...) AONEventMcuWakeUpGet(__VA_ARGS__) +#define ti_lib_aon_event_aux_wake_up_set(...) AONEventAuxWakeUpSet(__VA_ARGS__) +#define ti_lib_aon_event_aux_wake_up_get(...) AONEventAuxWakeUpGet(__VA_ARGS__) +#define ti_lib_aon_event_mcu_set(...) AONEventMcuSet(__VA_ARGS__) +#define ti_lib_aon_event_mcu_get(...) AONEventMcuGet(__VA_ARGS__) +#define ti_lib_aon_event_rtc_set(...) AONEventRtcSet(__VA_ARGS__) +#define ti_lib_aon_event_rtc_get(...) AONEventRtcGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_ioc.h */ +#include "driverlib/aon_ioc.h" + +#define ti_lib_aon_ioc_drive_strength_set(...) AONIOCDriveStrengthSet(__VA_ARGS__) +#define ti_lib_aon_ioc_drive_strength_get(...) AONIOCDriveStrengthGet(__VA_ARGS__) +#define ti_lib_aon_ioc_freeze_enable(...) AONIOCFreezeEnable(__VA_ARGS__) +#define ti_lib_aon_ioc_freeze_disable(...) AONIOCFreezeDisable(__VA_ARGS__) +#define ti_lib_aon_ioc_32_khz_output_disable(...) AONIOC32kHzOutputDisable(__VA_ARGS__) +#define ti_lib_aon_ioc_32_khz_output_enable(...) AONIOC32kHzOutputEnable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_rtc.h */ +#include "driverlib/aon_rtc.h" + +#define ti_lib_aon_rtc_enable(...) AONRTCEnable(__VA_ARGS__) +#define ti_lib_aon_rtc_disable(...) AONRTCDisable(__VA_ARGS__) +#define ti_lib_aon_rtc_status(...) AONRTCStatus(__VA_ARGS__) +#define ti_lib_aon_rtc_reset(...) AONRTCReset(__VA_ARGS__) +#define ti_lib_aon_rtc_delay_config(...) AONRTCDelayConfig(__VA_ARGS__) +#define ti_lib_aon_rtc_combined_event_config(...) AONRTCCombinedEventConfig(__VA_ARGS__) +#define ti_lib_aon_rtc_event_clear(...) AONRTCEventClear(__VA_ARGS__) +#define ti_lib_aon_rtc_event_get(...) AONRTCEventGet(__VA_ARGS__) +#define ti_lib_aon_rtc_sec_get(...) AONRTCSecGet(__VA_ARGS__) +#define ti_lib_aon_rtc_fraction_get(...) AONRTCFractionGet(__VA_ARGS__) +#define ti_lib_aon_rtc_sub_sec_incr_get(...) AONRTCSubSecIncrGet(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch1_set(...) AONRTCModeCh1Set(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch1_get(...) AONRTCModeCh1Get(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch2_set(...) AONRTCModeCh2Set(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch2_get(...) AONRTCModeCh2Get(__VA_ARGS__) +#define ti_lib_aon_rtc_channel_enable(...) AONRTCChannelEnable(__VA_ARGS__) +#define ti_lib_aon_rtc_channel_disable(...) AONRTCChannelDisable(__VA_ARGS__) +#define ti_lib_aon_rtc_compare_value_set(...) AONRTCCompareValueSet(__VA_ARGS__) +#define ti_lib_aon_rtc_compare_value_get(...) AONRTCCompareValueGet(__VA_ARGS__) +#define ti_lib_aon_rtc_current_compare_value_get(...) AONRTCCurrentCompareValueGet(__VA_ARGS__) +#define ti_lib_aon_rtc_inc_value_ch2_set(...) AONRTCIncValueCh2Set(__VA_ARGS__) +#define ti_lib_aon_rtc_inc_value_ch2_get(...) AONRTCIncValueCh2Get(__VA_ARGS__) +#define ti_lib_aon_rtc_capture_value_ch1_get(...) AONRTCCaptureValueCh1Get(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_wuc.h */ +#include "driverlib/aon_wuc.h" + +#define ti_lib_aon_wuc_mcu_wake_up_config(...) AONWUCMcuWakeUpConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_mcu_power_down_config(...) AONWUCMcuPowerDownConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_mcu_power_off_config(...) AONWUCMcuPowerOffConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_mcu_sram_config(...) AONWUCMcuSRamConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_clock_config_set(...) AONWUCAuxClockConfigSet(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_clock_config_get(...) AONWUCAuxClockConfigGet(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_power_down_config(...) AONWUCAuxPowerDownConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_power_off_config(...) AONWUCAuxPowerOffConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_wake_up_config(...) AONWUCAuxWakeUpConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_sram_config(...) AONWUCAuxSRamConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_wakeup_event(...) AONWUCAuxWakeupEvent(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_image_valid(...) AONWUCAuxImageValid(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_image_invalid(...) AONWUCAuxImageInvalid(__VA_ARGS__) +#define ti_lib_aon_wuc_aux_reset(...) AONWUCAuxReset(__VA_ARGS__) +#define ti_lib_aon_wuc_power_status(...) AONWUCPowerStatus(__VA_ARGS__) +#define ti_lib_aon_wuc_shut_down_enable(...) AONWUCShutDownEnable(__VA_ARGS__) +#define ti_lib_aon_wuc_domain_power_down_enable(...) AONWUCDomainPowerDownEnable(__VA_ARGS__) +#define ti_lib_aon_wuc_domain_power_down_disable(...) AONWUCDomainPowerDownDisable(__VA_ARGS__) +#define ti_lib_aon_wuc_mcu_reset_status(...) AONWUCMcuResetStatus(__VA_ARGS__) +#define ti_lib_aon_wuc_mcu_reset_clear(...) AONWUCMcuResetClear(__VA_ARGS__) +#define ti_lib_aon_wuc_recharge_ctrl_config_set(...) AONWUCRechargeCtrlConfigSet(__VA_ARGS__) +#define ti_lib_aon_wuc_recharge_ctrl_config_get(...) AONWUCRechargeCtrlConfigGet(__VA_ARGS__) +#define ti_lib_aon_wuc_osc_config(...) AONWUCOscConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_jtag_power_off(...) AONWUCJtagPowerOff(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aux_wuc.h */ +#include "driverlib/aux_wuc.h" + +#define ti_lib_aux_wuc_clock_enable(...) AUXWUCClockEnable(__VA_ARGS__) +#define ti_lib_aux_wuc_clock_disble(...) AUXWUCClockDisable(__VA_ARGS__) +#define ti_lib_aux_wuc_clock_status(...) AUXWUCClockStatus(__VA_ARGS__) +#define ti_lib_aux_wuc_clock_freq_req(...) AUXWUCClockFreqReq(__VA_ARGS__) +#define ti_lib_aux_wuc_power_ctrl(...) AUXWUCPowerCtrl(__VA_ARGS__) +#define ti_lib_aux_wuc_freeze_enable(...) AUXWUCFreezeEnable(__VA_ARGS__) +#define ti_lib_aux_wuc_freeze_disable(...) AUXWUCFreezeDisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* cpu.h */ +#include "driverlib/cpu.h" + +#define ti_lib_cpu_cpsid(...) CPUcpsid(__VA_ARGS__) +#define ti_lib_cpu_cpsie(...) CPUcpsie(__VA_ARGS__) +#define ti_lib_cpu_primask(...) CPUprimask(__VA_ARGS__) +#define ti_lib_cpu_wfi(...) CPUwfi(__VA_ARGS__) +#define ti_lib_cpu_wfe(...) CPUwfe(__VA_ARGS__) +#define ti_lib_cpu_sev(...) CPUsev(__VA_ARGS__) +#define ti_lib_cpu_base_pri_get(...) CPUbasepriGet(__VA_ARGS__) +#define ti_lib_cpu_base_pri_set(...) CPUbasepriSet(__VA_ARGS__) +#define ti_lib_cpu_delay(...) CPUdelay(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* ddi.h */ +#include "driverlib/ddi.h" + +#define ti_lib_aux_adi_ddi_safe_write(...) AuxAdiDdiSafeWrite(__VA_ARGS__) +#define ti_lib_aux_adi_ddi_safe_read(...) AuxAdiDdiSafeRead(__VA_ARGS__) +#define ti_lib_ddi_status_get(...) DDIStatusGet(__VA_ARGS__) +#define ti_lib_ddi_config_set(...) DDIConfigSet(__VA_ARGS__) +#define ti_lib_ddi_sync(...) DDISync(__VA_ARGS__) +#define ti_lib_ddi_protect(...) DDIProtect(__VA_ARGS__) +#define ti_lib_ddi_32_reg_write(...) DDI32RegWrite(__VA_ARGS__) +#define ti_lib_ddi_32_reg_read(...) DDI32RegRead(__VA_ARGS__) +#define ti_lib_ddi_32_bits_set(...) DDI32BitsSet(__VA_ARGS__) +#define ti_lib_ddi_32_bits_clear(...) DDI32BitsClear(__VA_ARGS__) +#define ti_lib_ddi_8_set_val_bit(...) DDI8SetValBit(__VA_ARGS__) +#define ti_lib_ddi_16_set_val_bit(...) DDI16SetValBit(__VA_ARGS__) +#define ti_lib_ddi_16_bit_write(...) DDI16BitWrite(__VA_ARGS__) +#define ti_lib_ddi_16_bit_field_write(...) DDI16BitfieldWrite(__VA_ARGS__) +#define ti_lib_ddi_16_bit_read(...) DDI16BitRead(__VA_ARGS__) +#define ti_lib_ddi_16_bitfield_read(...) DDI16BitfieldRead(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* gpio.h */ +#include "driverlib/gpio.h" + +#define ti_lib_gpio_dir_mode_set(...) GPIODirModeSet(__VA_ARGS__) +#define ti_lib_gpio_dir_mode_get(...) GPIODirModeGet(__VA_ARGS__) +#define ti_lib_gpio_pin_write(...) GPIOPinWrite(__VA_ARGS__) +#define ti_lib_gpio_pin_read(...) GPIOPinRead(__VA_ARGS__) +#define ti_lib_gpio_pin_clear(...) GPIOPinClear(__VA_ARGS__) +#define ti_lib_gpio_pin_toggle(...) GPIOPinToggle(__VA_ARGS__) +#define ti_lib_gpio_event_get(...) GPIOEventGet(__VA_ARGS__) +#define ti_lib_gpio_event_clear(...) GPIOEventClear(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* i2c.h */ +#include "driverlib/i2c.h" + +#define ti_lib_i2c_int_register(...) I2CIntRegister(__VA_ARGS__) +#define ti_lib_i2c_int_unregister(...) I2CIntUnregister(__VA_ARGS__) +#define ti_lib_i2c_master_bus_busy(...) I2CMasterBusBusy(__VA_ARGS__) +#define ti_lib_i2c_master_busy(...) I2CMasterBusy(__VA_ARGS__) +#define ti_lib_i2c_master_control(...) I2CMasterControl(__VA_ARGS__) +#define ti_lib_i2c_master_data_get(...) I2CMasterDataGet(__VA_ARGS__) +#define ti_lib_i2c_master_data_put(...) I2CMasterDataPut(__VA_ARGS__) +#define ti_lib_i2c_master_disable(...) I2CMasterDisable(__VA_ARGS__) +#define ti_lib_i2c_master_enable(...) I2CMasterEnable(__VA_ARGS__) +#define ti_lib_i2c_master_err(...) I2CMasterErr(__VA_ARGS__) +#define ti_lib_i2c_master_init_exp_clk(...) I2CMasterInitExpClk(__VA_ARGS__) +#define ti_lib_i2c_master_int_clear(...) I2CMasterIntClear(__VA_ARGS__) +#define ti_lib_i2c_master_int_disable(...) I2CMasterIntDisable(__VA_ARGS__) +#define ti_lib_i2c_master_int_enable(...) I2CMasterIntEnable(__VA_ARGS__) +#define ti_lib_i2c_master_int_status(...) I2CMasterIntStatus(__VA_ARGS__) +#define ti_lib_i2c_master_slave_addr_set(...) I2CMasterSlaveAddrSet(__VA_ARGS__) +#define ti_lib_i2c_slave_data_get(...) I2CSlaveDataGet(__VA_ARGS__) +#define ti_lib_i2c_slave_data_put(...) I2CSlaveDataPut(__VA_ARGS__) +#define ti_lib_i2c_slave_disable(...) I2CSlaveDisable(__VA_ARGS__) +#define ti_lib_i2c_slave_enable(...) I2CSlaveEnable(__VA_ARGS__) +#define ti_lib_i2c_slave_init(...) I2CSlaveInit(__VA_ARGS__) +#define ti_lib_i2c_slave_address_set(...) I2CSlaveAddressSet(__VA_ARGS__) +#define ti_lib_i2c_slave_int_clear(...) I2CSlaveIntClear(__VA_ARGS__) +#define ti_lib_i2c_slave_int_disable(...) I2CSlaveIntDisable(__VA_ARGS__) +#define ti_lib_i2c_slave_int_enable(...) I2CSlaveIntEnable(__VA_ARGS__) +#define ti_lib_i2c_slave_int_status(...) I2CSlaveIntStatus(__VA_ARGS__) +#define ti_lib_i2c_slave_status(...) I2CSlaveStatus(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* interrupt.h */ +#include "driverlib/interrupt.h" + +#define ti_lib_int_master_enable(...) IntMasterEnable(__VA_ARGS__) +#define ti_lib_int_master_disable(...) IntMasterDisable(__VA_ARGS__) +#define ti_lib_int_register(...) IntRegister(__VA_ARGS__); +#define ti_lib_int_unregsiter(...) IntUnregister(__VA_ARGS__) +#define ti_lib_int_priority_grouping_set(...) IntPriorityGroupingSet(__VA_ARGS__) +#define ti_lib_int_priority_grouping_get(...) IntPriorityGroupingGet(__VA_ARGS__) +#define ti_lib_int_priority_set(...) IntPrioritySet(__VA_ARGS__) +#define ti_lib_int_priority_get(...) IntPriorityGet(__VA_ARGS__) +#define ti_lib_int_enable(...) IntEnable(__VA_ARGS__) +#define ti_lib_int_disable(...) IntDisable(__VA_ARGS__) +#define ti_lib_int_pend_set(...) IntPendSet(__VA_ARGS__) +#define ti_lib_int_pend_get(...) IntPendGet(__VA_ARGS__) +#define ti_lib_int_pend_clear(...) IntPendClear(__VA_ARGS__) +#define ti_lib_int_mask_set(...) IntPriorityMaskSet(__VA_ARGS__) +#define ti_lib_int_mask_get(...) IntPriorityMaskGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* ioc.h */ +#include "driverlib/ioc.h" + +#define ti_lib_ioc_port_configure_set(...) IOCPortConfigureSet(__VA_ARGS__) +#define ti_lib_ioc_port_configure_get(...) IOCPortConfigureGet(__VA_ARGS__) +#define ti_lib_ioc_io_shutdown_set(...) IOCIOShutdownSet(__VA_ARGS__) +#define ti_lib_ioc_io_jtag_set(...) IOCIOJTagSet(__VA_ARGS__) +#define ti_lib_ioc_io_mode_set(...) IOCIOModeSet(__VA_ARGS__) +#define ti_lib_ioc_io_port_pull_set(...) IOCIOPortPullSet(__VA_ARGS__) +#define ti_lib_ioc_io_hyst_set(...) IOCIOHystSet(__VA_ARGS__) +#define ti_lib_ioc_io_input_set(...) IOCIOInputSet(__VA_ARGS__) +#define ti_lib_ioc_io_slew_ctrl_set(...) IOCIOSlewCtrlSet(__VA_ARGS__) +#define ti_lib_ioc_io_drv_strength_set(...) IOCIODrvStrengthSet(__VA_ARGS__) +#define ti_lib_ioc_io_port_id_set(...) IOCIOPortIdSet(__VA_ARGS__) +#define ti_lib_ioc_io_int_set(...) IOCIOIntSet(__VA_ARGS__) +#define ti_lib_ioc_int_register(...) IOCIntRegister(__VA_ARGS__); +#define ti_lib_ioc_int_unregister(...) IOCIntUnregister(__VA_ARGS__) +#define ti_lib_ioc_int_enable(...) IOCIntEnable(__VA_ARGS__) +#define ti_lib_ioc_int_disable(...) IOCIntDisable(__VA_ARGS__) +#define ti_lib_ioc_int_clear(...) IOCIntClear(__VA_ARGS__) +#define ti_lib_ioc_int_status(...) IOCIntStatus(__VA_ARGS__) +#define ti_lib_ioc_pin_type_gpio_input(...) IOCPinTypeGpioInput(__VA_ARGS__) +#define ti_lib_ioc_pin_type_gpio_output(...) IOCPinTypeGpioOutput(__VA_ARGS__) +#define ti_lib_ioc_pin_type_uart(...) IOCPinTypeUart(__VA_ARGS__) +#define ti_lib_ioc_pin_type_ssi_master(...) IOCPinTypeSsiMaster(__VA_ARGS__) +#define ti_lib_ioc_pin_type_ssi_slave(...) IOCPinTypeSsiSlave(__VA_ARGS__) +#define ti_lib_ioc_pin_type_i2c(...) IOCPinTypeI2c(__VA_ARGS__) +#define ti_lib_ioc_pin_type_aux(...) IOCPinTypeAux(__VA_ARGS__) +#define ti_lib_ioc_pin_type_spis(...) IOCPinTypeSpis(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* osc.h */ +#include "driverlib/osc.h" + +#define ti_lib_osc_xhf_power_mode_set(...) OSCXHfPowerModeSet(__VA_ARGS__) +#define ti_lib_osc_clock_source_set(...) OSCClockSourceSet(__VA_ARGS__) +#define ti_lib_osc_clock_source_get(...) OSCClockSourceGet(__VA_ARGS__) +#define ti_lib_osc_hf_source_ready(...) OSCHfSourceReady(__VA_ARGS__) +#define ti_lib_osc_hf_source_switch(...) OSCHfSourceSwitch(__VA_ARGS__) +#define ti_lib_osc_interface_enable(...) OSCInterfaceEnable(__VA_ARGS__) +#define ti_lib_osc_interface_disable(...) OSCInterfaceDisable(__VA_ARGS__) +#define ti_lib_osc_hf_get_startup_time(...) OSCHF_GetStartupTime(__VA_ARGS__) +#define ti_lib_osc_hf_turn_on_xosc(...) OSCHF_TurnOnXosc(__VA_ARGS__) +#define ti_lib_osc_hf_attempt_to_switch_to_xosc(...) OSCHF_AttemptToSwitchToXosc(__VA_ARGS__) +#define ti_lib_osc_hf_switch_to_rc_osc_turn_off_xosc(...) OSCHF_SwitchToRcOscTurnOffXosc(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* prcm.h */ +#include "driverlib/prcm.h" + +#define ti_lib_prcm_inf_clock_configure_set(...) PRCMInfClockConfigureSet(__VA_ARGS__) +#define ti_lib_prcm_inf_clock_configure_get(...) PRCMInfClockConfigureGet(__VA_ARGS__) +#define ti_lib_prcm_mcu_power_off(...) PRCMMcuPowerOff(__VA_ARGS__) +#define ti_lib_prcm_mcu_power_off_cancel(...) PRCMMcuPowerOffCancel(__VA_ARGS__) +#define ti_lib_prcm_mcu_uldo_configure(...) PRCMMcuUldoConfigure(__VA_ARGS__) +#define ti_lib_prcm_clock_configure_set(...) PRCMClockConfigureSet(__VA_ARGS__) +#define ti_lib_prcm_clock_configure_get(...) PRCMClockConfigureGet(__VA_ARGS__) +#define ti_lib_prcm_audio_clock_enable(...) PRCMAudioClockEnable(__VA_ARGS__) +#define ti_lib_prcm_audio_clock_disable(...) PRCMAudioClockDisable(__VA_ARGS__) +#define ti_lib_prcm_audio_clock_config_set(...) PRCMAudioClockConfigSet(__VA_ARGS__) +#define ti_lib_prcm_load_set(...) PRCMLoadSet(__VA_ARGS__) +#define ti_lib_prcm_load_get(...) PRCMLoadGet(__VA_ARGS__) +#define ti_lib_prcm_domain_enable(...) PRCMDomainEnable(__VA_ARGS__) +#define ti_lib_prcm_domain_disable(...) PRCMDomainDisable(__VA_ARGS__) +#define ti_lib_prcm_power_domain_on(...) PRCMPowerDomainOn(__VA_ARGS__) +#define ti_lib_prcm_power_domain_off(...) PRCMPowerDomainOff(__VA_ARGS__) +#define ti_lib_prcm_rf_power_down_when_idle(...) PRCMRfPowerDownWhenIdle(__VA_ARGS__) +#define ti_lib_prcm_peripheral_run_enable(...) PRCMPeripheralRunEnable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_run_disable(...) PRCMPeripheralRunDisable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_sleep_enable(...) PRCMPeripheralSleepEnable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_sleep_disable(...) PRCMPeripheralSleepDisable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_deep_sleep_enable(...) PRCMPeripheralDeepSleepEnable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_deep_sleep_disable(...) PRCMPeripheralDeepSleepDisable(__VA_ARGS__) +#define ti_lib_prcm_power_domain_status(...) PRCMPowerDomainStatus(__VA_ARGS__) +#define ti_lib_prcm_rf_ready(...) PRCMRfReady(__VA_ARGS__) +#define ti_lib_prcm_wdt_reset_status(...) PRCMWdtResetStatus(__VA_ARGS__) +#define ti_lib_prcm_sleep(...) PRCMSleep(__VA_ARGS__) +#define ti_lib_prcm_deep_sleep(...) PRCMDeepSleep(__VA_ARGS__) +#define ti_lib_prcm_retention_enable(...) PRCMRetentionEnable(__VA_ARGS__) +#define ti_lib_prcm_retention_disable(...) PRCMRetentionDisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* sys_ctrl.h */ +#include "driverlib/pwr_ctrl.h" + +#define ti_lib_pwr_ctrl_state_set(...) PowerCtrlStateSet(__VA_ARGS__) +#define ti_lib_pwr_ctrl_source_set(...) PowerCtrlSourceSet(__VA_ARGS__) +#define ti_lib_pwr_ctrl_source_get(...) PowerCtrlSourceGet(__VA_ARGS__) +#define ti_lib_pwr_ctrl_io_config_set(...) PowerCtrlIoConfigSet(__VA_ARGS__) +#define ti_lib_pwr_ctrl_reset_source_get(...) PowerCtrlResetSourceGet(__VA_ARGS__) +#define ti_lib_pwr_ctrl_reset_source_clear(...) PowerCtrlResetSourceClear(__VA_ARGS__) +#define ti_lib_pwr_ctrl_io_freeze_enable(...) PowerCtrlIOFreezeEnable(__VA_ARGS__) +#define ti_lib_pwr_ctrl_io_freeze_disable(...) PowerCtrlIOFreezeDisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* rom.h */ +#include "driverlib/rom.h" + +/* AON API */ +#define ti_lib_rom_aon_event_mcu_wake_up_set ROM_AONEventMcuWakeUpSet +#define ti_lib_rom_aon_event_mcu_wake_up_get ROM_AONEventMcuWakeUpGet +#define ti_lib_rom_aon_event_aux_wake_up_set ROM_AONEventAuxWakeUpSet +#define ti_lib_rom_aon_event_aux_wake_up_get ROM_AONEventAuxWakeUpGet +#define ti_lib_rom_aon_event_mcu_set ROM_AONEventMcuSet +#define ti_lib_rom_aon_event_mcu_get ROM_AONEventMcuGet + +/* AON_IOC API */ +#define ti_lib_rom_aon_ioc_drive_strength_set ROM_AONIOCDriveStrengthSet +#define ti_lib_rom_aon_ioc_drive_strength_get ROM_AONIOCDriveStrengthGet + +/* AON_RTC API */ +#define ti_lib_rom_aon_rtc_status ROM_AONRTCStatus +#define ti_lib_rom_aon_rtc_event_clear ROM_AONRTCEventClear +#define ti_lib_rom_aon_rtc_event_get ROM_AONRTCEventGet +#define ti_lib_rom_aon_rtc_mode_ch1_set ROM_AONRTCModeCh1Set +#define ti_lib_rom_aon_rtc_mode_ch1_get ROM_AONRTCModeCh1Get +#define ti_lib_rom_aon_rtc_mode_ch2_set ROM_AONRTCModeCh2Set +#define ti_lib_rom_aon_rtc_mode_ch2_get ROM_AONRTCModeCh2Get +#define ti_lib_rom_aon_rtc_channel_enable ROM_AONRTCChannelEnable +#define ti_lib_rom_aon_rtc_channel_disable ROM_AONRTCChannelDisable +#define ti_lib_rom_aon_rtc_compare_value_set ROM_AONRTCCompareValueSet +#define ti_lib_rom_aon_rtc_compare_value_get ROM_AONRTCCompareValueGet +#define ti_lib_rom_aon_rtc_current_compare_value_get ROM_AONRTCCurrentCompareValueGet + +/* AON_WUC API */ +#define ti_lib_rom_aon_wuc_aux_clock_config_set ROM_AONWUCAuxClockConfigSet +#define ti_lib_rom_aon_wuc_aux_s_ram_config ROM_AONWUCAuxSRamConfig +#define ti_lib_rom_aon_wuc_aux_wakeup_event ROM_AONWUCAuxWakeupEvent +#define ti_lib_rom_aon_wuc_aux_reset ROM_AONWUCAuxReset +#define ti_lib_rom_aon_wuc_recharge_ctrl_config_set ROM_AONWUCRechargeCtrlConfigSet +#define ti_lib_rom_aon_wuc_osc_config ROM_AONWUCOscConfig + +/* AUX_TDC API */ +#define ti_lib_rom_aux_tdc_config_set ROM_AUXTDCConfigSet +#define ti_lib_rom_aux_tdc_measurement_done ROM_AUXTDCMeasurementDone + +/* AUX_TIMER API */ +#define ti_lib_rom_aux_timer_configure ROM_AUXTimerConfigure +#define ti_lib_rom_aux_timer_start ROM_AUXTimerStart +#define ti_lib_rom_aux_timer_stop ROM_AUXTimerStop +#define ti_lib_rom_aux_timer_prescale_set ROM_AUXTimerPrescaleSet +#define ti_lib_rom_aux_timer_prescale_get ROM_AUXTimerPrescaleGet + +/* AUX_WUC API */ +#define ti_lib_rom_aux_wuc_clock_enable ROM_AUXWUCClockEnable +#define ti_lib_rom_aux_wuc_clock_disable ROM_AUXWUCClockDisable +#define ti_lib_rom_aux_wuc_clock_status ROM_AUXWUCClockStatus +#define ti_lib_rom_aux_wuc_power_ctrl ROM_AUXWUCPowerCtrl + +/* FLASH API */ +#define ti_lib_rom_flash_power_mode_get ROM_FlashPowerModeGet +#define ti_lib_rom_flash_protection_set ROM_FlashProtectionSet +#define ti_lib_rom_flash_protection_get ROM_FlashProtectionGet +#define ti_lib_rom_flash_protection_save ROM_FlashProtectionSave +#define ti_lib_rom_flash_sector_erase ROM_FlashSectorErase +#define ti_lib_rom_flash_program ROM_FlashProgram +#define ti_lib_rom_flash_program_nowait ROM_FlashProgramNowait + +#define ti_lib_rom_flash_efuse_read_row ROM_FlashEfuseReadRow +#define ti_lib_rom_flash_disable_sectors_for_write ROM_FlashDisableSectorsForWrite + +/* I2C API */ +#define ti_lib_rom_i2c_master_init_exp_clk ROM_I2CMasterInitExpClk +#define ti_lib_rom_i2c_master_err ROM_I2CMasterErr + +/* INTERRUPT API */ +#define ti_lib_rom_int_priority_grouping_set ROM_IntPriorityGroupingSet +#define ti_lib_rom_int_priority_grouping_get ROM_IntPriorityGroupingGet +#define ti_lib_rom_int_priority_set ROM_IntPrioritySet +#define ti_lib_rom_int_priority_get ROM_IntPriorityGet +#define ti_lib_rom_int_enable ROM_IntEnable +#define ti_lib_rom_int_disable ROM_IntDisable +#define ti_lib_rom_int_pend_set ROM_IntPendSet +#define ti_lib_rom_int_pend_get ROM_IntPendGet +#define ti_lib_rom_int_pend_clear ROM_IntPendClear + +/* IOC API */ +#define ti_lib_rom_ioc_port_configure_set ROM_IOCPortConfigureSet +#define ti_lib_rom_ioc_port_configure_get ROM_IOCPortConfigureGet +#define ti_lib_rom_ioc_io_shutdown_set ROM_IOCIOShutdownSet +#define ti_lib_rom_ioc_io_jtag_set ROM_IOCIOJTagSet +#define ti_lib_rom_ioc_io_mode_set ROM_IOCIOModeSet +#define ti_lib_rom_ioc_io_int_set ROM_IOCIOIntSet +#define ti_lib_rom_ioc_io_port_pull_set ROM_IOCIOPortPullSet +#define ti_lib_rom_ioc_io_hyst_set ROM_IOCIOHystSet +#define ti_lib_rom_ioc_io_input_set ROM_IOCIOInputSet +#define ti_lib_rom_ioc_io_slew_ctrl_set ROM_IOCIOSlewCtrlSet +#define ti_lib_rom_ioc_io_drv_strength_set ROM_IOCIODrvStrengthSet +#define ti_lib_rom_ioc_io_port_id_set ROM_IOCIOPortIdSet +#define ti_lib_rom_ioc_int_enable ROM_IOCIntEnable +#define ti_lib_rom_ioc_int_disable ROM_IOCIntDisable +#define ti_lib_rom_ioc_pin_type_gpio_input ROM_IOCPinTypeGpioInput +#define ti_lib_rom_ioc_pin_type_gpio_output ROM_IOCPinTypeGpioOutput +#define ti_lib_rom_ioc_pin_type_uart ROM_IOCPinTypeUart +#define ti_lib_rom_ioc_pin_type_ssi_master ROM_IOCPinTypeSsiMaster +#define ti_lib_rom_ioc_pin_type_ssi_slave ROM_IOCPinTypeSsiSlave +#define ti_lib_rom_ioc_pin_type_i2c ROM_IOCPinTypeI2c +#define ti_lib_rom_ioc_pin_type_spis ROM_IOCPinTypeSpis +#define ti_lib_rom_ioc_pin_type_aux ROM_IOCPinTypeAux + +/* PRCM API */ +#define ti_lib_rom_prcm_inf_clock_configure_set ROM_PRCMInfClockConfigureSet +#define ti_lib_rom_prcm_inf_clock_configure_get ROM_PRCMInfClockConfigureGet +#define ti_lib_rom_prcm_clock_configure_set ROM_PRCMClockConfigureSet +#define ti_lib_rom_prcm_clock_configure_get ROM_PRCMClockConfigureGet +#define ti_lib_rom_prcm_audio_clock_config_set ROM_PRCMAudioClockConfigSet +#define ti_lib_rom_prcm_power_domain_on ROM_PRCMPowerDomainOn +#define ti_lib_rom_prcm_power_domain_off ROM_PRCMPowerDomainOff +#define ti_lib_rom_prcm_peripheral_run_enable ROM_PRCMPeripheralRunEnable +#define ti_lib_rom_prcm_peripheral_run_disable ROM_PRCMPeripheralRunDisable +#define ti_lib_rom_prcm_peripheral_sleep_enable ROM_PRCMPeripheralSleepEnable +#define ti_lib_rom_prcm_peripheral_sleep_disable ROM_PRCMPeripheralSleepDisable +#define ti_lib_rom_prcm_peripheral_deep_sleep_enable ROM_PRCMPeripheralDeepSleepEnable +#define ti_lib_rom_prcm_peripheral_deep_sleep_disable ROM_PRCMPeripheralDeepSleepDisable +#define ti_lib_rom_prcm_power_domain_status ROM_PRCMPowerDomainStatus +#define ti_lib_rom_prcm_deep_sleep ROM_PRCMDeepSleep +#define ti_lib_rom_prcm_retention_enable ROM_PRCMRetentionEnable +#define ti_lib_rom_prcm_retention_disable ROM_PRCMRetentionDisable + +/* SMPH API */ +#define ti_lib_rom_smph_acquire ROM_SMPHAcquire + +/* SPIS API */ +#define ti_lib_rom_spis_data_put ROM_SPISDataPut +#define ti_lib_rom_spis_tx_get_value ROM_SPISTxGetValue +#define ti_lib_rom_spis_data_get ROM_SPISDataGet +#define ti_lib_rom_spis_rx_get_value ROM_SPISRxGetValue +#define ti_lib_rom_spis_int_status ROM_SPISIntStatus + +/* SSI API */ +#define ti_lib_rom_ssi_config_set_exp_clk ROM_SSIConfigSetExpClk +#define ti_lib_rom_ssi_data_put ROM_SSIDataPut +#define ti_lib_rom_ssi_data_put_non_blocking ROM_SSIDataPutNonBlocking +#define ti_lib_rom_ssi_data_get ROM_SSIDataGet +#define ti_lib_rom_ssi_data_get_non_blocking ROM_SSIDataGetNonBlocking + +/* TIMER API */ +#define ti_lib_rom_timer_configure ROM_TimerConfigure +#define ti_lib_rom_timer_level_control ROM_TimerLevelControl +#define ti_lib_rom_timer_trigger_control ROM_TimerTriggerControl +#define ti_lib_rom_timer_stall_control ROM_TimerStallControl +#define ti_lib_rom_timer_wait_on_trigger_control ROM_TimerWaitOnTriggerControl + +/* TRNG API */ +#define ti_lib_rom_trng_configure ROM_TRNGConfigure +#define ti_lib_rom_trng_number_get ROM_TRNGNumberGet + +/* UART API */ +#define ti_lib_rom_uart_fifo_level_get ROM_UARTFIFOLevelGet +#define ti_lib_rom_uart_config_set_exp_clk ROM_UARTConfigSetExpClk +#define ti_lib_rom_uart_config_get_exp_clk ROM_UARTConfigGetExpClk +#define ti_lib_rom_uart_disable ROM_UARTDisable +#define ti_lib_rom_uart_char_get_non_blocking ROM_UARTCharGetNonBlocking +#define ti_lib_rom_uart_char_get ROM_UARTCharGet +#define ti_lib_rom_uart_char_put_non_blocking ROM_UARTCharPutNonBlocking +#define ti_lib_rom_uart_char_put ROM_UARTCharPut + +/* UDMA API */ +#define ti_lib_rom_udma_channel_attribute_enable ROM_uDMAChannelAttributeEnable +#define ti_lib_rom_udma_channel_attribute_disable ROM_uDMAChannelAttributeDisable +#define ti_lib_rom_udma_channel_attribute_get ROM_uDMAChannelAttributeGet +#define ti_lib_rom_udma_channel_control_set ROM_uDMAChannelControlSet +#define ti_lib_rom_udma_channel_transfer_set ROM_uDMAChannelTransferSet +#define ti_lib_rom_udma_channel_scatter_gather_set ROM_uDMAChannelScatterGatherSet +#define ti_lib_rom_udma_channel_size_get ROM_uDMAChannelSizeGet +#define ti_lib_rom_udma_channel_mode_get ROM_uDMAChannelModeGet + +/* VIMS API */ +#define ti_lib_rom_vims_configure ROM_VIMSConfigure +#define ti_lib_rom_vims_mode_set ROM_VIMSModeSet +#define ti_lib_rom_vims_mode_get ROM_VIMSModeGet +/*---------------------------------------------------------------------------*/ +/* sys_ctrl.h */ +#include "driverlib/sys_ctrl.h" + +#define ti_lib_sys_ctrl_power_everything(...) SysCtrlPowerEverything(__VA_ARGS__) +#define ti_lib_sys_ctrl_powerdown(...) SysCtrlPowerdown(__VA_ARGS__) +#define ti_lib_sys_ctrl_standby(...) SysCtrlStandby(__VA_ARGS__) +#define ti_lib_sys_ctrl_shutdown(...) SysCtrlShutdown(__VA_ARGS__) +#define ti_lib_sys_ctrl_clock_get(...) SysCtrlClockGet(__VA_ARGS__) +#define ti_lib_sys_ctrl_peripheral_clock_get(...) SysCtrlPeripheralClockGet(__VA_ARGS__) +#define ti_lib_sys_ctrl_aon_sync(...) SysCtrlAonSync(__VA_ARGS__) +#define ti_lib_sys_ctrl_aon_update(...) SysCtrlAonUpdate(__VA_ARGS__) +#define ti_lib_sys_ctrl_set_recharge_before_power_down(...) SysCtrlSetRechargeBeforePowerDown(__VA_ARGS__) +#define ti_lib_sys_ctrl_adjust_recharge_after_power_down(...) SysCtrlAdjustRechargeAfterPowerDown(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* ssi.h */ +#include "driverlib/ssi.h" + +#define ti_lib_ssi_config_set_exp_clk(...) SSIConfigSetExpClk(__VA_ARGS__) +#define ti_lib_ssi_enable(...) SSIEnable(__VA_ARGS__) +#define ti_lib_ssi_disable(...) SSIDisable(__VA_ARGS__) +#define ti_lib_ssi_data_put(...) SSIDataPut(__VA_ARGS__) +#define ti_lib_ssi_data_put_non_blocking(...) SSIDataPutNonBlocking(__VA_ARGS__) +#define ti_lib_ssi_data_get(...) SSIDataGet(__VA_ARGS__) +#define ti_lib_ssi_data_get_non_blocking(...) SSIDataGetNonBlocking(__VA_ARGS__) +#define ti_lib_ssi_busy(...) SSIBusy(__VA_ARGS__) +#define ti_lib_ssi_status(...) SSIStatus(__VA_ARGS__) +#define ti_lib_ssi_int_register(...) SSIIntRegister(__VA_ARGS__) +#define ti_lib_ssi_int_unregister(...) SSIIntUnregister(__VA_ARGS__) +#define ti_lib_ssi_int_enable(...) SSIIntEnable(__VA_ARGS__) +#define ti_lib_ssi_int_disable(...) SSIIntDisable(__VA_ARGS__) +#define ti_lib_ssi_int_clear(...) SSIIntClear(__VA_ARGS__) +#define ti_lib_ssi_int_status(...) SSIIntStatus(__VA_ARGS__) +#define ti_lib_ssi_dma_enable(...) SSIDMAEnable(__VA_ARGS__) +#define ti_lib_ssi_dma_disable(...) SSIDMADisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* systick.h */ +#include "driverlib/systick.h" + +#define ti_lib_systick_enable(...) SysTickEnable(__VA_ARGS__) +#define ti_lib_systick_disable(...) SysTickDisable(__VA_ARGS__) +#define ti_lib_systick_int_register(...) SysTickIntRegister(__VA_ARGS__) +#define ti_lib_systick_int_unregister(...) SysTickIntUnregister(__VA_ARGS__) +#define ti_lib_systick_int_enable(...) SysTickIntEnable(__VA_ARGS__) +#define ti_lib_systick_int_disable(...) SysTickIntDisable(__VA_ARGS__) +#define ti_lib_systick_period_set(...) SysTickPeriodSet(__VA_ARGS__) +#define ti_lib_systick_period_get(...) SysTickPeriodGet(__VA_ARGS__) +#define ti_lib_systick_value_get(...) SysTickValueGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* timer.h */ +#include "driverlib/timer.h" + +#define ti_lib_timer_enable(...) TimerEnable(__VA_ARGS__) +#define ti_lib_timer_disable(...) TimerDisable(__VA_ARGS__) +#define ti_lib_timer_configure(...) TimerConfigure(__VA_ARGS__) +#define ti_lib_timer_level_control(...) TimerLevelControl(__VA_ARGS__) +#define ti_lib_timer_trigger_control(...) TimerTriggerControl(__VA_ARGS__) +#define ti_lib_timer_event_control(...) TimerEventControl(__VA_ARGS__) +#define ti_lib_timer_stall_control(...) TimerStallControl(__VA_ARGS__) +#define ti_lib_timer_wait_on_trigger_control(...) TimerWaitOnTriggerControl(__VA_ARGS__) +#define ti_lib_timer_rtc_enable(...) TimerRtcEnable(__VA_ARGS__) +#define ti_lib_timer_rtc_disable(...) TimerRtcDisable(__VA_ARGS__) +#define ti_lib_timer_prescale_set(...) TimerPrescaleSet(__VA_ARGS__) +#define ti_lib_timer_prescale_get(...) TimerPrescaleGet(__VA_ARGS__) +#define ti_lib_timer_prescale_match_set(...) TimerPrescaleMatchSet(__VA_ARGS__) +#define ti_lib_timer_prescale_match_get(...) TimerPrescaleMatchGet(__VA_ARGS__) +#define ti_lib_timer_load_set(...) TimerLoadSet(__VA_ARGS__) +#define ti_lib_timer_load_get(...) TimerLoadGet(__VA_ARGS__) +#define ti_lib_timer_value_get(...) TimerValueGet(__VA_ARGS__) +#define ti_lib_timer_match_set(...) TimerMatchSet(__VA_ARGS__) +#define ti_lib_timer_match_get(...) TimerMatchGet(__VA_ARGS__) +#define ti_lib_timer_int_register(...) TimerIntRegister(__VA_ARGS__) +#define ti_lib_timer_int_unregister(...) TimerIntUnregister(__VA_ARGS__) +#define ti_lib_timer_int_enable(...) TimerIntEnable(__VA_ARGS__) +#define ti_lib_timer_int_disable(...) TimerIntDisable(__VA_ARGS__) +#define ti_lib_timer_int_status(...) TimerIntStatus(__VA_ARGS__) +#define ti_lib_timer_int_clear(...) TimerIntClear(__VA_ARGS__) +#define ti_lib_timer_synchronize(...) TimerSynchronize(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* uart.h */ +#include "driverlib/uart.h" + +#define ti_lib_uart_parity_mode_set(...) UARTParityModeSet(__VA_ARGS__) +#define ti_lib_uart_parity_mode_get(...) UARTParityModeGet(__VA_ARGS__) +#define ti_lib_uart_fifo_level_set(...) UARTFIFOLevelSet(__VA_ARGS__) +#define ti_lib_uart_fifo_level_get(...) UARTFIFOLevelGet(__VA_ARGS__) +#define ti_lib_uart_config_set_exp_clk(...) UARTConfigSetExpClk(__VA_ARGS__) +#define ti_lib_uart_config_get_exp_clk(...) UARTConfigGetExpClk(__VA_ARGS__) +#define ti_lib_uart_enable(...) UARTEnable(__VA_ARGS__) +#define ti_lib_uart_disable(...) UARTDisable(__VA_ARGS__) +#define ti_lib_uart_fifo_enable(...) UARTFIFOEnable(__VA_ARGS__) +#define ti_lib_uart_fifo_disable(...) UARTFIFODisable(__VA_ARGS__) +#define ti_lib_uart_chars_avail(...) UARTCharsAvail(__VA_ARGS__) +#define ti_lib_uart_space_avail(...) UARTSpaceAvail(__VA_ARGS__) +#define ti_lib_uart_char_get_non_blocking(...) UARTCharGetNonBlocking(__VA_ARGS__) +#define ti_lib_uart_char_get(...) UARTCharGet(__VA_ARGS__) +#define ti_lib_uart_char_put_non_blocking(...) UARTCharPutNonBlocking(__VA_ARGS__) +#define ti_lib_uart_char_put(...) UARTCharPut(__VA_ARGS__) +#define ti_lib_uart_break_ctl(...) UARTBreakCtl(__VA_ARGS__) +#define ti_lib_uart_busy(...) UARTBusy(__VA_ARGS__) +#define ti_lib_uart_int_register(...) UARTIntRegister(__VA_ARGS__) +#define ti_lib_uart_int_unregister(...) UARTIntUnregister(__VA_ARGS__) +#define ti_lib_uart_int_enable(...) UARTIntEnable(__VA_ARGS__) +#define ti_lib_uart_int_disable(...) UARTIntDisable(__VA_ARGS__) +#define ti_lib_uart_int_status(...) UARTIntStatus(__VA_ARGS__) +#define ti_lib_uart_int_clear(...) UARTIntClear(__VA_ARGS__) +#define ti_lib_uart_dma_enable(...) UARTDMAEnable(__VA_ARGS__) +#define ti_lib_uart_dma_disable(...) UARTDMADisable(__VA_ARGS__) +#define ti_lib_uart_rx_error_get(...) UARTRxErrorGet(__VA_ARGS__) +#define ti_lib_uart_rx_error_clear(...) UARTRxErrorClear(__VA_ARGS__) +#define ti_lib_uart_tx_int_mode_set(...) UARTTxIntModeSet(__VA_ARGS__) +#define ti_lib_uart_tx_int_mode_get(...) UARTTxIntModeGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* vims.h */ +#include "driverlib/vims.h" + +#define ti_lib_vims_configure(...) VIMSConfigure(__VA_ARGS__) +#define ti_lib_vims_mode_set(...) VIMSModeSet(__VA_ARGS__) +#define ti_lib_vims_mode_get(...) VIMSModeGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* watchdog.h */ +#include "driverlib/watchdog.h" + +#define ti_lib_wathdog_running(...) WatchdogRunning(__VA_ARGS__) +#define ti_lib_wathdog_enable(...) WatchdogEnable(__VA_ARGS__) +#define ti_lib_wathdog_reset_enable(...) WatchdogResetEnable(__VA_ARGS__) +#define ti_lib_wathdog_reset_disable(...) WatchdogResetDisable(__VA_ARGS__) +#define ti_lib_wathdog_lock(...) WatchdogLock(__VA_ARGS__) +#define ti_lib_wathdog_unlock(...) WatchdogUnlock(__VA_ARGS__) +#define ti_lib_wathdog_lock_state(...) WatchdogLockState(__VA_ARGS__) +#define ti_lib_wathdog_reload_set(...) WatchdogReloadSet(__VA_ARGS__) +#define ti_lib_wathdog_reload_get(...) WatchdogReloadGet(__VA_ARGS__) +#define ti_lib_wathdog_value_get(...) WatchdogValueGet(__VA_ARGS__) +#define ti_lib_wathdog_int_register(...) WatchdogIntRegister(__VA_ARGS__) +#define ti_lib_wathdog_int_unregister(...) WatchdogIntUnregister(__VA_ARGS__) +#define ti_lib_wathdog_int_enable(...) WatchdogIntEnable(__VA_ARGS__) +#define ti_lib_wathdog_int_status(...) WatchdogIntStatus(__VA_ARGS__) +#define ti_lib_wathdog_int_clear(...) WatchdogIntClear(__VA_ARGS__) +#define ti_lib_wathdog_int_type_set(...) WatchdogIntTypeSet(__VA_ARGS__) +#define ti_lib_wathdog_stall_enable(...) WatchdogStallEnable(__VA_ARGS__) +#define ti_lib_wathdog_stall_disable(...) WatchdogStallDisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +#endif /* TI_LIB_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/cc26xx/Makefile b/examples/cc26xx/Makefile new file mode 100644 index 000000000..f23d49fe3 --- /dev/null +++ b/examples/cc26xx/Makefile @@ -0,0 +1,9 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +CONTIKI_PROJECT = cc26xx-demo + +all: $(CONTIKI_PROJECT) + +CONTIKI_WITH_IPV6 = 1 + +CONTIKI = ../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/cc26xx/Makefile.target b/examples/cc26xx/Makefile.target new file mode 100644 index 000000000..15890aa6a --- /dev/null +++ b/examples/cc26xx/Makefile.target @@ -0,0 +1 @@ +TARGET = srf06-cc26xx diff --git a/examples/cc26xx/README.md b/examples/cc26xx/README.md new file mode 100644 index 000000000..bd1be685b --- /dev/null +++ b/examples/cc26xx/README.md @@ -0,0 +1,15 @@ +CC26xx Demo +=========== +This example demonstrates basic functionality for the two supported CC26xx +boards. More specifically, the example demonstrates: + +* How to take sensor readings +* How to use buttons and the reed relay (triggered by holding a magnet near S3 + on the SensorTag). +* How to keep a power domain powered and a peripheral clocked under low power + operation +* How to send out BLE advertisements. The device will periodically send out BLE + beacons with the platform name as payload. Those beacons/BLE ADV packets can + be captured with any BLE capable device. Two such applications for iOS are the + TI Multitool and the TI Sensortag app. They can be found in the Apple App + Store. If you have a BLE-capable Mac, you can also use LightBlue for OS X. diff --git a/examples/cc26xx/cc26xx-demo.c b/examples/cc26xx/cc26xx-demo.c new file mode 100644 index 000000000..83f78e869 --- /dev/null +++ b/examples/cc26xx/cc26xx-demo.c @@ -0,0 +1,477 @@ +/* + * 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 "lpm.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, sht_timer, tmp_timer, mpu_timer; +/*---------------------------------------------------------------------------*/ +static void init_bmp_reading(void *not_used); +static void init_opt_reading(void *not_used); +static void init_sht_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_sht_reading() +{ + int value; + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + + value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP); + if(value != CC26XX_SENSOR_READING_ERROR) { + printf("SHT: Temp=%d.%02d C\n", value / 100, value % 100); + } else { + printf("SHT: Temp Read Error\n"); + } + + value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY); + if(value != CC26XX_SENSOR_READING_ERROR) { + printf("SHT: Humidity=%d.%02d %%RH\n", value / 100, value % 100); + } else { + printf("SHT: Humidity Read Error\n"); + } + + ctimer_set(&sht_timer, next, init_sht_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"); + } + + SENSORS_DEACTIVATE(opt_3001_sensor); + + 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_sht_reading(void *not_used) +{ + SENSORS_ACTIVATE(sht_21_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(sht_21_sensor); + SENSORS_ACTIVATE(tmp_007_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); + + init_mpu_reading(NULL); +#endif +} +/*---------------------------------------------------------------------------*/ +static lpm_power_domain_lock_t lock; +/*---------------------------------------------------------------------------*/ +/* + * In order to maintain UART input operation: + * - Keep the uart clocked in sleep and deep sleep + * - Keep the serial PD on in deep sleep + */ +static void +keep_uart_on(void) +{ + /* Keep the serial PD on */ + lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL); + + /* Keep the UART clock on during Sleep and Deep Sleep */ + ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0); + ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +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 == &sht_21_sensor) { + get_sht_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(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/Makefile b/examples/cc26xx/cc26xx-web-demo/Makefile new file mode 100644 index 000000000..622156a4d --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/Makefile @@ -0,0 +1,24 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +all: cc26xx-web-demo + +REST_RESOURCES_DIR = ./resources + +REST_RESOURCES_FILES += res-leds.c res-toggle-leds.c res-device.c +REST_RESOURCES_FILES += res-sensors.c res-ble-advd.c + +PROJECTDIRS += $(REST_RESOURCES_DIR) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +PROJECT_SOURCEFILES += cetic-6lbr-client.c coap-server.c net-uart.c mqtt-client.c +PROJECT_SOURCEFILES += httpd-simple.c + +CONTIKI_WITH_IPV6 = 1 + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine +APPS += mqtt + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/cc26xx/cc26xx-web-demo/Makefile.target b/examples/cc26xx/cc26xx-web-demo/Makefile.target new file mode 100644 index 000000000..15890aa6a --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/Makefile.target @@ -0,0 +1 @@ +TARGET = srf06-cc26xx diff --git a/examples/cc26xx/cc26xx-web-demo/README.md b/examples/cc26xx/cc26xx-web-demo/README.md new file mode 100644 index 000000000..194336a56 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/README.md @@ -0,0 +1,169 @@ +CC26xx Web Demo Readme +====================== +This demo project combines a number of web-based applications aiming to +demonstrate the CC26xx capability. The applications are: + +* A network-based UART +* A client for [6lbr](http://cetic.github.io/6lbr/) +* A CoAP server +* An MQTT client +* A web server which can be used to display sensor readings but also to + configure MQTT functionality + +The example has been configured to run for both CC26xx-based boards: i) The +SensorTag 2.0 and ii) The Srf06EB with a CC26xx EM mounted on it. + +To build the example for the Srf, simply run `make`. To build for the tag, +run `make BOARD=sensortag`. Do not forget to `make clean` when switching +between the two platforms. + +You can disable some of those individual components by changing the respective +defines in `project-conf.h`. For instance, to disable the CoAP functionality, +set `#define CC26XX_WEB_DEMO_CONF_COAP_SERVER 0`. The web server cannot be +disabled, all other aforementioned applications can. + +Network UART (net-uart) +----------------------- +This example only makes sense if you are using the Srf or if you have taken +the sensortag out of its case and you have it connected over JTAG to the Srf. + +The net-uart does two things: + +* When you type a string to the UART console, the string will be sent verbatim + to a remote UDP port 7777 listener. This can be for example a netcat listener + on a linux or OS X PC: + `nc -6ulkw 1 7777` +* The net-uart also listens to UDP port 7777 and when it receives a string over + UDP, it will print it verbatim over UART. + +The example will initially send packets to a hard-coded IPv6 address. This can +be changed very easily by entering a different IPv6 address to the console. +Thus, when the serial input string is an IPv6 address, it will not be sent as +any other string would, but instead it will configure the example to send to a +different remote address. This new IPv6 address is not persistent across +device reboots. + +6lbr Client +----------- +This will periodically send a UDP packet to your 6lbr, containing network +information, which will be used by 6lbr to construct a network graph. To see +this in action, fire up a browser and navigate to the 6lbr web page. The +default address is http://[bbbb::100]. Once the page loads, click the 'sensors' +tab, as per the image below. + +![6lbr](img/6lbr-web.png) + +CoAP Server +----------- +For this functionality to work, you will need to install the +[Copper (Cu)](https://addons.mozilla.org/en-US/firefox/addon/copper-270430/) +addon to your browser. + +From the sensors tab in the 6lbr web page, click the 'coap' link in the line +corresponding to your CC26xx device. Once the addon fires up, select +".well-known/core" in the left pane and then hit the 'Get' button at the top. + +![CoAP Resources](img/coap-resources.png) + +The Device will respond with a list of all available CoAP resources. This list +will be different between the Srf and the SensorTag. The screenshot below shows +a (partial) list of resources exported by the SensorTag CoAP server. Select +a resource on the left pane and hit 'Get' to retrieve its value. Select +`lt/g` and hit 'Post' to toggle the green LED, `lt/r` for the red one. + +You can also use CoAP to enable/disable BLE advertisements! Select +`dev/ble_advd` and then hit the "Outgoing" button in the payload panel. Type in +the desired payload, which can be: + +* `mode=on|off` +* `name=` +* `interval=` + +or a combination of both delimited with an amp. For example, you can set as +payload `mode=on&name=My CC26xx Device 4&interval=5`. Once you have set the +payload, hit either the POST or PUT button. + +Bear in mind that you must set `name` at least once before enabling BLE +advertisements. If you fail to do so, the RF will refuse to enter BLE mode and +the CoAP engine will return 4.03 forbidden. The values of `name` and `interval` +persist across BLE on/off cycles, so you only have to set them once. The values +do _not_ persist through device powercycles. + +HTTPD +----- +Back on the 6lbr page, hit the 'web' link corresponding to your device. This +will take you to a web page served by the CC26xx. The HTTPD serves two pages: + +* index.html: Provides sensor readings and network information +* config.html: Can be used to configure the MQTT client (more below) + +In the navigation bar at the top there is also a third link, which will take +you directly to your device's page on IBM's quickstart service. + +IBM Quickstart / MQTT Client +---------------------------- +The MQTT client can be used to: + +* Publish sensor readings to an MQTT broker. +* Subscribe to a topic and as a result receive commands from an MQTT broker + +The device will try to connect to IBM's quickstart over NAT64, so you will +need a NAT64 gateway in your network to make this work. A guide on how to +setup NAT64 is out of scope here. If this is not an option for you, you can +configure the device to publish to a local MQTT broker over end-to-end IPv6. +See below on how to change the destination broker's address. + +By default the device will publish readings to IBM's quickstart service. The +publish messages include sensor readings but also some other information such +as device uptime in seconds and a message sequence number. Click the "IBM +Quickstart" link in the web page to go directly to your device's page +on Quickstart. After a few seconds, you will see something like this: + +![A SensorTag on IBM Quickstart](img/quickstart-sensortag.png) + +Sensor readings are only published if they have changed since the previous +reading (BatMon is an exception and always gets published). Additionally, you +can turn on/off individual readings from the config.html web page, as per the +figure below. + +![Sensor Readings Configuration](img/sensor-readings-config.png) + +Some of the MQTT client functionality can be configured even further: + +* You can change the broker IP and port. This is useful if you want to use your + own MQTT broker instead of IBM's quickstart. The example has been tested + successfully with [mosquitto](http://mosquitto.org/) +* You can change the publish interval. Recommended values are 10secs or higher. + You will not be allowed to set this to anything less than 5 seconds. +* If you want to use IBM's cloud service with a registered device, change + 'Org ID' and provide an 'Auth Token', which acts as a 'password', but bear in + mind that it gets transported in clear text, both over the web configuration + page as well as inside MQTT messages. +* The remaining configuration options are related to the content of MQTT + messages and in general you won't have to modify them. + +For the SensorTag, changes to the MQTT configuration get saved in external +flash and persist across device restarts. The same does not hold true for +Srf+EM builds. + +You can also subscribe to topics and receive commands, but this will only +work if you use "Org ID" != 'quickstart'. Thus, if you provide a different +Org ID (do not forget the auth token!), the device will subscribe to: + +`iot-2/cmd/+/fmt/json` + +You can then use this to toggle LEDs or to turn the buzzer on and off. +The buzzer is only available on the SensorTag. To do this, you can for example +use mosquitto client to publish to `iot-2/cmd/leds/fmt/json`. So, to turn +the buzzer on, you would do this: + +`mosquitto_pub -h -m "1" -t iot-2/cmd/buzz/fmt/json` + +Where `broker IP` should be replaced with the IP address of your mosquitto +broker (the one where you device has subscribed). Replace `-m "1'` with `-m "0"` +to turn the buzzer back off. Replace `buzz` with `leds` in the topic to change +the state of the LED. + +Bear in mind that, even though the topic suggests that messages are of json +format, they are in fact not. This was done in order to avoid linking a json +parser into the firmware. diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c new file mode 100644 index 000000000..91f921b9d --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -0,0 +1,893 @@ +/* + * 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-web-demo + * @{ + * + * \file + * Main module for the CC26XX web demo. Activates on-device resources, + * takes sensor readings periodically and caches them for all other modules + * to use. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-net.h" +#include "rest-engine.h" +#include "board-peripherals.h" +#include "lib/sensors.h" +#include "lib/list.h" +#include "sys/process.h" +#include "button-sensor.h" +#include "batmon-sensor.h" +#include "httpd-simple.h" +#include "cc26xx-web-demo.h" +#include "mqtt-client.h" +#include "coap-server.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(cetic_6lbr_client_process); +PROCESS(cc26xx_web_demo_process, "CC26XX Web Demo"); +/*---------------------------------------------------------------------------*/ +/* + * 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) + +struct ctimer batmon_timer; + +#if BOARD_SENSORTAG +struct ctimer bmp_timer, sht_timer, tmp_timer, opt_timer, mpu_timer; +#endif +/*---------------------------------------------------------------------------*/ +/* Provide visible feedback via LEDS while searching for a network */ +#define NO_NET_LED_DURATION (CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC >> 1) + +static struct etimer et; +static struct ctimer ct; +/*---------------------------------------------------------------------------*/ +process_event_t cc26xx_web_demo_publish_event; +process_event_t cc26xx_web_demo_config_loaded_event; +process_event_t cc26xx_web_demo_load_config_defaults; +/*---------------------------------------------------------------------------*/ +/* Saved settings on flash: store, offset, magic */ +#define CONFIG_FLASH_OFFSET 0 +#define CONFIG_MAGIC 0xCC265001 + +cc26xx_web_demo_config_t cc26xx_web_demo_config; +/*---------------------------------------------------------------------------*/ +/* A cache of sensor values. Updated periodically or upon key press */ +LIST(sensor_list); +/*---------------------------------------------------------------------------*/ +/* The objects representing sensors used in this demo */ +#define DEMO_SENSOR(name, type, descr, xml_element, form_field, units) \ + cc26xx_web_demo_sensor_reading_t name##_reading = \ + { NULL, 0, 0, descr, xml_element, form_field, units, type, 1, 1 } + +/* CC26xx sensors */ +DEMO_SENSOR(batmon_temp, CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, + "Battery Temp", "battery-temp", "batmon_temp", + CC26XX_WEB_DEMO_UNIT_TEMP); +DEMO_SENSOR(batmon_volt, CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, + "Battery Volt", "battery-volt", "batmon_volt", + CC26XX_WEB_DEMO_UNIT_VOLT); + +/* Sensortag sensors */ +#if BOARD_SENSORTAG +DEMO_SENSOR(bmp_pres, CC26XX_WEB_DEMO_SENSOR_BMP_PRES, + "Air Pressure", "air-pressure", "bmp_pres", + CC26XX_WEB_DEMO_UNIT_PRES); +DEMO_SENSOR(bmp_temp, CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, + "Air Temp", "air-temp", "bmp_temp", + CC26XX_WEB_DEMO_UNIT_TEMP); +DEMO_SENSOR(sht_temp, CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, + "SHT Temp", "sht-temp", "sht_temp", + CC26XX_WEB_DEMO_UNIT_TEMP); +DEMO_SENSOR(sht_hum, CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, + "SHT Humidity", "sht-humidity", "sht_hum", + CC26XX_WEB_DEMO_UNIT_HUMIDITY); +DEMO_SENSOR(tmp_amb, CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, + "Ambient Temp", "ambient-temp", "tmp_amb", + CC26XX_WEB_DEMO_UNIT_TEMP); +DEMO_SENSOR(tmp_obj, CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, + "Object Temp", "object-temp", "tmp_obj", + CC26XX_WEB_DEMO_UNIT_TEMP); +DEMO_SENSOR(opt, CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, + "Light", "light", "light", + CC26XX_WEB_DEMO_UNIT_LIGHT); + +/* MPU Readings */ +DEMO_SENSOR(mpu_acc_x, CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, + "Acc X", "acc-x", "acc_x", + CC26XX_WEB_DEMO_UNIT_ACC); +DEMO_SENSOR(mpu_acc_y, CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, + "Acc Y", "acc-y", "acc_y", + CC26XX_WEB_DEMO_UNIT_ACC); +DEMO_SENSOR(mpu_acc_z, CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, + "Acc Z", "acc-z", "acc_z", + CC26XX_WEB_DEMO_UNIT_ACC); + +DEMO_SENSOR(mpu_gyro_x, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, + "Gyro X", "gyro-x", "gyro_x", + CC26XX_WEB_DEMO_UNIT_GYRO); +DEMO_SENSOR(mpu_gyro_y, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, + "Gyro Y", "gyro-y", "gyro_y", + CC26XX_WEB_DEMO_UNIT_GYRO); +DEMO_SENSOR(mpu_gyro_z, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, + "Gyro Z", "gyro-z", "gyro_Z", + CC26XX_WEB_DEMO_UNIT_GYRO); +#endif +/*---------------------------------------------------------------------------*/ +#if BOARD_SENSORTAG +static void init_bmp_reading(void *data); +static void init_light_reading(void *data); +static void init_sht_reading(void *data); +static void init_tmp_reading(void *data); +static void init_mpu_reading(void *data); +#endif +/*---------------------------------------------------------------------------*/ +static void +publish_led_off(void *d) +{ + leds_off(CC26XX_WEB_DEMO_STATUS_LED); +} +/*---------------------------------------------------------------------------*/ +static void +save_config() +{ + /* Dump current running config to flash */ +#if BOARD_SENSORTAG + int rv; + cc26xx_web_demo_sensor_reading_t *reading = NULL; + + rv = ext_flash_open(); + + if(!rv) { + printf("Could not open flash to save config\n"); + ext_flash_close(); + return; + } + + rv = ext_flash_erase(CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t)); + + if(!rv) { + printf("Error erasing flash\n"); + } else { + cc26xx_web_demo_config.magic = CONFIG_MAGIC; + cc26xx_web_demo_config.len = sizeof(cc26xx_web_demo_config_t); + cc26xx_web_demo_config.sensors_bitmap = 0; + + for(reading = list_head(sensor_list); + reading != NULL; + reading = list_item_next(reading)) { + if(reading->publish) { + cc26xx_web_demo_config.sensors_bitmap |= (1 << reading->type); + } + } + + rv = ext_flash_write(CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t), + (uint8_t *)&cc26xx_web_demo_config); + if(!rv) { + printf("Error saving config\n"); + } + } + + ext_flash_close(); +#endif +} +/*---------------------------------------------------------------------------*/ +static void +load_config() +{ +#if BOARD_SENSORTAG + /* Read from flash into a temp buffer */ + cc26xx_web_demo_config_t tmp_cfg; + cc26xx_web_demo_sensor_reading_t *reading = NULL; + + int rv = ext_flash_open(); + + if(!rv) { + printf("Could not open flash to load config\n"); + ext_flash_close(); + return; + } + + rv = ext_flash_read(CONFIG_FLASH_OFFSET, sizeof(tmp_cfg), + (uint8_t *)&tmp_cfg); + + ext_flash_close(); + + if(!rv) { + printf("Error loading config\n"); + return; + } + + if(tmp_cfg.magic == CONFIG_MAGIC && tmp_cfg.len == sizeof(tmp_cfg)) { + memcpy(&cc26xx_web_demo_config, &tmp_cfg, sizeof(cc26xx_web_demo_config)); + } + + for(reading = list_head(sensor_list); + reading != NULL; + reading = list_item_next(reading)) { + if(cc26xx_web_demo_config.sensors_bitmap & (1 << reading->type)) { + reading->publish = 1; + } else { + reading->publish = 0; + snprintf(reading->converted, CC26XX_WEB_DEMO_CONVERTED_LEN, "\"N/A\""); + } + } +#endif +} +/*---------------------------------------------------------------------------*/ +/* Don't start everything here, we need to dictate order of initialisation */ +AUTOSTART_PROCESSES(&cc26xx_web_demo_process); +/*---------------------------------------------------------------------------*/ +int +cc26xx_web_demo_ipaddr_sprintf(char *buf, uint8_t buf_len, + const uip_ipaddr_t *addr) +{ + uint16_t a; + uint8_t len = 0; + int i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + len += snprintf(&buf[len], buf_len - len, "::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + len += snprintf(&buf[len], buf_len - len, ":"); + } + len += snprintf(&buf[len], buf_len - len, "%x", a); + } + } + + return len; +} +/*---------------------------------------------------------------------------*/ +const cc26xx_web_demo_sensor_reading_t * +cc26xx_web_demo_sensor_lookup(int sens_type) +{ + cc26xx_web_demo_sensor_reading_t *reading = NULL; + + for(reading = list_head(sensor_list); + reading != NULL; + reading = list_item_next(reading)) { + if(reading->type == sens_type) { + return reading; + } + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +const cc26xx_web_demo_sensor_reading_t * +cc26xx_web_demo_sensor_first() +{ + return list_head(sensor_list); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_web_demo_restore_defaults(void) +{ + cc26xx_web_demo_sensor_reading_t *reading = NULL; + + leds_on(LEDS_ALL); + + for(reading = list_head(sensor_list); + reading != NULL; + reading = list_item_next(reading)) { + reading->publish = 1; + } + +#if CC26XX_WEB_DEMO_MQTT_CLIENT + process_post_synch(&mqtt_client_process, + cc26xx_web_demo_load_config_defaults, NULL); +#endif + +#if CC26XX_WEB_DEMO_NET_UART + process_post_synch(&net_uart_process, cc26xx_web_demo_load_config_defaults, + NULL); +#endif + + save_config(); + + leds_off(LEDS_ALL); +} +/*---------------------------------------------------------------------------*/ +static int +defaults_post_handler(char *key, int key_len, char *val, int val_len) +{ + if(key_len != strlen("defaults") || + strncasecmp(key, "defaults", strlen("defaults")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + cc26xx_web_demo_restore_defaults(); + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +static int +sensor_readings_handler(char *key, int key_len, char *val, int val_len) +{ + cc26xx_web_demo_sensor_reading_t *reading = NULL; + int rv; + + for(reading = list_head(sensor_list); + reading != NULL; + reading = list_item_next(reading)) { + if(key_len == strlen(reading->form_field) && + strncmp(reading->form_field, key, strlen(key)) == 0) { + + rv = atoi(val); + + /* Be pedantic: only accept 0 and 1, not just any non-zero value */ + if(rv == 0) { + reading->publish = 0; + snprintf(reading->converted, CC26XX_WEB_DEMO_CONVERTED_LEN, "\"N/A\""); + } else if(rv == 1) { + reading->publish = 1; + } else { + return HTTPD_SIMPLE_POST_HANDLER_ERROR; + } + + return HTTPD_SIMPLE_POST_HANDLER_OK; + } + } + + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; +} +/*---------------------------------------------------------------------------*/ +HTTPD_SIMPLE_POST_HANDLER(sensor, sensor_readings_handler); +HTTPD_SIMPLE_POST_HANDLER(defaults, defaults_post_handler); +/*---------------------------------------------------------------------------*/ +static void +get_batmon_reading(void *data) +{ + int value; + char *buf; + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + + if(batmon_temp_reading.publish) { + value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP); + if(value != CC26XX_SENSOR_READING_ERROR) { + batmon_temp_reading.raw = value; + + buf = batmon_temp_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value >> 2, + (value & 0x00000003) * 25); + } + } + + if(batmon_volt_reading.publish) { + value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); + if(value != CC26XX_SENSOR_READING_ERROR) { + batmon_volt_reading.raw = value; + + buf = batmon_volt_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d", (value * 125) >> 5); + } + } + + ctimer_set(&batmon_timer, next, get_batmon_reading, NULL); +} +/*---------------------------------------------------------------------------*/ +#if BOARD_SENSORTAG +/*---------------------------------------------------------------------------*/ +static void +compare_and_update(cc26xx_web_demo_sensor_reading_t *reading) +{ + if(reading->last == reading->raw) { + reading->changed = 0; + } else { + reading->last = reading->raw; + reading->changed = 1; + } +} +/*---------------------------------------------------------------------------*/ +static void +print_mpu_reading(int reading, char *buf) +{ + char *loc_buf = buf; + + if(reading < 0) { + sprintf(loc_buf, "-"); + reading = -reading; + loc_buf++; + } + + sprintf(loc_buf, "%d.%02d", reading / 100, reading % 100); +} +/*---------------------------------------------------------------------------*/ +static void +get_bmp_reading() +{ + int value; + char *buf; + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + + if(bmp_pres_reading.publish) { + value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS); + if(value != CC26XX_SENSOR_READING_ERROR) { + bmp_pres_reading.raw = value; + + compare_and_update(&bmp_pres_reading); + + buf = bmp_pres_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, + value % 100); + } + } + + if(bmp_temp_reading.publish) { + value = bmp_280_sensor.value(BMP_280_SENSOR_TYPE_TEMP); + if(value != CC26XX_SENSOR_READING_ERROR) { + bmp_temp_reading.raw = value; + + compare_and_update(&bmp_temp_reading); + + buf = bmp_temp_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, + value % 100); + } + } + + SENSORS_DEACTIVATE(bmp_280_sensor); + + ctimer_set(&bmp_timer, next, init_bmp_reading, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +get_tmp_reading() +{ + int value; + char *buf; + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + + if(tmp_amb_reading.publish || tmp_obj_reading.publish) { + if(tmp_007_sensor.value(TMP_007_SENSOR_TYPE_ALL) == + CC26XX_SENSOR_READING_ERROR) { + + SENSORS_DEACTIVATE(tmp_007_sensor); + ctimer_set(&tmp_timer, next, init_tmp_reading, NULL); + } + } + + if(tmp_amb_reading.publish) { + value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_AMBIENT); + tmp_amb_reading.raw = value; + + compare_and_update(&tmp_amb_reading); + + buf = tmp_amb_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%03d", value / 1000, + value % 1000); + } + + if(tmp_obj_reading.publish) { + value = tmp_007_sensor.value(TMP_007_SENSOR_TYPE_OBJECT); + tmp_obj_reading.raw = value; + + compare_and_update(&tmp_obj_reading); + + buf = tmp_obj_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%03d", value / 1000, + value % 1000); + } + + SENSORS_DEACTIVATE(tmp_007_sensor); + + ctimer_set(&tmp_timer, next, init_tmp_reading, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +get_sht_reading() +{ + int value; + char *buf; + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + + if(sht_temp_reading.publish) { + value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP); + if(value != CC26XX_SENSOR_READING_ERROR) { + sht_temp_reading.raw = value; + + compare_and_update(&sht_temp_reading); + + buf = sht_temp_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, + value % 100); + } + } + + if(sht_hum_reading.publish) { + value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY); + if(value != CC26XX_SENSOR_READING_ERROR) { + sht_hum_reading.raw = value; + + compare_and_update(&sht_hum_reading); + + buf = sht_hum_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, + value % 100); + } + } + + ctimer_set(&sht_timer, next, init_sht_reading, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +get_light_reading() +{ + int value; + char *buf; + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + + value = opt_3001_sensor.value(0); + + SENSORS_DEACTIVATE(opt_3001_sensor); + + if(value != CC26XX_SENSOR_READING_ERROR) { + opt_reading.raw = value; + + compare_and_update(&opt_reading); + + buf = opt_reading.converted; + memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, + value % 100); + } + + ctimer_set(&opt_timer, next, init_light_reading, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +get_mpu_reading() +{ + clock_time_t next = SENSOR_READING_PERIOD + + (random_rand() % SENSOR_READING_RANDOM); + int raw; + + if(mpu_gyro_x_reading.publish) { + raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_X); + if(raw != CC26XX_SENSOR_READING_ERROR) { + mpu_gyro_x_reading.raw = raw; + } + } + + if(mpu_gyro_y_reading.publish) { + raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Y); + if(raw != CC26XX_SENSOR_READING_ERROR) { + mpu_gyro_y_reading.raw = raw; + } + } + + if(mpu_gyro_z_reading.publish) { + raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_GYRO_Z); + if(raw != CC26XX_SENSOR_READING_ERROR) { + mpu_gyro_z_reading.raw = raw; + } + } + + if(mpu_acc_x_reading.publish) { + raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_X); + if(raw != CC26XX_SENSOR_READING_ERROR) { + mpu_acc_x_reading.raw = raw; + } + } + + if(mpu_acc_y_reading.publish) { + raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Y); + if(raw != CC26XX_SENSOR_READING_ERROR) { + mpu_acc_y_reading.raw = raw; + } + } + + if(mpu_acc_z_reading.publish) { + raw = mpu_9250_sensor.value(MPU_9250_SENSOR_TYPE_ACC_Z); + if(raw != CC26XX_SENSOR_READING_ERROR) { + mpu_acc_z_reading.raw = raw; + } + } + + SENSORS_DEACTIVATE(mpu_9250_sensor); + + if(mpu_gyro_x_reading.publish) { + compare_and_update(&mpu_gyro_x_reading); + memset(mpu_gyro_x_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + print_mpu_reading(mpu_gyro_x_reading.raw, mpu_gyro_x_reading.converted); + } + + if(mpu_gyro_y_reading.publish) { + compare_and_update(&mpu_gyro_y_reading); + memset(mpu_gyro_y_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + print_mpu_reading(mpu_gyro_y_reading.raw, mpu_gyro_y_reading.converted); + } + + if(mpu_gyro_z_reading.publish) { + compare_and_update(&mpu_gyro_z_reading); + memset(mpu_gyro_z_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + print_mpu_reading(mpu_gyro_z_reading.raw, mpu_gyro_z_reading.converted); + } + + if(mpu_acc_x_reading.publish) { + compare_and_update(&mpu_acc_x_reading); + memset(mpu_acc_x_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + print_mpu_reading(mpu_acc_x_reading.raw, mpu_acc_x_reading.converted); + } + + if(mpu_acc_y_reading.publish) { + compare_and_update(&mpu_acc_y_reading); + memset(mpu_acc_y_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + print_mpu_reading(mpu_acc_y_reading.raw, mpu_acc_y_reading.converted); + } + + if(mpu_acc_z_reading.publish) { + compare_and_update(&mpu_acc_z_reading); + memset(mpu_acc_z_reading.converted, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); + print_mpu_reading(mpu_acc_z_reading.raw, mpu_acc_z_reading.converted); + } + + /* We only use the single timer */ + ctimer_set(&mpu_timer, next, init_mpu_reading, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +init_tmp_reading(void *data) +{ + if(tmp_amb_reading.publish || tmp_obj_reading.publish) { + SENSORS_ACTIVATE(tmp_007_sensor); + } else { + ctimer_set(&tmp_timer, CLOCK_SECOND, init_tmp_reading, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +init_bmp_reading(void *data) +{ + if(bmp_pres_reading.publish || bmp_temp_reading.publish) { + SENSORS_ACTIVATE(bmp_280_sensor); + } else { + ctimer_set(&bmp_timer, CLOCK_SECOND, init_bmp_reading, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +init_sht_reading(void *data) +{ + if(sht_hum_reading.publish || sht_temp_reading.publish) { + SENSORS_ACTIVATE(sht_21_sensor); + } else { + ctimer_set(&sht_timer, CLOCK_SECOND, init_sht_reading, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +init_light_reading(void *data) +{ + if(opt_reading.publish) { + SENSORS_ACTIVATE(opt_3001_sensor); + } else { + ctimer_set(&opt_timer, CLOCK_SECOND, init_light_reading, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +init_mpu_reading(void *data) +{ + int readings_bitmap = 0; + + if(mpu_acc_x_reading.publish || mpu_acc_y_reading.publish || + mpu_acc_z_reading.publish) { + readings_bitmap |= MPU_9250_SENSOR_TYPE_ACC; + } + + if(mpu_gyro_x_reading.publish || mpu_gyro_y_reading.publish || + mpu_gyro_z_reading.publish) { + readings_bitmap |= MPU_9250_SENSOR_TYPE_GYRO; + } + + if(readings_bitmap) { + mpu_9250_sensor.configure(SENSORS_ACTIVE, readings_bitmap); + } else { + ctimer_set(&mpu_timer, CLOCK_SECOND, init_mpu_reading, NULL); + } +} +#endif +/*---------------------------------------------------------------------------*/ +static void +init_sensor_readings(void) +{ + /* + * Make a first pass and get all initial sensor readings. This will also + * trigger periodic value updates + */ + get_batmon_reading(NULL); + +#if BOARD_SENSORTAG + init_bmp_reading(NULL); + init_light_reading(NULL); + init_sht_reading(NULL); + init_tmp_reading(NULL); + init_mpu_reading(NULL); +#endif /* BOARD_SENSORTAG */ + + return; +} +/*---------------------------------------------------------------------------*/ +static void +init_sensors(void) +{ + + list_add(sensor_list, &batmon_temp_reading); + list_add(sensor_list, &batmon_volt_reading); + SENSORS_ACTIVATE(batmon_sensor); + +#if BOARD_SENSORTAG + list_add(sensor_list, &bmp_pres_reading); + list_add(sensor_list, &bmp_temp_reading); + + list_add(sensor_list, &tmp_obj_reading); + list_add(sensor_list, &tmp_amb_reading); + + list_add(sensor_list, &opt_reading); + + list_add(sensor_list, &sht_hum_reading); + list_add(sensor_list, &sht_temp_reading); + + list_add(sensor_list, &mpu_acc_x_reading); + list_add(sensor_list, &mpu_acc_y_reading); + list_add(sensor_list, &mpu_acc_z_reading); + list_add(sensor_list, &mpu_gyro_x_reading); + list_add(sensor_list, &mpu_gyro_y_reading); + list_add(sensor_list, &mpu_gyro_z_reading); + + SENSORS_ACTIVATE(reed_relay_sensor); +#endif +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc26xx_web_demo_process, ev, data) +{ + PROCESS_BEGIN(); + + printf("CC26XX Web Demo Process\n"); + + init_sensors(); + + cc26xx_web_demo_publish_event = process_alloc_event(); + cc26xx_web_demo_config_loaded_event = process_alloc_event(); + cc26xx_web_demo_load_config_defaults = process_alloc_event(); + + /* Start all other (enabled) processes first */ + process_start(&httpd_simple_process, NULL); +#if CC26XX_WEB_DEMO_COAP_SERVER + process_start(&coap_server_process, NULL); +#endif + +#if CC26XX_WEB_DEMO_6LBR_CLIENT + process_start(&cetic_6lbr_client_process, NULL); +#endif + +#if CC26XX_WEB_DEMO_MQTT_CLIENT + process_start(&mqtt_client_process, NULL); +#endif + +#if CC26XX_WEB_DEMO_NET_UART + process_start(&net_uart_process, NULL); +#endif + + /* + * Now that processes have set their own config default values, set our + * own defaults and restore saved config from flash... + */ + cc26xx_web_demo_config.sensors_bitmap = 0xFFFFFFFF; /* all on by default */ + load_config(); + + /* + * Notify all other processes (basically the ones in this demo) that the + * configuration has been loaded from flash, in case they care + */ + process_post(PROCESS_BROADCAST, cc26xx_web_demo_config_loaded_event, NULL); + + init_sensor_readings(); + + httpd_simple_register_post_handler(&sensor_handler); + httpd_simple_register_post_handler(&defaults_handler); + + etimer_set(&et, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC); + + /* + * Update all sensor readings on a configurable sensors_event + * (e.g a button press / or reed trigger) + */ + while(1) { + if(ev == sensors_event && data == CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) { + if((CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER)->value( + BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) { + printf("Restoring defaults!\n"); + cc26xx_web_demo_restore_defaults(); + } else { + init_sensor_readings(); + + process_post(PROCESS_BROADCAST, cc26xx_web_demo_publish_event, NULL); + } + } else if(ev == PROCESS_EVENT_TIMER && etimer_expired(&et)) { + if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) { + leds_on(CC26XX_WEB_DEMO_STATUS_LED); + ctimer_set(&ct, NO_NET_LED_DURATION, publish_led_off, NULL); + etimer_set(&et, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC); + } + } else if(ev == httpd_simple_event_new_config) { + save_config(); +#if BOARD_SENSORTAG + } 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 == &sht_21_sensor) { + get_sht_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(); +#endif + } + + PROCESS_YIELD(); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h new file mode 100644 index 000000000..89bf91d2b --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h @@ -0,0 +1,210 @@ +/* + * 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-examples + * @{ + * + * \defgroup cc26xx-web-demo CC26xx Web Demo + * @{ + * + * An example demonstrating: + * * how to use a CC26XX-powered node in a deployment driven by a 6LBR + * * how to expose on-device sensors as CoAP resources + * * how to build a small web page which reports networking and sensory data + * * how to configure functionality through the aforementioned web page using + * HTTP POST requests + * * a network-based UART + * + * \file + * Main header file for the CC26XX web demo. + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC26XX_WEB_DEMO_H_ +#define CC26XX_WEB_DEMO_H_ +/*---------------------------------------------------------------------------*/ +#include "dev/leds.h" +#include "sys/process.h" +#include "mqtt-client.h" +#include "net-uart.h" + +#include +/*---------------------------------------------------------------------------*/ +#ifdef CC26XX_WEB_DEMO_CONF_MQTT_CLIENT +#define CC26XX_WEB_DEMO_MQTT_CLIENT CC26XX_WEB_DEMO_CONF_MQTT_CLIENT +#else +#define CC26XX_WEB_DEMO_MQTT_CLIENT 1 +#endif + +#ifdef CC26XX_WEB_DEMO_CONF_6LBR_CLIENT +#define CC26XX_WEB_DEMO_6LBR_CLIENT CC26XX_WEB_DEMO_CONF_6LBR_CLIENT +#else +#define CC26XX_WEB_DEMO_6LBR_CLIENT 1 +#endif + +#ifdef CC26XX_WEB_DEMO_CONF_COAP_SERVER +#define CC26XX_WEB_DEMO_COAP_SERVER CC26XX_WEB_DEMO_CONF_COAP_SERVER +#else +#define CC26XX_WEB_DEMO_COAP_SERVER 1 +#endif + +#ifdef CC26XX_WEB_DEMO_CONF_NET_UART +#define CC26XX_WEB_DEMO_NET_UART CC26XX_WEB_DEMO_CONF_NET_UART +#else +#define CC26XX_WEB_DEMO_NET_UART 1 +#endif +/*---------------------------------------------------------------------------*/ +/* User configuration */ +/* Take a sensor reading on button press */ +#define CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER &button_left_sensor + +/* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */ +#define CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN 20 + +#if BOARD_SENSORTAG +/* Force an MQTT publish on sensor event */ +#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &reed_relay_sensor +#else +#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_right_sensor +#endif + +#define CC26XX_WEB_DEMO_STATUS_LED LEDS_GREEN +/*---------------------------------------------------------------------------*/ +/* A timeout used when waiting to connect to a network */ +#define CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC (CLOCK_SECOND >> 3) +/*---------------------------------------------------------------------------*/ +/* Default configuration values */ +#define CC26XX_WEB_DEMO_DEFAULT_ORG_ID "quickstart" +#define CC26XX_WEB_DEMO_DEFAULT_TYPE_ID "cc26xx" +#define CC26XX_WEB_DEMO_DEFAULT_EVENT_TYPE_ID "status" +#define CC26XX_WEB_DEMO_DEFAULT_SUBSCRIBE_CMD_TYPE "+" +#define CC26XX_WEB_DEMO_DEFAULT_BROKER_PORT 1883 +#define CC26XX_WEB_DEMO_DEFAULT_PUBLISH_INTERVAL (30 * CLOCK_SECOND) +#define CC26XX_WEB_DEMO_DEFAULT_KEEP_ALIVE_TIMER 60 +#define CC26XX_WEB_DEMO_DEFAULT_RSSI_MEAS_INTERVAL (CLOCK_SECOND * 30) +/*---------------------------------------------------------------------------*/ +/* + * You normally won't have to change anything from here onwards unless you are + * extending the example + */ +/*---------------------------------------------------------------------------*/ +/* Sensor types */ +#define CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP 0 +#define CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT 1 +#define CC26XX_WEB_DEMO_SENSOR_BMP_PRES 2 +#define CC26XX_WEB_DEMO_SENSOR_BMP_TEMP 3 +#define CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT 4 +#define CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT 5 +#define CC26XX_WEB_DEMO_SENSOR_SHT_TEMP 6 +#define CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY 7 +#define CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT 8 +#define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X 9 +#define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y 10 +#define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z 11 +#define CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X 12 +#define CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y 13 +#define CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z 14 +/*---------------------------------------------------------------------------*/ +extern process_event_t cc26xx_web_demo_publish_event; +extern process_event_t cc26xx_web_demo_config_loaded_event; +extern process_event_t cc26xx_web_demo_load_config_defaults; +/*---------------------------------------------------------------------------*/ +#define CC26XX_WEB_DEMO_UNIT_TEMP "C" +#define CC26XX_WEB_DEMO_UNIT_VOLT "mV" +#define CC26XX_WEB_DEMO_UNIT_PRES "hPa" +#define CC26XX_WEB_DEMO_UNIT_HUMIDITY "%RH" +#define CC26XX_WEB_DEMO_UNIT_LIGHT "lux" +#define CC26XX_WEB_DEMO_UNIT_ACC "G" +#define CC26XX_WEB_DEMO_UNIT_GYRO "deg per sec" +/*---------------------------------------------------------------------------*/ +/* A data type for sensor readings, internally stored in a linked list */ +#define CC26XX_WEB_DEMO_CONVERTED_LEN 12 + +typedef struct cc26xx_web_demo_sensor_reading { + struct cc26xx_web_demo_sensor_reading *next; + int raw; + int last; + const char *descr; + const char *xml_element; + const char *form_field; + char *units; + uint8_t type; + uint8_t publish; + uint8_t changed; + char converted[CC26XX_WEB_DEMO_CONVERTED_LEN]; +} cc26xx_web_demo_sensor_reading_t; +/*---------------------------------------------------------------------------*/ +/* Global configuration */ +typedef struct cc26xx_web_demo_config_s { + uint32_t magic; + int len; + uint32_t sensors_bitmap; + mqtt_client_config_t mqtt_config; + net_uart_config_t net_uart; +} cc26xx_web_demo_config_t; + +extern cc26xx_web_demo_config_t cc26xx_web_demo_config; +/*---------------------------------------------------------------------------*/ +/** + * \brief Performs a lookup for a reading of a specific type of sensor + * \param sens_type CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP... + * \return A pointer to the reading data structure or NULL + */ +const cc26xx_web_demo_sensor_reading_t *cc26xx_web_demo_sensor_lookup(int sens_type); + +/** + * \brief Returns the first available sensor reading + * \return A pointer to the reading data structure or NULL + */ +const cc26xx_web_demo_sensor_reading_t *cc26xx_web_demo_sensor_first(void); + +/** + * \brief Print an IPv6 address into a buffer + * \param buf A pointer to the buffer where this function will print the IPv6 + * address + * \param buf_len the length of the buffer + * \param addr A pointer to the IPv6 address + * \return The number of bytes written to the buffer + * + * It is the caller's responsibility to allocate enough space for buf + */ +int cc26xx_web_demo_ipaddr_sprintf(char *buf, uint8_t buf_len, + const uip_ipaddr_t *addr); + +/** + * \brief Resets the example to a default configuration + */ +void cc26xx_web_demo_restore_defaults(void); +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_WEB_DEMO_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c b/examples/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c new file mode 100644 index 000000000..68a890390 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c @@ -0,0 +1,197 @@ +/* + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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-web-demo + * @{ + * + * \file + * An implementation of a 6LBR UDP client. Is used to populate the 6LBR + * web server's 'sensors' tab + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#include "net/ip/uip-debug.h" +/*---------------------------------------------------------------------------*/ +#ifndef CETIC_6LBR_NODE_INFO_PORT +#define CETIC_6LBR_NODE_INFO_PORT 3000 +#endif + +#define MAX_PAYLOAD_LEN 40 +#define MSG_INTERVAL (60 * CLOCK_SECOND) +/*---------------------------------------------------------------------------*/ +static struct uip_udp_conn *client_conn = NULL; +static struct etimer et; +static uip_ip6addr_t dest_addr; +/*---------------------------------------------------------------------------*/ +PROCESS(cetic_6lbr_client_process, "6LBR Client Process"); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + char *str; + + if(uip_newdata()) { + str = uip_appdata; + str[uip_datalen()] = '\0'; + PRINTF("Response from the server: '%s'\n", str); + } +} +/*---------------------------------------------------------------------------*/ +static char * +add_ipaddr(char *buf, const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f; + char *p = buf; + + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + p += sprintf(p, "::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + p += sprintf(p, ":"); + } + p += sprintf(p, "%04x", a); + } + } + return p; +} +/*---------------------------------------------------------------------------*/ +static void +timeout_handler(void) +{ + static int seq_id; + char buf[MAX_PAYLOAD_LEN]; + int i; + uip_ip6addr_t *globaladdr = NULL; + uint16_t dest_port = CETIC_6LBR_NODE_INFO_PORT; + int has_dest = 0; + rpl_dag_t *dag; + + uip_ds6_addr_t *addr_desc = uip_ds6_get_global(ADDR_PREFERRED); + if(addr_desc != NULL) { + globaladdr = &addr_desc->ipaddr; + dag = rpl_get_any_dag(); + if(dag) { + uip_ipaddr_copy(&dest_addr, globaladdr); + memcpy(&dest_addr.u8[8], &dag->dag_id.u8[8], sizeof(uip_ipaddr_t) / 2); + has_dest = 1; + } + } + + if(has_dest) { + if(client_conn == NULL) { + PRINTF("UDP-CLIENT: address destination: "); + PRINT6ADDR(&dest_addr); + PRINTF("\n"); + client_conn = udp_new(&dest_addr, UIP_HTONS(dest_port), NULL); + + if(client_conn != NULL) { + PRINTF("Created a connection with the server "); + PRINT6ADDR(&client_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); + } else { + PRINTF("Could not open connection\n"); + } + } else { + if(memcmp(&client_conn->ripaddr, &dest_addr, sizeof(uip_ipaddr_t)) != 0) { + PRINTF("UDP-CLIENT: new address destination: "); + PRINT6ADDR(&dest_addr); + PRINTF("\n"); + uip_udp_remove(client_conn); + client_conn = udp_new(&dest_addr, UIP_HTONS(dest_port), NULL); + if(client_conn != NULL) { + PRINTF("Created a connection with the server "); + PRINT6ADDR(&client_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); + } else { + PRINTF("Could not open connection\n"); + } + } + } + if(client_conn != NULL) { + PRINTF("Client sending to: "); + PRINT6ADDR(&client_conn->ripaddr); + i = sprintf(buf, "%d | ", ++seq_id); + dag = rpl_get_any_dag(); + if(dag && dag->instance->def_route) { + add_ipaddr(buf + i, &dag->instance->def_route->ipaddr); + } else { + sprintf(buf + i, "(null)"); + } + PRINTF(" (msg: %s)\n", buf); + uip_udp_packet_send(client_conn, buf, strlen(buf)); + } else { + PRINTF("No connection created\n"); + } + } else { + PRINTF("No address configured\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cetic_6lbr_client_process, ev, data) +{ + + PROCESS_BEGIN(); + + printf("6LBR Client Process\n"); + + memset(&dest_addr, 0, sizeof(uip_ipaddr_t)); + + etimer_set(&et, MSG_INTERVAL); + while(1) { + PROCESS_YIELD(); + if(etimer_expired(&et)) { + timeout_handler(); + etimer_set(&et, MSG_INTERVAL); + } else if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/coap-server.c b/examples/cc26xx/cc26xx-web-demo/coap-server.c new file mode 100644 index 000000000..65d748707 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/coap-server.c @@ -0,0 +1,157 @@ +/* + * 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-web-demo + * @{ + * + * \file + * A CC26XX-specific CoAP server + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-net.h" +#include "rest-engine.h" +#include "board-peripherals.h" +#include "dev/cc26xx-rf.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/* Common resources */ +extern resource_t res_leds; + +extern resource_t res_batmon_temp; +extern resource_t res_batmon_volt; + +extern resource_t res_device_sw; +extern resource_t res_device_hw; +extern resource_t res_device_uptime; +extern resource_t res_device_cfg_reset; + +#if CC26XX_RF_BLE_SUPPORT +extern resource_t res_ble_advd; +#endif + +/* Board-specific resources */ +#if BOARD_SENSORTAG +extern resource_t res_bmp280_temp; +extern resource_t res_bmp280_press; +extern resource_t res_tmp007_amb; +extern resource_t res_tmp007_obj; +extern resource_t res_sht21_temp; +extern resource_t res_sht21_hum; +extern resource_t res_opt3001_light; +extern resource_t res_mpu_acc_x; +extern resource_t res_mpu_acc_y; +extern resource_t res_mpu_acc_z; +extern resource_t res_mpu_gyro_x; +extern resource_t res_mpu_gyro_y; +extern resource_t res_mpu_gyro_z; +extern resource_t res_toggle_red; +extern resource_t res_toggle_green; +#else +extern resource_t res_toggle_red; +extern resource_t res_toggle_green; +extern resource_t res_toggle_orange; +extern resource_t res_toggle_yellow; +#endif +/*---------------------------------------------------------------------------*/ +const char *coap_server_not_found_msg = "Resource not found"; +const char *coap_server_supported_msg = "Supported:" + "text/plain," + "application/json," + "application/xml"; +/*---------------------------------------------------------------------------*/ +static void +start_board_resources(void) +{ +#if BOARD_SENSORTAG + rest_activate_resource(&res_bmp280_temp, "sen/bar/temp"); + rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); + rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); + rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); + rest_activate_resource(&res_sht21_temp, "sen/sht/t"); + rest_activate_resource(&res_sht21_hum, "sen/sht/h"); + rest_activate_resource(&res_opt3001_light, "sen/opt/light"); + rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); + rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); + rest_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); + rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); + rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); + rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); + rest_activate_resource(&res_leds, "lt"); + rest_activate_resource(&res_toggle_green, "lt/g"); + rest_activate_resource(&res_toggle_red, "lt/r"); +#elif BOARD_SMARTRF06EB + rest_activate_resource(&res_leds, "lt"); + rest_activate_resource(&res_toggle_red, "lt/r"); + rest_activate_resource(&res_toggle_yellow, "lt/y"); + rest_activate_resource(&res_toggle_green, "lt/g"); + rest_activate_resource(&res_toggle_orange, "lt/o"); +#endif +} +/*---------------------------------------------------------------------------*/ +PROCESS(coap_server_process, "CC26XX CoAP Server"); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_server_process, ev, data) +{ + PROCESS_BEGIN(); + + printf("CC26XX CoAP Server\n"); + + /* Initialize the REST engine. */ + rest_init_engine(); + + rest_activate_resource(&res_batmon_temp, "sen/batmon/temp"); + rest_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); + + rest_activate_resource(&res_device_hw, "dev/mdl/hw"); + rest_activate_resource(&res_device_sw, "dev/mdl/sw"); + rest_activate_resource(&res_device_uptime, "dev/uptime"); + rest_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); + +#if CC26XX_RF_BLE_SUPPORT + rest_activate_resource(&res_ble_advd, "dev/ble_advd"); +#endif + + start_board_resources(); + + /* Define application-specific events here. */ + while(1) { + PROCESS_WAIT_EVENT(); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/coap-server.h b/examples/cc26xx/cc26xx-web-demo/coap-server.h new file mode 100644 index 000000000..7399597c8 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/coap-server.h @@ -0,0 +1,52 @@ +/* + * 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-web-demo + * @{ + * + * \file + * Header file for the CC26xx web demo CoAP functionality + */ +/*---------------------------------------------------------------------------*/ +#include "sys/process.h" +/*---------------------------------------------------------------------------*/ +#ifndef COAP_SERVER_H_ +#define COAP_SERVER_H_ +/*---------------------------------------------------------------------------*/ +extern const char *coap_server_not_found_msg; +extern const char *coap_server_supported_msg; +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(coap_server_process); +/*---------------------------------------------------------------------------*/ +#endif /* COAP_SERVER_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c new file mode 100644 index 000000000..281567acf --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c @@ -0,0 +1,1298 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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-web-demo + * @{ + * + * \file + * A simple web server which displays network and sensor information + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "httpd-simple.h" +#include "net/ipv6/uip-ds6-route.h" +#include "batmon-sensor.h" +#include "lib/sensors.h" +#include "lib/list.h" +#include "cc26xx-web-demo.h" +#include "mqtt-client.h" +#include "net-uart.h" + +#include +#include +#include +#include +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, strlen(str)) +/*---------------------------------------------------------------------------*/ +#define CONNS 2 +#define CONTENT_LENGTH_MAX 256 +#define STATE_WAITING 0 +#define STATE_OUTPUT 1 +#define IPADDR_BUF_LEN 64 +/*---------------------------------------------------------------------------*/ +#define RETURN_CODE_OK 0 +#define RETURN_CODE_NF 1 /* Not Found */ +#define RETURN_CODE_SU 2 /* Service Unavailable */ +#define RETURN_CODE_BR 3 /* Bad Request */ +#define RETURN_CODE_LR 4 /* Length Required */ +#define RETURN_CODE_TL 5 /* Content Length too Large */ +/*---------------------------------------------------------------------------*/ +/* POST request machine states */ +#define PARSE_POST_STATE_INIT 0 +#define PARSE_POST_STATE_MORE 1 +#define PARSE_POST_STATE_READING_KEY 2 +#define PARSE_POST_STATE_READING_VAL 3 +#define PARSE_POST_STATE_ERROR 0xFFFFFFFF +/*---------------------------------------------------------------------------*/ +#define PARSE_POST_BUF_SIZES 64 + +/* Last byte always used to null terminate */ +#define PARSE_POST_MAX_POS (PARSE_POST_BUF_SIZES - 2) + +static char key[PARSE_POST_BUF_SIZES]; +static char val_escaped[PARSE_POST_BUF_SIZES]; +static char val[PARSE_POST_BUF_SIZES]; +static int key_len; +static int val_len; +static int state; +/*---------------------------------------------------------------------------*/ +/* Stringified min/max intervals */ +#define STRINGIFY(x) XSTR(x) +#define XSTR(x) #x + +#define RSSI_INT_MAX STRINGIFY(MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MAX) +#define RSSI_INT_MIN STRINGIFY(MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MIN) +#define PUB_INT_MAX STRINGIFY(MQTT_CLIENT_PUBLISH_INTERVAL_MAX) +#define PUB_INT_MIN STRINGIFY(MQTT_CLIENT_PUBLISH_INTERVAL_MIN) +/*---------------------------------------------------------------------------*/ +/* + * We can only handle a single POST request at a time. Since a second POST + * request cannot interrupt us while obtaining a lock, we don't really need + * this lock to be atomic. + * + * An HTTP connection will first request a lock before it starts processing + * a POST request. We maintain a global lock which is either NULL or points + * to the http conn which currently has the lock + */ +static struct httpd_state *lock; +/*---------------------------------------------------------------------------*/ +PROCESS(httpd_simple_process, "CC26XX Web Server"); +/*---------------------------------------------------------------------------*/ +#define ISO_nl 0x0A +#define ISO_space 0x20 +#define ISO_slash 0x2F +#define ISO_amp 0x26 +#define ISO_column 0x3A +#define ISO_equal 0x3D +/*---------------------------------------------------------------------------*/ +#define HTTP_200_OK "HTTP/1.0 200 OK\r\n" +#define HTTP_302_FO "HTTP/1.0 302 Found\r\n" +#define HTTP_400_BR "HTTP/1.0 400 Bad Request\r\n" +#define HTTP_404_NF "HTTP/1.0 404 Not Found\r\n" +#define HTTP_411_LR "HTTP/1.0 411 Length Required\r\n" +#define HTTP_413_TL "HTTP/1.0 413 Request Entity Too Large\r\n" +#define HTTP_503_SU "HTTP/1.0 503 Service Unavailable\r\n" +#define CONN_CLOSE "Connection: close\r\n" +/*---------------------------------------------------------------------------*/ +#define SECTION_TAG "div" +#define SECTION_OPEN "<" SECTION_TAG ">" +#define SECTION_CLOSE "" + +#define CONTENT_OPEN "
"
+#define CONTENT_CLOSE "
" +/*---------------------------------------------------------------------------*/ +#define REQUEST_TYPE_GET 1 +#define REQUEST_TYPE_POST 2 +/*---------------------------------------------------------------------------*/ +static const char *NOT_FOUND = "" + "
" + "

404 - file not found

" + "
" + "" + ""; +/*---------------------------------------------------------------------------*/ +/* Page template */ +static const char http_doctype[] = ""; +static const char http_header_200[] = HTTP_200_OK; +static const char http_header_302[] = HTTP_302_FO; +static const char http_header_400[] = HTTP_400_BR; +static const char http_header_404[] = HTTP_404_NF; +static const char http_header_411[] = HTTP_411_LR; +static const char http_header_413[] = HTTP_413_TL; +static const char http_header_503[] = HTTP_503_SU; +static const char http_get[] = "GET "; +static const char http_post[] = "POST "; +static const char http_index_html[] = "/index.html"; +static const char http_html_start[] = ""; +static const char *http_header_srv_str[] = { + "Server: Contiki, ", + BOARD_STRING "\r\n", + NULL +}; + +static const char *http_header_redir_location[] = { + "Location: /config.html\r\n", + NULL +}; + +static const char *http_header_con_close[] = { + CONN_CLOSE, + NULL +}; + +static const char *http_config_css[] = { + "", + NULL +}; +static const char http_head_charset[] = ""; +static const char http_title_start[] = ""; +static const char http_title_end[] = ""; +static const char http_head_end[] = ""; +static const char http_body_start[] = ""; +static const char http_bottom[] = ""; +/*---------------------------------------------------------------------------*/ +static const char http_content_type_html[] = "text/html"; +static const char http_content_type_plain[] = "text/plain"; +/*---------------------------------------------------------------------------*/ +/* For the config page */ +static const char config_div_left[] = "
"; +static const char config_div_right[] = "
"; +static const char config_div_close[] = "
"; +/*---------------------------------------------------------------------------*/ +typedef struct page { + struct page *next; + char *filename; + char *title; +} page_t; + +static page_t http_index_page = { + NULL, + "index.html", + "Index", +}; + +static page_t http_dev_cfg_page = { + NULL, + "config.html", + "Device Config", +}; + +#if CC26XX_WEB_DEMO_NET_UART +static page_t http_net_cfg_page = { + NULL, + "net.html", + "Net-UART Config", +}; +#endif + +#if CC26XX_WEB_DEMO_MQTT_CLIENT +static page_t http_mqtt_cfg_page = { + NULL, + "mqtt.html", + "MQTT/IBM Cloud Config", +}; +#endif +/*---------------------------------------------------------------------------*/ +#define IBM_QUICKSTART_LINK_LEN 128 +static char http_mqtt_a[IBM_QUICKSTART_LINK_LEN]; +/*---------------------------------------------------------------------------*/ +static uint16_t numtimes; +static const httpd_simple_post_handler_t *handler; +/*---------------------------------------------------------------------------*/ +static uint8_t config_ok; +process_event_t httpd_simple_event_new_config; +/*---------------------------------------------------------------------------*/ +struct httpd_state; +typedef char (*httpd_simple_script_t)(struct httpd_state *s); + +struct httpd_state { + char buf[HTTPD_SIMPLE_MAIN_BUF_SIZE]; + char tmp_buf[TMP_BUF_SIZE]; + struct timer timer; + struct psock sin, sout; + int blen; + const char **ptr; + const cc26xx_web_demo_sensor_reading_t *reading; + const page_t *page; + uip_ds6_route_t *r; + uip_ds6_nbr_t *nbr; + httpd_simple_script_t script; + int content_length; + int tmp_buf_len; + int tmp_buf_copied; + char filename[HTTPD_PATHLEN]; + char inputbuf[HTTPD_INBUF_LEN]; + struct pt outputpt; + struct pt generate_pt; + struct pt top_matter_pt; + char state; + char request_type; + char return_code; +}; +/*---------------------------------------------------------------------------*/ +LIST(post_handlers); +LIST(pages_list); +MEMB(conns, struct httpd_state, CONNS); +/*---------------------------------------------------------------------------*/ +#define HEX_TO_INT(x) (isdigit(x) ? x - '0' : x - 'W') +static size_t +url_unescape(const char *src, size_t srclen, char *dst, size_t dstlen) +{ + size_t i, j; + int a, b; + + for(i = j = 0; i < srclen && j < dstlen - 1; i++, j++) { + if(src[i] == '%' && isxdigit(*(unsigned char *)(src + i + 1)) + && isxdigit(*(unsigned char *)(src + i + 2))) { + a = tolower(*(unsigned char *)(src + i + 1)); + b = tolower(*(unsigned char *)(src + i + 2)); + dst[j] = ((HEX_TO_INT(a) << 4) | HEX_TO_INT(b)) & 0xff; + i += 2; + } else if(src[i] == '+') { + dst[j] = ' '; + } else { + dst[j] = src[i]; + } + } + + dst[j] = '\0'; + + return i == srclen; +} +/*---------------------------------------------------------------------------*/ +void +httpd_simple_register_post_handler(httpd_simple_post_handler_t *h) +{ + list_add(post_handlers, h); +} +/*---------------------------------------------------------------------------*/ +static void +get_neighbour_state_text(char *buf, uint8_t state) +{ + switch(state) { + case NBR_INCOMPLETE: + memcpy(buf, "INCOMPLETE", strlen("INCOMPLETE")); + break; + case NBR_REACHABLE: + memcpy(buf, "REACHABLE", strlen("REACHABLE")); + break; + case NBR_STALE: + memcpy(buf, "STALE", strlen("STALE")); + break; + case NBR_DELAY: + memcpy(buf, "DELAY", strlen("DELAY")); + break; + case NBR_PROBE: + memcpy(buf, "NBR_PROBE", strlen("NBR_PROBE")); + break; + } +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(enqueue_chunk(struct httpd_state *s, uint8_t immediate, + const char *format, ...)) +{ + va_list ap; + + PSOCK_BEGIN(&s->sout); + + va_start(ap, format); + + s->tmp_buf_len = vsnprintf(s->tmp_buf, TMP_BUF_SIZE, format, ap); + + va_end(ap); + + if(s->blen + s->tmp_buf_len < HTTPD_SIMPLE_MAIN_BUF_SIZE) { + /* Enough space for the entire chunk. Copy over */ + memcpy(&s->buf[s->blen], s->tmp_buf, s->tmp_buf_len); + s->blen += s->tmp_buf_len; + } else { + memcpy(&s->buf[s->blen], s->tmp_buf, HTTPD_SIMPLE_MAIN_BUF_SIZE - s->blen); + s->tmp_buf_copied = HTTPD_SIMPLE_MAIN_BUF_SIZE - s->blen; + s->blen = HTTPD_SIMPLE_MAIN_BUF_SIZE; + PSOCK_SEND(&s->sout, (uint8_t *)s->buf, s->blen); + s->blen = 0; + if(s->tmp_buf_copied < s->tmp_buf_len) { + memcpy(s->buf, &s->tmp_buf[s->tmp_buf_copied], + s->tmp_buf_len - s->tmp_buf_copied); + s->blen += s->tmp_buf_len - s->tmp_buf_copied; + } + } + + if(immediate != 0 && s->blen > 0) { + PSOCK_SEND(&s->sout, (uint8_t *)s->buf, s->blen); + s->blen = 0; + } + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(generate_top_matter(struct httpd_state *s, const char *title, + const char **css)) +{ + + PT_BEGIN(&s->top_matter_pt); + + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_doctype)); + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_html_start)); + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_title_start)); + + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, title)); + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_title_end)); + + if(css != NULL) { + for(s->ptr = css; *(s->ptr) != NULL; s->ptr++) { + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, *(s->ptr))); + } + } + + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_head_charset)); + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_head_end)); + PT_WAIT_THREAD(&s->top_matter_pt, enqueue_chunk(s, 0, http_body_start)); + + /* Links */ + PT_WAIT_THREAD(&s->top_matter_pt, + enqueue_chunk(s, 0, SECTION_OPEN "

")); + + s->page = list_head(pages_list); + PT_WAIT_THREAD(&s->top_matter_pt, + enqueue_chunk(s, 0, "[ %s ]", + s->page->filename, s->page->title)); + + for(s->page = s->page->next; s->page != NULL; s->page = s->page->next) { + PT_WAIT_THREAD(&s->top_matter_pt, + enqueue_chunk(s, 0, " | [ %s ]", + s->page->filename, s->page->title)); + } + +#if CC26XX_WEB_DEMO_MQTT_CLIENT + PT_WAIT_THREAD(&s->top_matter_pt, + enqueue_chunk(s, 0, " | %s", http_mqtt_a)); +#endif + PT_WAIT_THREAD(&s->top_matter_pt, + enqueue_chunk(s, 0, "

" SECTION_CLOSE)); + + PT_END(&s->top_matter_pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(generate_index(struct httpd_state *s)) +{ + char ipaddr_buf[IPADDR_BUF_LEN]; /* Intentionally on stack */ + + PT_BEGIN(&s->generate_pt); + + /* Generate top matter (doctype, title, nav links etc) */ + PT_WAIT_THREAD(&s->generate_pt, + generate_top_matter(s, http_index_page.title, NULL)); + + /* ND Cache */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, SECTION_OPEN "Neighbors" CONTENT_OPEN)); + + for(s->nbr = nbr_table_head(ds6_neighbors); s->nbr != NULL; + s->nbr = nbr_table_next(ds6_neighbors, s->nbr)) { + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "\n")); + + memset(ipaddr_buf, 0, IPADDR_BUF_LEN); + cc26xx_web_demo_ipaddr_sprintf(ipaddr_buf, IPADDR_BUF_LEN, &s->nbr->ipaddr); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "%s", ipaddr_buf)); + + memset(ipaddr_buf, 0, IPADDR_BUF_LEN); + get_neighbour_state_text(ipaddr_buf, s->nbr->state); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, " %s", ipaddr_buf)); + } + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, CONTENT_CLOSE SECTION_CLOSE)); + + /* Default Route */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + SECTION_OPEN "Default Route" CONTENT_OPEN)); + + memset(ipaddr_buf, 0, IPADDR_BUF_LEN); + cc26xx_web_demo_ipaddr_sprintf(ipaddr_buf, IPADDR_BUF_LEN, + uip_ds6_defrt_choose()); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "%s", ipaddr_buf)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, CONTENT_CLOSE SECTION_CLOSE)); + + /* Routes */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, SECTION_OPEN "Routes" CONTENT_OPEN)); + + for(s->r = uip_ds6_route_head(); s->r != NULL; + s->r = uip_ds6_route_next(s->r)) { + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "\n")); + + memset(ipaddr_buf, 0, IPADDR_BUF_LEN); + cc26xx_web_demo_ipaddr_sprintf(ipaddr_buf, IPADDR_BUF_LEN, &s->r->ipaddr); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "%s", ipaddr_buf)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, " / %u via ", s->r->length)); + + memset(ipaddr_buf, 0, IPADDR_BUF_LEN); + cc26xx_web_demo_ipaddr_sprintf(ipaddr_buf, IPADDR_BUF_LEN, + uip_ds6_route_nexthop(s->r)); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "%s", ipaddr_buf)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + ", lifetime=%lus", s->r->state.lifetime)); + } + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, + CONTENT_CLOSE SECTION_CLOSE)); + + /* Sensors */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, SECTION_OPEN "Sensors" CONTENT_OPEN)); + + for(s->reading = cc26xx_web_demo_sensor_first(); + s->reading != NULL; s->reading = s->reading->next) { + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "\n%s = %s %s", s->reading->descr, + s->reading->publish ? s->reading->converted : "N/A", + s->reading->units)); + } + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, CONTENT_CLOSE SECTION_CLOSE)); + + /* Footer */ + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, SECTION_OPEN)); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "Page hits: %u
", + ++numtimes)); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "Uptime: %lu secs
", + clock_seconds())); + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, SECTION_CLOSE)); + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 1, http_bottom)); + + PT_END(&s->generate_pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(generate_config(struct httpd_state *s)) +{ + PT_BEGIN(&s->generate_pt); + + /* Generate top matter (doctype, title, nav links etc) */ + PT_WAIT_THREAD(&s->generate_pt, + generate_top_matter(s, http_dev_cfg_page.title, + http_config_css)); + + /* Sensor Settings */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "

Sensors

")); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "
generate_pt, + enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "application/x-www-form-urlencoded\" ")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "accept-charset=\"UTF-8\">")); + + for(s->reading = cc26xx_web_demo_sensor_first(); + s->reading != NULL; s->reading = s->reading->next) { + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%s%s:%s%s", config_div_left, + s->reading->descr, config_div_close, + config_div_right)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "generate_pt, + enqueue_chunk(s, 0, "title=\"On\" name=\"%s\"%s>", + s->reading->form_field, + s->reading->publish ? " Checked" : "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "generate_pt, + enqueue_chunk(s, 0, "title=\"Off\" name=\"%s\"%s>%s", + s->reading->form_field, + s->reading->publish ? "" : " Checked", + config_div_close)); + } + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "
")); + + /* Actions */ + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "

Actions

")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "
generate_pt, + enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "application/x-www-form-urlencoded\" ")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "accept-charset=\"UTF-8\">")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "
")); + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 1, http_bottom)); + + PT_END(&s->generate_pt); +} +/*---------------------------------------------------------------------------*/ +#if CC26XX_WEB_DEMO_MQTT_CLIENT +static +PT_THREAD(generate_mqtt_config(struct httpd_state *s)) +{ + PT_BEGIN(&s->generate_pt); + + /* Generate top matter (doctype, title, nav links etc) */ + PT_WAIT_THREAD(&s->generate_pt, + generate_top_matter(s, http_mqtt_cfg_page.title, + http_config_css)); + + /* MQTT client settings */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "

%s

", http_mqtt_cfg_page.title)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "
generate_pt, + enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "application/x-www-form-urlencoded\" ")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "accept-charset=\"UTF-8\">")); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sType ID:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%s\" ", + cc26xx_web_demo_config.mqtt_config.type_id)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"type_id\">%s", config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sOrg ID:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%s\" ", + cc26xx_web_demo_config.mqtt_config.org_id)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"org_id\">%s", config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sAuth Token:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"\" ")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"auth_token\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sCommand Type:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%s\" ", + cc26xx_web_demo_config.mqtt_config.cmd_type)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"cmd_type\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sEvent Type ID:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%s\" ", + cc26xx_web_demo_config.mqtt_config.event_type_id)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"event_type_id\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sInterval (secs):%s", + config_div_left, config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%lu\" ", + (clock_time_t) + (cc26xx_web_demo_config.mqtt_config.pub_interval + / CLOCK_SECOND))); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "min=\"" PUB_INT_MIN "\" " + "max=\"" PUB_INT_MAX "\" " + "name=\"interval\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sBroker IP:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%s\" ", + cc26xx_web_demo_config.mqtt_config.broker_ip)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"broker_ip\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sBroker Port:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%d\" ", + cc26xx_web_demo_config.mqtt_config.broker_port)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "min=\"1\" max=\"65535\" " + "name=\"broker_port\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sRSSI Interval (secs):%s", + config_div_left, config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%lu\" ", + (clock_time_t) + (cc26xx_web_demo_config.mqtt_config.def_rt_ping_interval + / CLOCK_SECOND))); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "min=\"" RSSI_INT_MIN "\" " + "max=\"" RSSI_INT_MAX "\" " + "name=\"ping_interval\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "
")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "
generate_pt, + enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "application/x-www-form-urlencoded\" ")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "accept-charset=\"UTF-8\">")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "
")); + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 1, http_bottom)); + + PT_END(&s->generate_pt); +} +#endif +/*---------------------------------------------------------------------------*/ +#if CC26XX_WEB_DEMO_NET_UART +static +PT_THREAD(generate_net_uart_config(struct httpd_state *s)) +{ + + PT_BEGIN(&s->generate_pt); + + /* Generate top matter (doctype, title, nav links etc) */ + PT_WAIT_THREAD(&s->generate_pt, + generate_top_matter(s, http_net_cfg_page.title, + http_config_css)); + + /* Net-UART settings */ + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "

%s

", http_net_cfg_page.title)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "
generate_pt, + enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "application/x-www-form-urlencoded\" ")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "accept-charset=\"UTF-8\">")); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sRemote IPv6:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%s\" ", + cc26xx_web_demo_config.net_uart.remote_address)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "name=\"net_uart_ip\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sRemote Port:%s", config_div_left, + config_div_close)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%sgenerate_pt, + enqueue_chunk(s, 0, "value=\"%u\" ", + cc26xx_web_demo_config.net_uart.remote_port)); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "min=\"1\" max=\"65535\" " + "name=\"net_uart_port\">%s", + config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "%s%s:%s%s", config_div_left, + "Enable", config_div_close, + config_div_right)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "generate_pt, + enqueue_chunk(s, 0, "title=\"On\" name=\"net_uart_on\"%s>", + cc26xx_web_demo_config.net_uart.enable ? + " Checked" : "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "generate_pt, + enqueue_chunk(s, 0, "title=\"Off\" name=\"net_uart_on\"" + "%s>%s", + cc26xx_web_demo_config.net_uart.enable ? + "" : " Checked", config_div_close)); + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, + "")); + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "
")); + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 1, http_bottom)); + + PT_END(&s->generate_pt); +} +#endif +/*---------------------------------------------------------------------------*/ +static void +lock_obtain(struct httpd_state *s) +{ + if(lock == NULL) { + lock = s; + } +} +/*---------------------------------------------------------------------------*/ +static void +lock_release(struct httpd_state *s) +{ + if(lock == s) { + lock = NULL; + } +} +/*---------------------------------------------------------------------------*/ +static void +parse_post_request_chunk(char *buf, int buf_len, int last_chunk) +{ + int i; + int finish; + + for(i = 0; i < buf_len; i++) { + switch(state) { + case PARSE_POST_STATE_INIT: + state = PARSE_POST_STATE_MORE; + /* continue */ + case PARSE_POST_STATE_MORE: + memset(key, 0, PARSE_POST_BUF_SIZES); + memset(val, 0, PARSE_POST_BUF_SIZES); + memset(val_escaped, 0, PARSE_POST_BUF_SIZES); + key_len = 0; + val_len = 0; + state = PARSE_POST_STATE_READING_KEY; + /* continue */ + case PARSE_POST_STATE_READING_KEY: + if(buf[i] == ISO_equal) { + state = PARSE_POST_STATE_READING_VAL; + } else if(buf[i] == ISO_amp) { + /* Don't accept an amp while reading a key */ + state = PARSE_POST_STATE_ERROR; + } else { + /* Make sure we don't overshoot key's boundary */ + if(key_len <= PARSE_POST_MAX_POS) { + key[key_len] = buf[i]; + key_len++; + } else { + /* Not enough space for the key. Abort */ + state = PARSE_POST_STATE_ERROR; + } + } + break; + case PARSE_POST_STATE_READING_VAL: + finish = 0; + if(buf[i] == ISO_amp) { + finish = 1; + } else if(buf[i] == ISO_equal) { + /* Don't accept an '=' while reading a val */ + state = PARSE_POST_STATE_ERROR; + } else { + /* Make sure we don't overshoot key's boundary */ + if(val_len <= PARSE_POST_MAX_POS) { + val[val_len] = buf[i]; + val_len++; + /* Last character of the last chunk */ + if((i == buf_len - 1) && (last_chunk == 1)) { + finish = 1; + } + } else { + /* Not enough space for the value. Abort */ + state = PARSE_POST_STATE_ERROR; + } + } + + if(finish == 1) { + /* + * Done reading a key=value pair, either because we encountered an amp + * or because we reached the end of the message body. + * + * First, unescape the value. + * + * Then invoke handlers. We will bail out with PARSE_POST_STATE_ERROR, + * unless the key-val gets correctly processed + */ + url_unescape(val, val_len, val_escaped, PARSE_POST_BUF_SIZES); + val_len = strlen(val_escaped); + + for(handler = list_head(post_handlers); handler != NULL; + handler = list_item_next((void *)handler)) { + if(handler->handler != NULL) { + finish = handler->handler(key, key_len, val_escaped, val_len); + } + if(finish == HTTPD_SIMPLE_POST_HANDLER_ERROR) { + state = PARSE_POST_STATE_ERROR; + break; + } else if(finish == HTTPD_SIMPLE_POST_HANDLER_OK) { + /* Restart the state machine to expect the next pair */ + state = PARSE_POST_STATE_MORE; + + /* + * At least one handler returned OK, therefore we must generate a + * new config event when we're done. + */ + config_ok = 1; + break; + } + /* Else, continue */ + } + } + break; + case PARSE_POST_STATE_ERROR: + /* If we entered the error state earlier, do nothing */ + return; + default: + break; + } + } +} +/*---------------------------------------------------------------------------*/ +static httpd_simple_script_t +get_script(const char *name) +{ + if(strlen(name) == 10 && strncmp(name, "index.html", 10) == 0) { + return generate_index; + } else if(strlen(name) == 11 && strncmp(name, "config.html", 11) == 0) { + return generate_config; +#if CC26XX_WEB_DEMO_MQTT_CLIENT + } else if(strlen(name) == 9 && strncmp(name, "mqtt.html", 9) == 0) { + return generate_mqtt_config; +#endif +#if CC26XX_WEB_DEMO_NET_UART + } else if(strlen(name) == 8 && strncmp(name, "net.html", 8) == 0) { + return generate_net_uart_config; +#endif + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_string(struct httpd_state *s, const char *str)) +{ + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, str); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr, + const char *content_type, const char **additional)) +{ + PT_BEGIN(&s->generate_pt); + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, statushdr)); + + for(s->ptr = http_header_srv_str; *(s->ptr) != NULL; s->ptr++) { + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, *(s->ptr))); + } + + if(additional) { + for(s->ptr = additional; *(s->ptr) != NULL; s->ptr++) { + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, *(s->ptr))); + } + } + + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "Content-type: %s; ", content_type)); + + PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 1, "charset=UTF-8\r\n\r\n")); + + PT_END(&s->generate_pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_output(struct httpd_state *s)) +{ + PT_BEGIN(&s->outputpt); + + s->script = NULL; + + PT_INIT(&s->generate_pt); + PT_INIT(&s->top_matter_pt); + + if(s->request_type == REQUEST_TYPE_POST) { + if(s->return_code == RETURN_CODE_OK) { + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_302, + http_content_type_plain, + http_header_redir_location)); + } else if(s->return_code == RETURN_CODE_LR) { + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_411, + http_content_type_plain, + http_header_con_close)); + PT_WAIT_THREAD(&s->outputpt, send_string(s, "Content-Length Required\n")); + } else if(s->return_code == RETURN_CODE_TL) { + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_413, + http_content_type_plain, + http_header_con_close)); + PT_WAIT_THREAD(&s->outputpt, send_string(s, "Content-Length too Large\n")); + } else if(s->return_code == RETURN_CODE_SU) { + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_503, + http_content_type_plain, + http_header_con_close)); + PT_WAIT_THREAD(&s->outputpt, send_string(s, "Service Unavailable\n")); + } else { + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_400, + http_content_type_plain, + http_header_con_close)); + PT_WAIT_THREAD(&s->outputpt, send_string(s, "Bad Request\n")); + } + } else if(s->request_type == REQUEST_TYPE_GET) { + s->script = get_script(&s->filename[1]); + if(s->script == NULL) { + strncpy(s->filename, "/notfound.html", sizeof(s->filename)); + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_404, + http_content_type_html, + http_header_con_close)); + PT_WAIT_THREAD(&s->outputpt, + send_string(s, NOT_FOUND)); + uip_close(); + PT_EXIT(&s->outputpt); + } else { + PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200, + http_content_type_html, + http_header_con_close)); + PT_WAIT_THREAD(&s->outputpt, s->script(s)); + } + } + s->script = NULL; + PSOCK_CLOSE(&s->sout); + PT_END(&s->outputpt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_input(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sin); + + PSOCK_READTO(&s->sin, ISO_space); + + if(strncasecmp(s->inputbuf, http_get, 4) == 0) { + s->request_type = REQUEST_TYPE_GET; + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + + if(s->inputbuf[1] == ISO_space) { + strncpy(s->filename, http_index_html, sizeof(s->filename)); + } else { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + strncpy(s->filename, s->inputbuf, sizeof(s->filename)); + } + } else if(strncasecmp(s->inputbuf, http_post, 5) == 0) { + s->request_type = REQUEST_TYPE_POST; + /* POST: Read out the rest of the line and ignore it */ + PSOCK_READTO(&s->sin, ISO_nl); + + /* + * Start parsing headers. We look for Content-Length and ignore everything + * else until we hit the start of the message body. + * + * We will return 411 if the client doesn't send Content-Length and 413 + * if Content-Length is too high + */ + s->content_length = 0; + s->return_code = RETURN_CODE_LR; + do { + s->inputbuf[PSOCK_DATALEN(&s->sin)] = 0; + /* We anticipate a content length */ + if((PSOCK_DATALEN(&s->sin) > 14) && + strncasecmp(s->inputbuf, "Content-Length:", 15) == 0) { + char *val_start = &s->inputbuf[15]; + s->content_length = atoi(val_start); + + /* So far so good */ + s->return_code = RETURN_CODE_OK; + } + PSOCK_READTO(&s->sin, ISO_nl); + } while(PSOCK_DATALEN(&s->sin) != 2); + + /* + * Done reading headers. + * Reject content length greater than CONTENT_LENGTH_MAX bytes + */ + if(s->content_length > CONTENT_LENGTH_MAX) { + s->content_length = 0; + s->return_code = RETURN_CODE_TL; + } + + if(s->return_code == RETURN_CODE_OK) { + /* Acceptable Content Length. Try to obtain a lock */ + lock_obtain(s); + + if(lock == s) { + state = PARSE_POST_STATE_INIT; + } else { + s->return_code = RETURN_CODE_SU; + } + } + + /* Parse the message body, unless we have detected an error. */ + while(s->content_length > 0 && lock == s && + s->return_code == RETURN_CODE_OK) { + PSOCK_READBUF_LEN(&s->sin, s->content_length); + s->content_length -= PSOCK_DATALEN(&s->sin); + + /* Parse the message body */ + parse_post_request_chunk(s->inputbuf, PSOCK_DATALEN(&s->sin), + (s->content_length == 0)); + if(state == PARSE_POST_STATE_ERROR) { + /* Could not parse: Bad Request and stop parsing */ + s->return_code = RETURN_CODE_BR; + } + } + + /* + * Done. If our return code is OK but the state machine is not in + * STATE_MORE, it means that the message body ended half-way reading a key + * or value. Set 'Bad Request' + */ + if(s->return_code == RETURN_CODE_OK && state != PARSE_POST_STATE_MORE) { + s->return_code = RETURN_CODE_BR; + } + + /* If the flag is set, we had at least 1 configuration value accepted */ + if(config_ok) { + process_post(PROCESS_BROADCAST, httpd_simple_event_new_config, NULL); + } + config_ok = 0; + + lock_release(s); + } else { + PSOCK_CLOSE_EXIT(&s->sin); + } + + s->state = STATE_OUTPUT; + + while(1) { + PSOCK_READTO(&s->sin, ISO_nl); + } + + PSOCK_END(&s->sin); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connection(struct httpd_state *s) +{ + handle_input(s); + if(s->state == STATE_OUTPUT) { + handle_output(s); + } +} +/*---------------------------------------------------------------------------*/ +static void +appcall(void *state) +{ + struct httpd_state *s = (struct httpd_state *)state; + + if(uip_closed() || uip_aborted() || uip_timedout()) { + if(s != NULL) { + s->script = NULL; + s->blen = 0; + s->tmp_buf_len = 0; + memb_free(&conns, s); + } + } else if(uip_connected()) { + s = (struct httpd_state *)memb_alloc(&conns); + if(s == NULL) { + uip_abort(); + return; + } + tcp_markconn(uip_conn, s); + PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); + PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); + PT_INIT(&s->outputpt); + s->script = NULL; + s->state = STATE_WAITING; + timer_set(&s->timer, CLOCK_SECOND * 10); + handle_connection(s); + } else if(s != NULL) { + if(uip_poll()) { + if(timer_expired(&s->timer)) { + uip_abort(); + s->script = NULL; + memb_free(&conns, s); + } + } else { + timer_restart(&s->timer); + } + handle_connection(s); + } else { + uip_abort(); + } +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + tcp_listen(UIP_HTONS(80)); + memb_init(&conns); + + list_add(pages_list, &http_index_page); + list_add(pages_list, &http_dev_cfg_page); + +#if CC26XX_WEB_DEMO_NET_UART + list_add(pages_list, &http_net_cfg_page); +#endif + +#if CC26XX_WEB_DEMO_MQTT_CLIENT + list_add(pages_list, &http_mqtt_cfg_page); +#endif +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(httpd_simple_process, ev, data) +{ + PROCESS_BEGIN(); + + printf("CC26XX Web Server\n"); + + httpd_simple_event_new_config = process_alloc_event(); + + init(); + + snprintf(http_mqtt_a, IBM_QUICKSTART_LINK_LEN, + "[ IBM Quickstart ]", + linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], + linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5], + linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + appcall(data); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/httpd-simple.h b/examples/cc26xx/cc26xx-web-demo/httpd-simple.h new file mode 100644 index 000000000..c7631adb1 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/httpd-simple.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \file + * Header file for the HTTPD of the cc26xx web demo example. + * \author + * Adam Dunkels + * Niclas Finne + * Joakim Eriksson + * Texas Instruments Incorporated - http://www.ti.com/ + */ +/*---------------------------------------------------------------------------*/ +#ifndef HTTPD_SIMPLE_H_ +#define HTTPD_SIMPLE_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-net.h" +#include "sys/process.h" +#include "cc26xx-web-demo.h" +/*---------------------------------------------------------------------------*/ +/* Ideally a multiple of TCP_MSS */ +#ifdef HTTPD_SIMPLE_CONF_MAIN_BUF_SIZE +#define HTTPD_SIMPLE_MAIN_BUF_SIZE HTTPD_SIMPLE_CONF_BUF_SIZE +#else +#define HTTPD_SIMPLE_MAIN_BUF_SIZE UIP_TCP_MSS +#endif +/*---------------------------------------------------------------------------*/ +#define HTTPD_PATHLEN 16 +#define HTTPD_INBUF_LEN (HTTPD_PATHLEN + 10) + +#define TMP_BUF_SIZE (UIP_TCP_MSS + 1) +/*---------------------------------------------------------------------------*/ +/* POST request handlers */ +#define HTTPD_SIMPLE_POST_HANDLER_OK 1 +#define HTTPD_SIMPLE_POST_HANDLER_UNKNOWN 0 +#define HTTPD_SIMPLE_POST_HANDLER_ERROR 0xFFFFFFFF + +/** + * \brief Datatype for a handler which can process incoming POST requests + * \param key The configuration key to be updated + * \param key_len The length of the key argument + * \param val The new configuration value for key + * \param val_len The length of the value argument + * + * \return 1: HTTPD_SIMPLE_POST_HANDLER_OK if the function can handle the + * request, HTTPD_SIMPLE_POST_HANDLER_UNKNOWN if it does not know how to handle + * it. HTTPD_SIMPLE_POST_HANDLER_ERROR if it does know how to handle it but + * the request was malformed. + */ +typedef struct httpd_simple_post_handler { + struct httpd_simple_post_handler *next; + int (*handler)(char *key, int key_len, char *val, int val_len); +} httpd_simple_post_handler_t; + +/* Declare a handler */ +#define HTTPD_SIMPLE_POST_HANDLER(name, fp) \ + httpd_simple_post_handler_t name##_handler = { NULL, fp } + +/** + * \brief Register a handler for POST requests + * \param h A pointer to the handler structure + */ +void httpd_simple_register_post_handler(httpd_simple_post_handler_t *h); +/*---------------------------------------------------------------------------*/ +/* + * An event generated by the HTTPD when a new configuration request has been + * received + */ +extern process_event_t httpd_simple_event_new_config; +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(httpd_simple_process); +/*---------------------------------------------------------------------------*/ +#endif /* HTTPD_SIMPLE_H_ */ diff --git a/examples/cc26xx/cc26xx-web-demo/img/6lbr-web.png b/examples/cc26xx/cc26xx-web-demo/img/6lbr-web.png new file mode 100644 index 000000000..5308c412b Binary files /dev/null and b/examples/cc26xx/cc26xx-web-demo/img/6lbr-web.png differ diff --git a/examples/cc26xx/cc26xx-web-demo/img/coap-resources.png b/examples/cc26xx/cc26xx-web-demo/img/coap-resources.png new file mode 100644 index 000000000..c71c934fe Binary files /dev/null and b/examples/cc26xx/cc26xx-web-demo/img/coap-resources.png differ diff --git a/examples/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png b/examples/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png new file mode 100644 index 000000000..a7ce7dabe Binary files /dev/null and b/examples/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png differ diff --git a/examples/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png b/examples/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png new file mode 100644 index 000000000..79c8e61e3 Binary files /dev/null and b/examples/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png differ diff --git a/examples/cc26xx/cc26xx-web-demo/img/well-known-core.png b/examples/cc26xx/cc26xx-web-demo/img/well-known-core.png new file mode 100644 index 000000000..93552e502 Binary files /dev/null and b/examples/cc26xx/cc26xx-web-demo/img/well-known-core.png differ diff --git a/examples/cc26xx/cc26xx-web-demo/mqtt-client.c b/examples/cc26xx/cc26xx-web-demo/mqtt-client.c new file mode 100644 index 000000000..4fa0736ef --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/mqtt-client.c @@ -0,0 +1,975 @@ +/* + * 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-web-demo + * @{ + * + * \file + * MQTT/IBM cloud service client for the CC26XX web demo. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "rpl/rpl-private.h" +#include "mqtt.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-icmp6.h" +#include "net/ipv6/sicslowpan.h" +#include "sys/etimer.h" +#include "sys/ctimer.h" +#include "lib/sensors.h" +#include "button-sensor.h" +#include "board-peripherals.h" +#include "cc26xx-web-demo.h" +#include "dev/leds.h" +#include "mqtt-client.h" +#include "httpd-simple.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +/* + * IBM server: messaging.quickstart.internetofthings.ibmcloud.com + * (184.172.124.189) mapped in an NAT64 (prefix 64:ff9b::/96) IPv6 address + * Note: If not able to connect; lookup the IP address again as it may change. + * + * If the node has a broker IP setting saved on flash, this value here will + * get ignored + */ +static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd"; +/*---------------------------------------------------------------------------*/ +/* + * A timeout used when waiting for something to happen (e.g. to connect or to + * disconnect) + */ +#define STATE_MACHINE_PERIODIC (CLOCK_SECOND >> 1) +/*---------------------------------------------------------------------------*/ +/* Provide visible feedback via LEDS during various states */ +/* When connecting to broker */ +#define CONNECTING_LED_DURATION (CLOCK_SECOND >> 3) + +/* Each time we try to publish */ +#define PUBLISH_LED_ON_DURATION (CLOCK_SECOND) +/*---------------------------------------------------------------------------*/ +/* Connections and reconnections */ +#define RETRY_FOREVER 0xFF +#define RECONNECT_INTERVAL (CLOCK_SECOND * 2) + +/* + * Number of times to try reconnecting to the broker. + * Can be a limited number (e.g. 3, 10 etc) or can be set to RETRY_FOREVER + */ +#define RECONNECT_ATTEMPTS RETRY_FOREVER +#define CONNECTION_STABLE_TIME (CLOCK_SECOND * 5) +#define NEW_CONFIG_WAIT_INTERVAL (CLOCK_SECOND * 20) +static struct timer connection_life; +static uint8_t connect_attempt; +/*---------------------------------------------------------------------------*/ +/* Various states */ +static uint8_t state; +#define MQTT_CLIENT_STATE_INIT 0 +#define MQTT_CLIENT_STATE_REGISTERED 1 +#define MQTT_CLIENT_STATE_CONNECTING 2 +#define MQTT_CLIENT_STATE_CONNECTED 3 +#define MQTT_CLIENT_STATE_PUBLISHING 4 +#define MQTT_CLIENT_STATE_DISCONNECTED 5 +#define MQTT_CLIENT_STATE_NEWCONFIG 6 +#define MQTT_CLIENT_STATE_CONFIG_ERROR 0xFE +#define MQTT_CLIENT_STATE_ERROR 0xFF +/*---------------------------------------------------------------------------*/ +/* Maximum TCP segment size for outgoing segments of our socket */ +#define MQTT_CLIENT_MAX_SEGMENT_SIZE 32 +/*---------------------------------------------------------------------------*/ +/* + * Buffers for Client ID and Topic. + * Make sure they are large enough to hold the entire respective string + * + * d:quickstart:status:EUI64 is 32 bytes long + * iot-2/evt/status/fmt/json is 25 bytes + * We also need space for the null termination + */ +#define BUFFER_SIZE 64 +static char client_id[BUFFER_SIZE]; +static char pub_topic[BUFFER_SIZE]; +static char sub_topic[BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ +/* + * The main MQTT buffers. + * We will need to increase if we start publishing more data. + */ +#define APP_BUFFER_SIZE 512 +static struct mqtt_connection conn; +static char app_buffer[APP_BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ +#define QUICKSTART "quickstart" +/*---------------------------------------------------------------------------*/ +static struct mqtt_message *msg_ptr = 0; +static struct etimer publish_periodic_timer; +static struct ctimer ct; +static char *buf_ptr; +static uint16_t seq_nr_value = 0; +/*---------------------------------------------------------------------------*/ +static uip_ip6addr_t def_route; +/*---------------------------------------------------------------------------*/ +/* Parent RSSI functionality */ +static struct uip_icmp6_echo_reply_notification echo_reply_notification; +static struct etimer echo_request_timer; +int def_rt_rssi = 0; +/*---------------------------------------------------------------------------*/ +const static cc26xx_web_demo_sensor_reading_t *reading; +/*---------------------------------------------------------------------------*/ +mqtt_client_config_t *conf; +/*---------------------------------------------------------------------------*/ +PROCESS(mqtt_client_process, "CC26XX MQTT Client"); +/*---------------------------------------------------------------------------*/ +static void +publish_led_off(void *d) +{ + leds_off(CC26XX_WEB_DEMO_STATUS_LED); +} +/*---------------------------------------------------------------------------*/ +static void +new_net_config(void) +{ + /* + * We got a new configuration over the net. + * + * Disconnect from the current broker and stop the periodic timer. + * + * When the source of the new configuration is done, we will get notified + * via an event. + */ + if(state == MQTT_CLIENT_STATE_NEWCONFIG) { + return; + } + + state = MQTT_CLIENT_STATE_NEWCONFIG; + + etimer_stop(&publish_periodic_timer); + mqtt_disconnect(&conn); +} +/*---------------------------------------------------------------------------*/ +static int +org_id_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + if(key_len != strlen("org_id") || + strncasecmp(key, "org_id", strlen("org_id")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > MQTT_CLIENT_CONFIG_ORG_ID_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + memset(conf->org_id, 0, MQTT_CLIENT_CONFIG_ORG_ID_LEN); + memcpy(conf->org_id, val, val_len); + + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + + new_net_config(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +type_id_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + if(key_len != strlen("type_id") || + strncasecmp(key, "type_id", strlen("type_id")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > MQTT_CLIENT_CONFIG_TYPE_ID_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + memset(conf->type_id, 0, MQTT_CLIENT_CONFIG_TYPE_ID_LEN); + memcpy(conf->type_id, val, val_len); + + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + + new_net_config(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +event_type_id_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + if(key_len != strlen("event_type_id") || + strncasecmp(key, "event_type_id", strlen("event_type_id")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + memset(conf->event_type_id, 0, MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN); + memcpy(conf->event_type_id, val, val_len); + + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + + new_net_config(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +cmd_type_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + if(key_len != strlen("cmd_type") || + strncasecmp(key, "cmd_type", strlen("cmd_type")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > MQTT_CLIENT_CONFIG_CMD_TYPE_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + memset(conf->cmd_type, 0, MQTT_CLIENT_CONFIG_CMD_TYPE_LEN); + memcpy(conf->cmd_type, val, val_len); + + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + + new_net_config(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +auth_token_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + if(key_len != strlen("auth_token") || + strncasecmp(key, "auth_token", strlen("auth_token")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + memset(conf->auth_token, 0, MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN); + memcpy(conf->auth_token, val, val_len); + + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + + new_net_config(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +interval_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = 0; + + if(key_len != strlen("interval") || + strncasecmp(key, "interval", strlen("interval")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + rv = atoi(val); + + if(rv < MQTT_CLIENT_PUBLISH_INTERVAL_MIN || + rv > MQTT_CLIENT_PUBLISH_INTERVAL_MAX) { + return HTTPD_SIMPLE_POST_HANDLER_ERROR; + } + + conf->pub_interval = rv * CLOCK_SECOND; + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +static int +port_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = 0; + + if(key_len != strlen("broker_port") || + strncasecmp(key, "broker_port", strlen("broker_port")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + rv = atoi(val); + + if(rv <= 65535 && rv > 0) { + conf->broker_port = rv; + } else { + return HTTPD_SIMPLE_POST_HANDLER_ERROR; + } + + new_net_config(); + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +static int +ip_addr_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + + if(key_len != strlen("broker_ip") || + strncasecmp(key, "broker_ip", strlen("broker_ip")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + memset(conf->broker_ip, 0, MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN); + memcpy(conf->broker_ip, val, val_len); + + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + + new_net_config(); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +reconnect_post_handler(char *key, int key_len, char *val, int val_len) +{ + if(key_len != strlen("reconnect") || + strncasecmp(key, "reconnect", strlen("reconnect")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + new_net_config(); + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +static int +ping_interval_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = 0; + + if(key_len != strlen("ping_interval") || + strncasecmp(key, "ping_interval", strlen("ping_interval")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + rv = atoi(val); + + if(rv < MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MIN || + rv > MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MAX) { + return HTTPD_SIMPLE_POST_HANDLER_ERROR; + } + + conf->def_rt_ping_interval = rv * CLOCK_SECOND; + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +HTTPD_SIMPLE_POST_HANDLER(org_id, org_id_post_handler); +HTTPD_SIMPLE_POST_HANDLER(type_id, type_id_post_handler); +HTTPD_SIMPLE_POST_HANDLER(event_type_id, event_type_id_post_handler); +HTTPD_SIMPLE_POST_HANDLER(cmd_type, cmd_type_post_handler); +HTTPD_SIMPLE_POST_HANDLER(auth_token, auth_token_post_handler); +HTTPD_SIMPLE_POST_HANDLER(ip_addr, ip_addr_post_handler); +HTTPD_SIMPLE_POST_HANDLER(port, port_post_handler); +HTTPD_SIMPLE_POST_HANDLER(interval, interval_post_handler); +HTTPD_SIMPLE_POST_HANDLER(reconnect, reconnect_post_handler); +HTTPD_SIMPLE_POST_HANDLER(ping_interval, ping_interval_post_handler); +/*---------------------------------------------------------------------------*/ +static void +echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, + uint16_t datalen) +{ + if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) { + def_rt_rssi = sicslowpan_get_last_rssi(); + } +} +/*---------------------------------------------------------------------------*/ +static void +pub_handler(const char *topic, uint16_t topic_len, const uint8_t *chunk, + uint16_t chunk_len) +{ + DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, topic_len, + chunk_len); + + /* If we don't like the length, ignore */ + if(topic_len != 23 || chunk_len != 1) { + printf("Incorrect topic or chunk len. Ignored\n"); + return; + } + + /* If the format != json, ignore */ + if(strncmp(&topic[topic_len - 4], "json", 4) != 0) { + printf("Incorrect format\n"); + } + + if(strncmp(&topic[10], "leds", 4) == 0) { + if(chunk[0] == '1') { + leds_on(LEDS_RED); + } else if(chunk[0] == '0') { + leds_off(LEDS_RED); + } + return; + } + +#if BOARD_SENSORTAG + if(strncmp(&topic[10], "buzz", 4) == 0) { + if(chunk[0] == '1') { + buzzer_start(1000); + } else if(chunk[0] == '0') { + buzzer_stop(); + } + return; + } +#endif +} +/*---------------------------------------------------------------------------*/ +static void +mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data) +{ + switch(event) { + case MQTT_EVENT_CONNECTED: { + DBG("APP - Application has a MQTT connection\n"); + timer_set(&connection_life, CONNECTION_STABLE_TIME); + state = MQTT_CLIENT_STATE_CONNECTED; + break; + } + case MQTT_EVENT_DISCONNECTED: { + DBG("APP - MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data)); + + /* Do nothing if the disconnect was the result of an incoming config */ + if(state != MQTT_CLIENT_STATE_NEWCONFIG) { + state = MQTT_CLIENT_STATE_DISCONNECTED; + process_poll(&mqtt_client_process); + } + break; + } + case MQTT_EVENT_PUBLISH: { + msg_ptr = data; + + /* Implement first_flag in publish message? */ + if(msg_ptr->first_chunk) { + msg_ptr->first_chunk = 0; + DBG("APP - Application received a publish on topic '%s'. Payload " + "size is %i bytes. Content:\n\n", + msg_ptr->topic, msg_ptr->payload_length); + } + + pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), msg_ptr->payload_chunk, + msg_ptr->payload_length); + break; + } + case MQTT_EVENT_SUBACK: { + DBG("APP - Application is subscribed to topic successfully\n"); + break; + } + case MQTT_EVENT_UNSUBACK: { + DBG("APP - Application is unsubscribed to topic successfully\n"); + break; + } + case MQTT_EVENT_PUBACK: { + DBG("APP - Publishing complete.\n"); + break; + } + default: + DBG("APP - Application got a unhandled MQTT event: %i\n", event); + break; + } +} +/*---------------------------------------------------------------------------*/ +static int +construct_pub_topic(void) +{ + int len = snprintf(pub_topic, BUFFER_SIZE, "iot-2/evt/%s/fmt/json", + conf->event_type_id); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +construct_sub_topic(void) +{ + int len = snprintf(sub_topic, BUFFER_SIZE, "iot-2/cmd/%s/fmt/json", + conf->cmd_type); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +construct_client_id(void) +{ + int len = snprintf(client_id, BUFFER_SIZE, "d:%s:%s:%02x%02x%02x%02x%02x%02x", + conf->org_id, conf->type_id, + linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], + linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5], + linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +update_config(void) +{ + if(construct_client_id() == 0) { + /* Fatal error. Client ID larger than the buffer */ + state = MQTT_CLIENT_STATE_CONFIG_ERROR; + return; + } + + if(construct_sub_topic() == 0) { + /* Fatal error. Topic larger than the buffer */ + state = MQTT_CLIENT_STATE_CONFIG_ERROR; + return; + } + + if(construct_pub_topic() == 0) { + /* Fatal error. Topic larger than the buffer */ + state = MQTT_CLIENT_STATE_CONFIG_ERROR; + return; + } + + /* Reset the counter */ + seq_nr_value = 0; + + state = MQTT_CLIENT_STATE_INIT; + + /* + * Schedule next timer event ASAP + * + * If we entered an error state then we won't do anything when it fires. + * + * Since the error at this stage is a config error, we will only exit this + * error state if we get a new config. + */ + etimer_set(&publish_periodic_timer, 0); + + return; +} +/*---------------------------------------------------------------------------*/ +static int +init_config() +{ + /* Populate configuration with default values */ + memset(conf, 0, sizeof(mqtt_client_config_t)); + + memcpy(conf->org_id, CC26XX_WEB_DEMO_DEFAULT_ORG_ID, 11); + memcpy(conf->type_id, CC26XX_WEB_DEMO_DEFAULT_TYPE_ID, 7); + memcpy(conf->event_type_id, CC26XX_WEB_DEMO_DEFAULT_EVENT_TYPE_ID, 7); + memcpy(conf->broker_ip, broker_ip, strlen(broker_ip)); + memcpy(conf->cmd_type, CC26XX_WEB_DEMO_DEFAULT_SUBSCRIBE_CMD_TYPE, 1); + + conf->broker_port = CC26XX_WEB_DEMO_DEFAULT_BROKER_PORT; + conf->pub_interval = CC26XX_WEB_DEMO_DEFAULT_PUBLISH_INTERVAL; + conf->def_rt_ping_interval = CC26XX_WEB_DEMO_DEFAULT_RSSI_MEAS_INTERVAL; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +register_http_post_handlers(void) +{ + httpd_simple_register_post_handler(&org_id_handler); + httpd_simple_register_post_handler(&type_id_handler); + httpd_simple_register_post_handler(&event_type_id_handler); + httpd_simple_register_post_handler(&cmd_type_handler); + httpd_simple_register_post_handler(&auth_token_handler); + httpd_simple_register_post_handler(&interval_handler); + httpd_simple_register_post_handler(&port_handler); + httpd_simple_register_post_handler(&ip_addr_handler); + httpd_simple_register_post_handler(&reconnect_handler); + httpd_simple_register_post_handler(&ping_interval_handler); +} +/*---------------------------------------------------------------------------*/ +static void +subscribe(void) +{ + /* Publish MQTT topic in IBM quickstart format */ + mqtt_status_t status; + + status = mqtt_subscribe(&conn, NULL, sub_topic, MQTT_QOS_LEVEL_0); + + DBG("APP - Subscribing!\n"); + if(status == MQTT_STATUS_OUT_QUEUE_FULL) { + DBG("APP - Tried to subscribe but command queue was full!\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +publish(void) +{ + /* Publish MQTT topic in IBM quickstart format */ + int len; + int remaining = APP_BUFFER_SIZE; + + seq_nr_value++; + + buf_ptr = app_buffer; + + len = snprintf(buf_ptr, remaining, + "{" + "\"d\":{" + "\"myName\":\"%s\"," + "\"Seq #\":%d," + "\"Uptime (sec)\":%lu", + BOARD_STRING, seq_nr_value, clock_seconds()); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + + remaining -= len; + buf_ptr += len; + + /* Put our Default route's string representation in a buffer */ + char def_rt_str[64]; + memset(def_rt_str, 0, sizeof(def_rt_str)); + cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), + uip_ds6_defrt_choose()); + + len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d", + def_rt_str, def_rt_rssi); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + remaining -= len; + buf_ptr += len; + + memcpy(&def_route, uip_ds6_defrt_choose(), sizeof(uip_ip6addr_t)); + + for(reading = cc26xx_web_demo_sensor_first(); + reading != NULL; reading = reading->next) { + if(reading->publish && reading->raw != CC26XX_SENSOR_READING_ERROR) { + len = snprintf(buf_ptr, remaining, + ",\"%s (%s)\":%s", reading->descr, reading->units, + reading->converted); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + remaining -= len; + buf_ptr += len; + } + } + + len = snprintf(buf_ptr, remaining, "}}"); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + + mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer, + strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF); + + DBG("APP - Publish!\n"); +} +/*---------------------------------------------------------------------------*/ +static void +connect_to_broker(void) +{ + /* Connect to MQTT server */ + mqtt_connect(&conn, conf->broker_ip, conf->broker_port, + conf->pub_interval * 3); + + state = MQTT_CLIENT_STATE_CONNECTING; +} +/*---------------------------------------------------------------------------*/ +static void +ping_parent(void) +{ + if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) { + return; + } + + uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0, + CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN); +} +/*---------------------------------------------------------------------------*/ +static void +state_machine(void) +{ + switch(state) { + case MQTT_CLIENT_STATE_INIT: + /* If we have just been configured register MQTT connection */ + mqtt_register(&conn, &mqtt_client_process, client_id, mqtt_event, + MQTT_CLIENT_MAX_SEGMENT_SIZE); + + /* + * If we are not using the quickstart service (thus we are an IBM + * registered device), we need to provide user name and password + */ + if(strncasecmp(conf->org_id, QUICKSTART, strlen(conf->org_id)) != 0) { + if(strlen(conf->auth_token) == 0) { + printf("User name set, but empty auth token\n"); + state = MQTT_CLIENT_STATE_ERROR; + break; + } else { + mqtt_set_username_password(&conn, "use-token-auth", + conf->auth_token); + } + } + + /* _register() will set auto_reconnect. We don't want that. */ + conn.auto_reconnect = 0; + connect_attempt = 1; + + /* + * Wipe out the default route so we'll republish it every time we switch to + * a new broker + */ + memset(&def_route, 0, sizeof(def_route)); + + state = MQTT_CLIENT_STATE_REGISTERED; + DBG("Init\n"); + /* Continue */ + case MQTT_CLIENT_STATE_REGISTERED: + if(uip_ds6_get_global(ADDR_PREFERRED) != NULL) { + /* Registered and with a public IP. Connect */ + DBG("Registered. Connect attempt %u\n", connect_attempt); + ping_parent(); + connect_to_broker(); + } + etimer_set(&publish_periodic_timer, CC26XX_WEB_DEMO_NET_CONNECT_PERIODIC); + return; + break; + case MQTT_CLIENT_STATE_CONNECTING: + leds_on(CC26XX_WEB_DEMO_STATUS_LED); + ctimer_set(&ct, CONNECTING_LED_DURATION, publish_led_off, NULL); + /* Not connected yet. Wait */ + DBG("Connecting (%u)\n", connect_attempt); + break; + case MQTT_CLIENT_STATE_CONNECTED: + /* Don't subscribe unless we are a registered device */ + if(strncasecmp(conf->org_id, QUICKSTART, strlen(conf->org_id)) == 0) { + DBG("Using 'quickstart': Skipping subscribe\n"); + state = MQTT_CLIENT_STATE_PUBLISHING; + } + /* Continue */ + case MQTT_CLIENT_STATE_PUBLISHING: + /* If the timer expired, the connection is stable. */ + if(timer_expired(&connection_life)) { + /* + * Intentionally using 0 here instead of 1: We want RECONNECT_ATTEMPTS + * attempts if we disconnect after a successful connect + */ + connect_attempt = 0; + } + + if(mqtt_ready(&conn) && conn.out_buffer_sent) { + /* Connected. Publish */ + if(state == MQTT_CLIENT_STATE_CONNECTED) { + subscribe(); + state = MQTT_CLIENT_STATE_PUBLISHING; + } else { + leds_on(CC26XX_WEB_DEMO_STATUS_LED); + ctimer_set(&ct, PUBLISH_LED_ON_DURATION, publish_led_off, NULL); + publish(); + } + etimer_set(&publish_periodic_timer, conf->pub_interval); + + DBG("Publishing\n"); + /* Return here so we don't end up rescheduling the timer */ + return; + } else { + /* + * Our publish timer fired, but some MQTT packet is already in flight + * (either not sent at all, or sent but not fully ACKd). + * + * This can mean that we have lost connectivity to our broker or that + * simply there is some network delay. In both cases, we refuse to + * trigger a new message and we wait for TCP to either ACK the entire + * packet after retries, or to timeout and notify us. + */ + DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state, + conn.out_queue_full); + } + break; + case MQTT_CLIENT_STATE_DISCONNECTED: + DBG("Disconnected\n"); + if(connect_attempt < RECONNECT_ATTEMPTS || + RECONNECT_ATTEMPTS == RETRY_FOREVER) { + /* Disconnect and backoff */ + clock_time_t interval; + mqtt_disconnect(&conn); + connect_attempt++; + + interval = connect_attempt < 3 ? RECONNECT_INTERVAL << connect_attempt : + RECONNECT_INTERVAL << 3; + + DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval); + + etimer_set(&publish_periodic_timer, interval); + + state = MQTT_CLIENT_STATE_REGISTERED; + return; + } else { + /* Max reconnect attempts reached. Enter error state */ + state = MQTT_CLIENT_STATE_ERROR; + DBG("Aborting connection after %u attempts\n", connect_attempt - 1); + } + break; + case MQTT_CLIENT_STATE_NEWCONFIG: + /* Only update config after we have disconnected */ + if(conn.state == MQTT_CONN_STATE_NOT_CONNECTED) { + update_config(); + DBG("New config\n"); + + /* update_config() scheduled next pass. Return */ + return; + } + break; + case MQTT_CLIENT_STATE_CONFIG_ERROR: + /* Idle away. The only way out is a new config */ + printf("Bad configuration.\n"); + return; + case MQTT_CLIENT_STATE_ERROR: + default: + leds_on(CC26XX_WEB_DEMO_STATUS_LED); + /* + * 'default' should never happen. + * + * If we enter here it's because of some error. Stop timers. The only thing + * that can bring us out is a new config event + */ + printf("Default case: State=0x%02x\n", state); + return; + } + + /* If we didn't return so far, reschedule ourselves */ + etimer_set(&publish_periodic_timer, STATE_MACHINE_PERIODIC); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mqtt_client_process, ev, data) +{ + + PROCESS_BEGIN(); + + printf("CC26XX MQTT Client Process\n"); + + conf = &cc26xx_web_demo_config.mqtt_config; + if(init_config() != 1) { + PROCESS_EXIT(); + } + + register_http_post_handlers(); + + update_config(); + + def_rt_rssi = 0x8000000; + uip_icmp6_echo_reply_callback_add(&echo_reply_notification, + echo_reply_handler); + etimer_set(&echo_request_timer, conf->def_rt_ping_interval); + + /* Main loop */ + while(1) { + + PROCESS_YIELD(); + + if(ev == sensors_event && data == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER) { + if(state == MQTT_CLIENT_STATE_ERROR) { + connect_attempt = 1; + state = MQTT_CLIENT_STATE_REGISTERED; + } + } + + if(ev == httpd_simple_event_new_config) { + /* + * Schedule next pass in a while. When HTTPD sends us this event, it is + * also in the process of sending the config page. Wait a little before + * reconnecting, so as to not cause congestion. + */ + etimer_set(&publish_periodic_timer, NEW_CONFIG_WAIT_INTERVAL); + } + + if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) || + ev == PROCESS_EVENT_POLL || + ev == cc26xx_web_demo_publish_event || + (ev == sensors_event && data == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER)) { + state_machine(); + } + + if(ev == PROCESS_EVENT_TIMER && data == &echo_request_timer) { + ping_parent(); + etimer_set(&echo_request_timer, conf->def_rt_ping_interval); + } + + if(ev == cc26xx_web_demo_load_config_defaults) { + init_config(); + etimer_set(&publish_periodic_timer, NEW_CONFIG_WAIT_INTERVAL); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/mqtt-client.h b/examples/cc26xx/cc26xx-web-demo/mqtt-client.h new file mode 100644 index 000000000..b4b50085f --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/mqtt-client.h @@ -0,0 +1,74 @@ +/* + * 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-web-demo + * @{ + * + * \file + * Header file for the CC26xx web demo MQTT client functionality + */ +/*---------------------------------------------------------------------------*/ +#ifndef MQTT_CLIENT_H_ +#define MQTT_CLIENT_H_ +/*---------------------------------------------------------------------------*/ +#define MQTT_CLIENT_CONFIG_ORG_ID_LEN 32 +#define MQTT_CLIENT_CONFIG_TYPE_ID_LEN 32 +#define MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN 32 +#define MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN 32 +#define MQTT_CLIENT_CONFIG_CMD_TYPE_LEN 8 +#define MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN 64 +/*---------------------------------------------------------------------------*/ +#define MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */ +#define MQTT_CLIENT_RSSI_MEASURE_INTERVAL_MIN 5 /* secs */ +#define MQTT_CLIENT_PUBLISH_INTERVAL_MAX 86400 /* secs: 1 day */ +#define MQTT_CLIENT_PUBLISH_INTERVAL_MIN 5 /* secs */ +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(mqtt_client_process); +/*---------------------------------------------------------------------------*/ +/** + * \brief Data structure declaration for the MQTT client configuration + */ +typedef struct mqtt_client_config { + char org_id[MQTT_CLIENT_CONFIG_ORG_ID_LEN]; + char type_id[MQTT_CLIENT_CONFIG_TYPE_ID_LEN]; + char auth_token[MQTT_CLIENT_CONFIG_AUTH_TOKEN_LEN]; + char event_type_id[MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN]; + char broker_ip[MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN]; + char cmd_type[MQTT_CLIENT_CONFIG_CMD_TYPE_LEN]; + clock_time_t pub_interval; + int def_rt_ping_interval; + uint16_t broker_port; +} mqtt_client_config_t; +/*---------------------------------------------------------------------------*/ +#endif /* MQTT_CLIENT_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/net-uart.c b/examples/cc26xx/cc26xx-web-demo/net-uart.c new file mode 100644 index 000000000..96463aee0 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/net-uart.c @@ -0,0 +1,344 @@ +/* + * 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-web-demo + * @{ + * + * \file + * A process which receives data over UART and transmits them over UDP + * to a pre-defined IPv6 address and port. It also listens on the same UDP + * port for messages, which it prints out over UART. + * + * For this example to work, you will have to modify the destination IPv6 + * address by adjusting the set_dest_addr() macro below. + * + * To listen on your linux or OS X box: + * nc -6ulkw 1 REMOTE_PORT + * + * (REMOTE_PORT should be the actual value of the define below, e.g. 7777) + * + * Once netcat is up and listening, type something to the CC26xx's terminal + * Bear in mind that the datagram will only be sent after a 0x0a (LF) char + * has been received. Therefore, if you are on Win, do NOT use PuTTY for + * this purpose, since it does not send 0x0a as part of the line end. On + * Win XP use hyperterm. On Win 7 use some other software (e.g. Tera Term, + * which can be configured to send CRLF on enter keystrokes). + * + * To send data in the other direction from your linux or OS X box: + * + * nc -6u \ REMOTE_PORT + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "sys/process.h" +#include "dev/serial-line.h" +#include "net/ip/uip.h" +#include "net/ip/uip-udp-packet.h" +#include "net/ip/uiplib.h" +#include "lpm.h" +#include "net-uart.h" +#include "httpd-simple.h" + +#include "ti-lib.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" +/*---------------------------------------------------------------------------*/ +#define REMOTE_PORT 7777 +#define MAX_MSG_SIZE 100 + +#define set_dest_addr() uip_ip6addr(&remote_addr, \ + 0xBBBB, 0x0000, 0x0000, 0x0000, \ + 0x3E07, 0x54FF, 0xFE74, 0x4885); +/*---------------------------------------------------------------------------*/ +#define ADDRESS_CONVERSION_OK 1 +#define ADDRESS_CONVERSION_ERROR 0 +/*---------------------------------------------------------------------------*/ +#ifndef MIN +#define MIN(n, m) (((n) < (m)) ? (n) : (m)) +#endif +/*---------------------------------------------------------------------------*/ +static struct uip_udp_conn *udp_conn = NULL; + +static uint8_t buffer[MAX_MSG_SIZE]; +static uint8_t msg_len; +static uip_ip6addr_t remote_addr; +/*---------------------------------------------------------------------------*/ +#define IPV6_ADDR_STR_LEN 64 +/*---------------------------------------------------------------------------*/ +PROCESS(net_uart_process, "Net UART Process"); +/*---------------------------------------------------------------------------*/ +/* + * \brief Attempts to convert a string representation of an IPv6 address to a + * numeric one. + * \param buf The buffer with the string to be converted. + * \return ADDRESS_CONVERSION_OK or ADDRESS_CONVERSION_ERROR + * + * ToDo: Add support for NAT64 conversion in case the incoming address is a v4 + * This is now supported in the current master, so when we pull it in this will + * be very straightforward. + */ +static int +set_new_ip_address(char *buf) +{ + /* + * uiplib_ip6addrconv will immediately start writing into the supplied buffer + * even if it subsequently fails. Thus, pass an intermediate buffer + */ + uip_ip6addr_t tmp_addr; + + int rv = uiplib_ip6addrconv(buf, &tmp_addr); + + if(rv == ADDRESS_CONVERSION_OK) { + /* Conversion OK, copy to our main buffer */ + memcpy(&remote_addr, &tmp_addr, sizeof(remote_addr)); + + PRINTF("Updated remote address "); + PRINT6ADDR(&remote_addr); + PRINTF("\n"); + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static void +net_input(void) +{ + if(uip_newdata()) { + memset(buffer, 0, MAX_MSG_SIZE); + msg_len = MIN(uip_datalen(), MAX_MSG_SIZE - 1); + + /* Copy data */ + memcpy(buffer, uip_appdata, msg_len); + printf("%s", (char *)buffer); + } + + return; +} +/*---------------------------------------------------------------------------*/ +/* + * In order to maintain UART input operation: + * - Keep the uart clocked in sleep and deep sleep + * - Keep the serial PD on in deep sleep + */ +static lpm_power_domain_lock_t lock; +/*---------------------------------------------------------------------------*/ +static void +release_uart(void) +{ + /* Release serial PD lock */ + lpm_pd_lock_release(&lock); + + /* Let the UART turn off during Sleep and Deep Sleep */ + ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0); + ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +static void +keep_uart_on(void) +{ + /* Keep the serial PD on */ + lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL); + + /* Keep the UART clock on during Sleep and Deep Sleep */ + ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0); + ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +static int +remote_port_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv; + + if(key_len != strlen("net_uart_port") || + strncasecmp(key, "net_uart_port", strlen("net_uart_port")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + rv = atoi(val); + + if(rv <= 65535 && rv > 0) { + cc26xx_web_demo_config.net_uart.remote_port = (uint16_t)rv; + } else { + return HTTPD_SIMPLE_POST_HANDLER_ERROR; + } + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +static int +remote_ipv6_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + + if(key_len != strlen("net_uart_ip") || + strncasecmp(key, "net_uart_ip", strlen("net_uart_ip")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + if(val_len > IPV6_ADDR_STR_LEN) { + /* Ours but bad value */ + rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; + } else { + if(set_new_ip_address(val)) { + memset(cc26xx_web_demo_config.net_uart.remote_address, 0, + NET_UART_IP_ADDR_STRLEN); + memcpy(cc26xx_web_demo_config.net_uart.remote_address, val, val_len); + rv = HTTPD_SIMPLE_POST_HANDLER_OK; + } + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +on_off_post_handler(char *key, int key_len, char *val, int val_len) +{ + int rv; + + if(key_len != strlen("net_uart_on") || + strncasecmp(key, "net_uart_on", strlen("net_uart_on")) != 0) { + /* Not ours */ + return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + } + + rv = atoi(val); + + /* Be pedantic: only accept 0 and 1, not just any non-zero value */ + if(rv == 0) { + cc26xx_web_demo_config.net_uart.enable = 0; + release_uart(); + } else if(rv == 1) { + cc26xx_web_demo_config.net_uart.enable = 1; + keep_uart_on(); + } else { + return HTTPD_SIMPLE_POST_HANDLER_ERROR; + } + + return HTTPD_SIMPLE_POST_HANDLER_OK; +} +/*---------------------------------------------------------------------------*/ +HTTPD_SIMPLE_POST_HANDLER(remote_port, remote_port_post_handler); +HTTPD_SIMPLE_POST_HANDLER(remote_ipv6, remote_ipv6_post_handler); +HTTPD_SIMPLE_POST_HANDLER(on_off, on_off_post_handler); +/*---------------------------------------------------------------------------*/ +static void +set_config_defaults(void) +{ + /* Set a hard-coded destination address to start with */ + set_dest_addr(); + + /* Set config defaults */ + cc26xx_web_demo_ipaddr_sprintf(cc26xx_web_demo_config.net_uart.remote_address, + NET_UART_IP_ADDR_STRLEN, &remote_addr); + cc26xx_web_demo_config.net_uart.remote_port = REMOTE_PORT; + cc26xx_web_demo_config.net_uart.enable = 1; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(net_uart_process, ev, data) +{ + PROCESS_BEGIN(); + + printf("CC26XX Net UART Process\n"); + + set_config_defaults(); + + udp_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(udp_conn, UIP_HTONS(REMOTE_PORT)); + + if(udp_conn == NULL) { + printf("No UDP connection available, exiting the process!\n"); + PROCESS_EXIT(); + } + + httpd_simple_register_post_handler(&remote_port_handler); + httpd_simple_register_post_handler(&remote_ipv6_handler); + httpd_simple_register_post_handler(&on_off_handler); + + while(1) { + + PROCESS_YIELD(); + + if(ev == serial_line_event_message) { + /* + * If the message contains a new IP address, save it and go back to + * waiting. + */ + if(set_new_ip_address((char *)data) == ADDRESS_CONVERSION_ERROR) { + /* Not an IP address in the message. Send to current destination */ + memset(buffer, 0, MAX_MSG_SIZE); + + /* We need to add a line feed, thus never fill the entire buffer */ + msg_len = MIN(strlen(data), MAX_MSG_SIZE - 1); + memcpy(buffer, data, msg_len); + + /* Add a line feed */ + buffer[msg_len] = 0x0A; + msg_len++; + + uip_udp_packet_sendto( + udp_conn, buffer, msg_len, &remote_addr, + UIP_HTONS(cc26xx_web_demo_config.net_uart.remote_port)); + } + } else if(ev == tcpip_event) { + net_input(); + } else if(ev == cc26xx_web_demo_config_loaded_event) { + /* + * New config. Check if it's possible to update the remote address. + * The port will have been updated already + */ + set_new_ip_address(cc26xx_web_demo_config.net_uart.remote_address); + + if(cc26xx_web_demo_config.net_uart.enable == 1) { + keep_uart_on(); + } + } else if(ev == cc26xx_web_demo_load_config_defaults) { + set_config_defaults(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/cc26xx/cc26xx-web-demo/net-uart.h b/examples/cc26xx/cc26xx-web-demo/net-uart.h new file mode 100644 index 000000000..5c4201672 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/net-uart.h @@ -0,0 +1,48 @@ +/* + * 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. + */ +#ifndef NET_UART_H_ +#define NET_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "net/ip/uip.h" + +#include +/*---------------------------------------------------------------------------*/ +#define NET_UART_IP_ADDR_STRLEN 64 +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(net_uart_process); +/*---------------------------------------------------------------------------*/ +typedef struct net_uart_config_s { + char remote_address[NET_UART_IP_ADDR_STRLEN]; + uint16_t remote_port; + uint8_t enable; +} net_uart_config_t; +/*---------------------------------------------------------------------------*/ +#endif /* NET_UART_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/cc26xx-web-demo/project-conf.h b/examples/cc26xx/cc26xx-web-demo/project-conf.h new file mode 100644 index 000000000..d49a7b3e9 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/project-conf.h @@ -0,0 +1,53 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +/* Change to match your configuration */ +#define NETSTACK_CONF_RDC contikimac_driver +#define IEEE802154_CONF_PANID 0xABCD +#define CC26XX_RF_CONF_CHANNEL 25 +#define CC26XX_MODEL_CONF_CPU_VARIANT 2650 /* CC2650 */ +#define CC26XX_RF_CONF_BLE_SUPPORT 1 /* Only available with CC2650 */ +/*---------------------------------------------------------------------------*/ +/* Enable/Disable Components of this Demo */ +#define CC26XX_WEB_DEMO_CONF_MQTT_CLIENT 1 +#define CC26XX_WEB_DEMO_CONF_6LBR_CLIENT 1 +#define CC26XX_WEB_DEMO_CONF_COAP_SERVER 1 +#define CC26XX_WEB_DEMO_CONF_NET_UART 1 +/*---------------------------------------------------------------------------*/ +/* Shrink the size of the uIP buffer, routing table and ND cache */ +#define UIP_CONF_BUFFER_SIZE 900 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 8 +#define UIP_CONF_MAX_ROUTES 8 +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c b/examples/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c new file mode 100644 index 000000000..0604c7ac9 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015, 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 Institute 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 INSTITUTE 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 INSTITUTE 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-web-demo + * @{ + * + * \file + * CoAP resource to start/stop/configure BLE advertisements + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "rest-engine.h" +#include "er-coap.h" +#include "dev/cc26xx-rf.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define BLE_NAME_BUF_LEN 32 +/*---------------------------------------------------------------------------*/ +const char *forbidden_payload = "Name to advertise unspecified.\n" + "Use name= in the request"; +/*---------------------------------------------------------------------------*/ +static void +res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + size_t len = 0; + const char *text = NULL; + char name[BLE_NAME_BUF_LEN]; + int success = 0; + int rv; + + memset(name, 0, BLE_NAME_BUF_LEN); + + len = REST.get_post_variable(request, "name", &text); + + if(len > 0 && len < BLE_NAME_BUF_LEN) { + memcpy(name, text, len); + cc26xx_rf_ble_beacond_config(0, name); + success = 1; + } + + len = REST.get_post_variable(request, "interval", &text); + + rv = atoi(text); + + if(rv > 0) { + cc26xx_rf_ble_beacond_config((clock_time_t)(rv * CLOCK_SECOND), NULL); + success = 1; + } + + len = REST.get_post_variable(request, "mode", &text); + + if(len) { + if(strncmp(text, "on", len) == 0) { + if(cc26xx_rf_ble_beacond_start()) { + success = 1; + } else { + REST.set_response_status(response, REST.status.FORBIDDEN); + REST.set_response_payload(response, forbidden_payload, + strlen(forbidden_payload)); + return; + } + } else if(strncmp(text, "off", len) == 0) { + cc26xx_rf_ble_beacond_stop(); + success = 1; + } else { + success = 0; + } + } + + if(!success) { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_ble_advd, + "title=\"BLE advd config: POST/PUT name=&mode=on|off" + "&interval=\";rt=\"Control\"", + NULL, + res_ble_post_put_handler, + res_ble_post_put_handler, + NULL); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-device.c b/examples/cc26xx/cc26xx-web-demo/resources/res-device.c new file mode 100644 index 000000000..84cef8e24 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-device.c @@ -0,0 +1,179 @@ +/* + * 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-web-demo + * @{ + * + * \file + * CoAP resource handler for CC26XX software and hardware version + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "rest-engine.h" +#include "er-coap.h" +#include "sys/clock.h" +#include "cc26xx-model.h" +#include "coap-server.h" +#include "cc26xx-web-demo.h" + +#include +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_hw(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + unsigned int accept = -1; + + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING, + CC26XX_MODEL_CPU_VARIANT); + + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}", + BOARD_STRING, CC26XX_MODEL_CPU_VARIANT); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_XML) { + REST.set_header_content_type(response, REST.type.APPLICATION_XML); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + "", BOARD_STRING, + CC26XX_MODEL_CPU_VARIANT); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + REST.set_response_payload(response, coap_server_supported_msg, + strlen(coap_server_supported_msg)); + } +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_sw(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + unsigned int accept = -1; + + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", CONTIKI_VERSION_STRING); + + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"SW Ver\":\"%s\"}", + CONTIKI_VERSION_STRING); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_XML) { + REST.set_header_content_type(response, REST.type.APPLICATION_XML); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + "", CONTIKI_VERSION_STRING); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + REST.set_response_payload(response, coap_server_supported_msg, + strlen(coap_server_supported_msg)); + } +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_uptime(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + unsigned int accept = -1; + + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%lu", clock_seconds()); + + REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"uptime\":%lu}", + clock_seconds()); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_XML) { + REST.set_header_content_type(response, REST.type.APPLICATION_XML); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + "", clock_seconds()); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + REST.set_response_payload(response, coap_server_supported_msg, + strlen(coap_server_supported_msg)); + } +} +/*---------------------------------------------------------------------------*/ +static void +res_post_handler_cfg_reset(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + cc26xx_web_demo_restore_defaults(); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_device_sw, + "title=\"Software version\";rt=\"text\"", + res_get_handler_sw, + NULL, + NULL, + NULL); +/*---------------------------------------------------------------------------*/ +RESOURCE(res_device_uptime, + "title=\"Uptime\";rt=\"seconds\"", + res_get_handler_uptime, + NULL, + NULL, + NULL); +/*---------------------------------------------------------------------------*/ +RESOURCE(res_device_hw, + "title=\"Hardware version\";rt=\"text\"", + res_get_handler_hw, + NULL, + NULL, + NULL); +/*---------------------------------------------------------------------------*/ +RESOURCE(res_device_cfg_reset, + "title=\"Reset Device Config: POST\";rt=\"Control\"", + NULL, res_post_handler_cfg_reset, NULL, NULL); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c new file mode 100644 index 000000000..2a86ad25b --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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-web-demo + * @{ + * + * \file + * CoAP resource handler for the CC26xx LEDs. Slightly modified copy of + * the one found in Contiki's original CoAP example. + * \author + * Matthias Kovatsch (original) + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "rest-engine.h" +#include "dev/leds.h" + +#include +/*---------------------------------------------------------------------------*/ +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + size_t len = 0; + const char *color = NULL; + const char *mode = NULL; + uint8_t led = 0; + int success = 1; + + if((len = REST.get_query_variable(request, "color", &color))) { + if(strncmp(color, "r", len) == 0) { + led = LEDS_RED; + } else if(strncmp(color, "g", len) == 0) { + led = LEDS_GREEN; +#if BOARD_SMARTRF06EB + } else if(strncmp(color, "y", len) == 0) { + led = LEDS_YELLOW; + } else if(strncmp(color, "o", len) == 0) { + led = LEDS_ORANGE; +#endif + } else { + success = 0; + } + } else { + success = 0; + } + + if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + if(strncmp(mode, "on", len) == 0) { + leds_on(led); + } else if(strncmp(mode, "off", len) == 0) { + leds_off(led); + } else { + success = 0; + } + } else { + success = 0; + } + + if(!success) { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} +/*---------------------------------------------------------------------------*/ +/* + * A simple actuator example, depending on the color query parameter and post + * variable mode, corresponding led is activated or deactivated + */ +#if BOARD_SENSORTAG +#define RESOURCE_PARAMS "r|g" +#elif BOARD_SMARTRF06EB +#define RESOURCE_PARAMS "r|g|y|o" +#endif + +RESOURCE(res_leds, + "title=\"LEDs: ?color=" RESOURCE_PARAMS ", POST/PUT mode=on|off\";rt=\"Control\"", + NULL, + res_post_put_handler, + res_post_put_handler, + NULL); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c new file mode 100644 index 000000000..fecfca994 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -0,0 +1,269 @@ +/* + * 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-web-demo + * @{ + * + * \file + * CoAP resource handler for the Sensortag-CC26xx sensors + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "rest-engine.h" +#include "er-coap.h" +#include "cc26xx-web-demo.h" +#include "coap-server.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/* + * Generic resource handler for any sensor in this example. Ultimately gets + * called by all handlers and populates the CoAP response + */ +static void +res_get_handler_all(int sens_type, void *request, void *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + unsigned int accept = -1; + const cc26xx_web_demo_sensor_reading_t *reading; + + reading = cc26xx_web_demo_sensor_lookup(sens_type); + + if(reading == NULL) { + REST.set_response_status(response, REST.status.NOT_FOUND); + REST.set_response_payload(response, coap_server_not_found_msg, + strlen(coap_server_not_found_msg)); + return; + } + + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", reading->converted); + + REST.set_response_payload(response, (uint8_t *)buffer, + strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"%s\":%s}", + reading->descr, reading->converted); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_XML) { + REST.set_header_content_type(response, REST.type.APPLICATION_XML); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + "<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element, + reading->converted, reading->units); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + REST.set_response_payload(response, coap_server_supported_msg, + strlen(coap_server_supported_msg)); + } +} +/*---------------------------------------------------------------------------*/ +/* BatMon resources and handler: Temperature, Voltage */ +static void +res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_batmon_volt(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_batmon_temp, "title=\"Battery Temp\";rt=\"C\"", + res_get_handler_batmon_temp, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"", + res_get_handler_batmon_volt, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +#if BOARD_SENSORTAG +/*---------------------------------------------------------------------------*/ +/* MPU resources and handler: Accelerometer and Gyro */ +static void +res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_mpu_gyro_z(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_mpu_acc_x, "title=\"Acc X\";rt=\"G\"", res_get_handler_mpu_acc_x, + NULL, NULL, NULL); +RESOURCE(res_mpu_acc_y, "title=\"Acc Y\";rt=\"G\"", res_get_handler_mpu_acc_y, + NULL, NULL, NULL); +RESOURCE(res_mpu_acc_z, "title=\"Acc Z\";rt=\"G\"", res_get_handler_mpu_acc_z, + NULL, NULL, NULL); + +RESOURCE(res_mpu_gyro_x, "title=\"Gyro X\";rt=\"deg/sec\"", + res_get_handler_mpu_gyro_x, NULL, NULL, NULL); +RESOURCE(res_mpu_gyro_y, "title=\"Gyro Y\";rt=\"deg/sec\"", + res_get_handler_mpu_gyro_y, NULL, NULL, NULL); +RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"", + res_get_handler_mpu_gyro_z, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +/* TMP sensor resources and handlers: Object, Ambient */ +static void +res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_amb_temp(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_tmp007_obj, "title=\"Temperature (Object)\";rt=\"C\"", + res_get_handler_obj_temp, NULL, NULL, NULL); + +RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"", + res_get_handler_amb_temp, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +/* BMP sensor resources: Temperature, Pressure */ +static void +res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_bmp_press(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_PRES, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_bmp280_temp, "title=\"Barometer (Temperature)\";rt=\"C\"", + res_get_handler_bmp_temp, NULL, NULL, NULL); + +RESOURCE(res_bmp280_press, + "title=\"Barometer (Pressure)\";rt=\"hPa (hectopascal / millibar)\"", + res_get_handler_bmp_press, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +/* SHT21 sensor resources and handler: Temperature, Pressure */ +static void +res_get_handler_sht_temp(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +static void +res_get_handler_sht_humidity(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_sht21_temp, "title=\"Temperature\";rt=\"C\"", + res_get_handler_sht_temp, NULL, NULL, NULL); + +RESOURCE(res_sht21_hum, "title=\"Humidity\";rt=\"%RH\"", + res_get_handler_sht_humidity, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +/* Illuminance resources and handler */ +static void +res_get_handler_opt(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, request, response, + buffer, preferred_size, offset); +} +/*---------------------------------------------------------------------------*/ +RESOURCE(res_opt3001_light, "title=\"Illuminance\";rt=\"Lux\"", + res_get_handler_opt, NULL, NULL, NULL); +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_SENSORTAG */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c b/examples/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c new file mode 100644 index 000000000..2fb424a03 --- /dev/null +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the Contiki operating system. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx-web-demo + * @{ + * + * \file + * CoAP resource to toggle LEDs. Slightly modified copy of the one found + * in Contiki's original CoAP example. + * \author + * Matthias Kovatsch (original) + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "rest-engine.h" +#include "dev/leds.h" + +#include +/*---------------------------------------------------------------------------*/ +static void +res_post_handler_red(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + leds_toggle(LEDS_RED); +} +/*---------------------------------------------------------------------------*/ +static void +res_post_handler_green(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + leds_toggle(LEDS_GREEN); +} +/*---------------------------------------------------------------------------*/ +/* Toggles the red led */ +RESOURCE(res_toggle_red, + "title=\"Red LED\";rt=\"Control\"", + NULL, + res_post_handler_red, + NULL, + NULL); + +/* Toggles the green led */ +RESOURCE(res_toggle_green, + "title=\"Green LED\";rt=\"Control\"", + NULL, + res_post_handler_green, + NULL, + NULL); +/*---------------------------------------------------------------------------*/ +/* An additional 2 LEDs on the Srf */ +#if BOARD_SMARTRF06EB +/*---------------------------------------------------------------------------*/ +static void +res_post_handler_yellow(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + leds_toggle(LEDS_YELLOW); +} +/*---------------------------------------------------------------------------*/ +static void +res_post_handler_orange(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + leds_toggle(LEDS_ORANGE); +} +/*---------------------------------------------------------------------------*/ +/* Toggles the yellow led */ +RESOURCE(res_toggle_yellow, + "title=\"Yellow LED\";rt=\"Control\"", + NULL, + res_post_handler_yellow, + NULL, + NULL); + +/* Toggles the orange led */ +RESOURCE(res_toggle_orange, + "title=\"Orange LED\";rt=\"Control\"", + NULL, + res_post_handler_orange, + NULL, + NULL); +#endif +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/cc26xx/project-conf.h b/examples/cc26xx/project-conf.h new file mode 100644 index 000000000..97bb52591 --- /dev/null +++ b/examples/cc26xx/project-conf.h @@ -0,0 +1,45 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +/* Disable button shutdown functionality */ +#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 0 +/*---------------------------------------------------------------------------*/ +/* Change to match your configuration */ +#define NETSTACK_CONF_RDC contikimac_driver +#define IEEE802154_CONF_PANID 0xABCD +#define CC26XX_RF_CONF_CHANNEL 25 +#define CC26XX_MODEL_CONF_CPU_VARIANT 2650 /* CC2650 */ +#define CC26XX_RF_CONF_BLE_SUPPORT 1 /* Only available with CC2650 */ +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/platform/srf06-cc26xx/Makefile.srf06-cc26xx new file mode 100644 index 000000000..7feefa126 --- /dev/null +++ b/platform/srf06-cc26xx/Makefile.srf06-cc26xx @@ -0,0 +1,36 @@ +# srf06-cc26xx platform makefile + +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +### Board and BSP selection +ifeq ($(BOARD),) + BOARD=srf06 +endif + +### Configure the build for the board and pull in board-specific sources +CONTIKI_TARGET_DIRS += . $(BOARD) +PLATFORM_ROOT_DIR = $(CONTIKI)/platform/$(TARGET) + +### Include the board dir if one exists +-include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(BOARD) + +CONTIKI_TARGET_SOURCEFILES += contiki-main.c +CONTIKI_TARGET_SOURCEFILES += sensors.c leds.c +CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES) + +CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) + +CLEAN += *.srf06-cc26xx + +### Unless the example dictates otherwise, build with code size optimisations +ifndef SMALL + SMALL = 0 +endif + +### Define the CPU directory +CONTIKI_CPU=$(CONTIKI)/cpu/cc26xx +include $(CONTIKI_CPU)/Makefile.cc26xx + +MODULES += core/net core/net/mac core/net/mac/contikimac core/net/llsec diff --git a/platform/srf06-cc26xx/README.md b/platform/srf06-cc26xx/README.md new file mode 100644 index 000000000..4cfb9945d --- /dev/null +++ b/platform/srf06-cc26xx/README.md @@ -0,0 +1,180 @@ +Getting Started with Contiki for TI CC26xx +========================================== + +This guide's aim is to help you start using Contiki for TI's CC26xx. The +platform supports two different boards: + +* SmartRF 06 Evaluation Board with a CC26xx Evaluation Module (relevant files + and drivers are under `srf06/`) +* CC26xx SensorTag 2.0 (relevant drivers under `sensortag/`) + +The CPU code, common for both platforms, can be found under `$(CONTIKI)/cpu/cc26xx`. +The port was developed and tested with CC2650s, but the intention is for it to +work with the CC2630 as well. Thus, bug reports are welcome for both chips. +Bear in mind that the CC2630 does not have BLE capability. + +This port is only meant to work with 7x7mm chips + +This guide assumes that you have basic understanding of how to use the command +line and perform basic admin tasks on UNIX family OSs. + +Port Features +============= +The platform has the following key features: + +* Deep Sleep support with RAM retention for ultra-low energy consumption. +* Support for CC26xx RF in IEEE as well as BLE mode (BLE support is very basic + since Contiki does not provide a BLE stack). + +In terms of hardware support, the following drivers have been implemented: + +* SmartRF06 EB peripherals + * LEDs + * Buttons + * UART connectivity over the XDS100v3 backchannel +* SensorTag 2.0 + * LEDs + * Buttons (One of the buttons can be used as a shutdown button) + * Reed relay + * Motion Processing Unit (MPU9250 - Accelerometer, Gyro) + * BMP280 sensor + * TMP007 sensor + * SHT21 sensor + * OPT3001 sensor + * Buzzer + * External SPI flash + +Examples +======== +The port comes with two examples: A very basic example and a mode advanced one +(web demo). The former demonstrates how to read sensors and how to use board +peripherals. It also demonstrates how to send out BLE advertisements. +The latter includes a CoAP server, an MQTT client which connects and publishes +to the IBM quickstart service, a net-based UART and lastly a web server that +can be used to configure the rest of the example. + +More details about those two examples can be found in their respective READMEs. + +Requirements +============ +To use the port you need: + +* TI's CC26xxware sources (more below) +* Software to program the nodes. Use TI's SmartRF Flash Programmer +* A toolchain to build firmware: The port has been developed and tested with + GNU Tools for ARM Embedded Processors . + The port was developed and tested using this version: + + $ arm-none-eabi-gcc -v + [...] + gcc version 4.9.3 20141119 (release) [ARM/embedded-4_9-branch revision 218278] (GNU Tools for ARM Embedded Processors) + +* You may also need other drivers so that the SmartRF can communicate with your +operating system and so that you can use the chip's UART for I/O. Please read +the section ["Drivers" in the CC2538DK readme](https://github.com/contiki-os/contiki/tree/master/platform/cc2538dk#drivers). + +Environment +=========== +To use this port, you will need to download and extract CC26xxware sources, +provided by TI here http://www.ti.com/tool/cc26xxware. Once you have done this, you will need to configure the Contiki +build system so that it can locate and compile them as part of the build process. + +To do this, you will need to set the following environment variable: + +* `TI_CC26XXWARE` + + Stores the path to a directory containing the following: + + * cc26xxware sources under `$(TI_CC26XXWARE)/driverlib` + * cc26xxware includes under `$(TI_CC26XXWARE)/inc` + * Startup files under `$(TI_CC26XXWARE)/startup_files` + +This _must_ be a path relative to the Contiki source directory. For +example, if Contiki is in `/home/user/contiki-2.x` and the CC26xxware is in +`/home/user/cc26xxware`, then `TI_CC26XXWARE` must be set to `../cc26xxware` + +The variable can be set within the example's Makefile, by adding this: + + TI_CC26XXWARE=../cc26xxware + +or you can use an environment variable, like so: + + export TI_CC26XXWARE=../cc26xxware + +Filename conflicts between Contiki and CC26xxware +================================================= +There is a file called `timer.c` both in Contiki as well as in CC26xxware. The +way things are configured now, we don't use the latter. However, if you need to +start using it at some point, you will need to rename it: + +From `$(TI_CC26XXWARE)/driverlib/cc26xx/source/timer.c` to `driverlib-timer.c` + +Sensortag vs Srf06 +================== +To build for the sensortag, set `BOARD=sensortag`. You can do that by exporting +it as an environment variable, by adding it to your Makefile or by adding it to +your make command as an argument + +If the `BOARD` variable is not equal to `sensortag`, an image for the Srf06 +CC26XXEM will be built instead. + +If you want to switch between building for one platform to the other, make +certain to `make clean` before building for the new one, or you will get linker +errors. + +Low Power Operation +=================== +The platform takes advantage of the CC26xx's power saving features. In a +nutshell, here is how things work: + +* When the RF is TXing, the CPU will enter sleep mode and will resume after TX + has completed. +* When there are no events in the Contiki event queue, the chip will enter + 'some' low power mode (more below). + +We do not use pre-defined power profiles (e.g. as mentioned in the TRM or as +we do for the CC2538 with LPM1, LPM2 etc). Each time we enter low power +operation, we either put the CM3 to sleep or to deep sleep. The latter case is +highly configurable: the LPM engine allows other code modules to register +themselves for notifications and to configure low power operation. With these +facilities, a module can e.g. prohibit deep sleep altogether, or it can request +that a power domain be kept powered. The LPM engine will turn off as many +CC26xx components as it can while satisfying all restrictions set by registered +modules. + +To determine which power mode to use, the following logic is followed: + +* The deepest available low power mode can be hard-coded by using + the `LPM_MODE_MAX_SUPPORTED` macro in the LPM driver (`lpm.[ch]`). Thus, it + is possible to prohibit deep sleep altogether. +* Code modules which are affected by low power operation can 'register' + themselves with the LPM driver. +* If the projected low-power duration is lower than `STANDBY_MIN_DURATION`, + the chip will simply sleep. +* If the projected low power duration is sufficiently long, the LPM will visit + all registered modules to query the maximum allowed power mode (maximum means + sleep vs deep sleep in this context). It will then drop to this power mode. + This is where a code module can forbid deep sleep if required. +* All registered modules will be notified when the chip is about to enter + deep sleep, as well as after wake-up. + +When the chip does enter deep sleep: + +* The RF Core, VIMS, SYSBUS and CPU power domains are always turned off. Due to + the way the RF driver works, the RFCORE PD should be off already. +* Peripheral clocks stop +* The Serial and Peripheral power domains are turned off, unless an LPM module + requests them to stay operational. For example, the net-uart demo keeps the + serial power domain powered on and the UART clocked under sleep and deep + sleep in order to retain UART RX functionality. +* If both SERIAL and PERIPH PDs are turned off, we also switch power source to + the uLDO for ultra low leakage under deep sleep. + +The chip will come out of low power mode by one of the following events: + +* Button press or, in the case of the SensorTag, a reed relay trigger +* Software clock tick (timer). The clock ticks at 128Hz, therefore the maximum + time we will ever spend in a sleep mode is 7.8125ms. In hardware terms, this + is an AON RTC Channel 2 compare interrupt. +* Rtimer triggers, as part of ContikiMAC's sleep/wake-up cycles. The rtimer + sits on the AON RTC channel 0. diff --git a/platform/srf06-cc26xx/contiki-conf.h b/platform/srf06-cc26xx/contiki-conf.h new file mode 100644 index 000000000..6a99c29b3 --- /dev/null +++ b/platform/srf06-cc26xx/contiki-conf.h @@ -0,0 +1,350 @@ +/* + * 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-srf-tag + * @{ + * + * \file + * Configuration for the srf06-cc26xx platform + */ +#ifndef CONTIKI_CONF_H +#define CONTIKI_CONF_H + +#include +/*---------------------------------------------------------------------------*/ +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif /* PROJECT_CONF_H */ +/*---------------------------------------------------------------------------*/ +/** + * \name CC26xx flavour selection + * @{ + */ +#ifndef CC26XX_MODEL_CONF_CPU_VARIANT +#define CC26XX_MODEL_CONF_CPU_VARIANT 2650 /**< 2650 => CC2650, 2630 => CC2630 */ + +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Network Stack Configuration + * + * @{ + */ +#ifndef NETSTACK_CONF_NETWORK +#if NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#else +#define NETSTACK_CONF_NETWORK rime_driver +#endif /* NETSTACK_CONF_WITH_IPV6 */ +#endif /* NETSTACK_CONF_NETWORK */ + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC csma_driver +#endif + +#ifndef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC contikimac_driver +#endif + +/* Configure NullRDC for when it's selected */ +#define NULLRDC_802154_AUTOACK 1 +#define NULLRDC_802154_AUTOACK_HW 1 + +/* Configure ContikiMAC for when it's selected */ +#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 +#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 +#define WITH_FAST_SLEEP 1 + +#ifndef NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +#endif + +#ifndef NETSTACK_CONF_FRAMER +#define NETSTACK_CONF_FRAMER framer_802154 +#endif + +#define NETSTACK_CONF_RADIO cc26xx_rf_driver +#define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 + +/* 6LoWPAN */ +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 +#define SICSLOWPAN_CONF_FRAG 1 +#define SICSLOWPAN_CONF_MAXAGE 8 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name IEEE address configuration + * + * Used to generate our RIME & IPv6 address + * @{ + */ +/** + * \brief Location of the IEEE address + * 0 => Read from InfoPage, + * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS + */ +#ifndef IEEE_ADDR_CONF_HARDCODED +#define IEEE_ADDR_CONF_HARDCODED 0 +#endif + +/** + * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED + * is defined as 1 + */ +#ifndef IEEE_ADDR_CONF_ADDRESS +#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name RF configuration + * + * @{ + */ +/* RF Config */ +#ifndef IEEE802154_CONF_PANID +#define IEEE802154_CONF_PANID 0xABCD /**< Default PAN ID */ +#endif + +#ifndef CC26XX_RF_CONF_CHANNEL +#define CC26XX_RF_CONF_CHANNEL 25 /**< Default RF channel */ +#endif + +#ifndef CC26XX_RF_CONF_AUTOACK +#define CC26XX_RF_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ +#endif + +#ifndef CC26XX_RF_CONF_PROMISCOUS +#define CC26XX_RF_CONF_PROMISCOUS 0 /**< 1 to enable promiscous mode */ +#endif + +#ifndef CC26XX_RF_CONF_BLE_SUPPORT +#define CC26XX_RF_CONF_BLE_SUPPORT 0 /**< 0 to disable BLE support */ +#endif + +/* + * Patch Management for the CPE itself and for BLE and IEEE modes + * + * Don't change these unless you know what you're doing + */ +#ifndef CC26XX_CONF_CPE_HAS_PATCHES +#define CC26XX_CONF_CPE_HAS_PATCHES 0 /**< 1 to enable patching the CPE */ +#endif + +#ifndef CC26XX_CONF_BLE_HAS_PATCHES +#define CC26XX_CONF_BLE_HAS_PATCHES 0 /**< 1 to enable patching BLE mode */ +#endif + +#ifndef CC26XX_CONF_IEEE_HAS_PATCHES +#define CC26XX_CONF_IEEE_HAS_PATCHES 0 /**< 1 to enable patching IEEE mode */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** + * \name IPv6, RIME and network buffer configuration + * + * @{ + */ +/* Don't let contiki-default-conf.h decide if we are an IPv6 build */ +#ifndef NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_WITH_IPV6 0 +#endif + +#if NETSTACK_CONF_WITH_IPV6 +/*---------------------------------------------------------------------------*/ +/* Addresses, Sizes and Interfaces */ +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* The size of the uIP main buffer */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1000 +#endif + +/* ND and Routing */ +#ifndef UIP_CONF_ROUTER +#define UIP_CONF_ROUTER 1 +#endif + +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_IP_FORWARD 0 +#define RPL_CONF_STATS 0 +#define RPL_CONF_MAX_DAG_ENTRIES 1 +#ifndef RPL_CONF_OF +#define RPL_CONF_OF rpl_mrhof +#endif + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#endif +#ifndef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 20 +#endif + +#ifndef UIP_CONF_TCP +#define UIP_CONF_TCP 1 +#endif +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS 128 +#endif + +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_ICMP6 1 +/*---------------------------------------------------------------------------*/ +#else /* NETSTACK_CONF_WITH_IPV6 */ +/* Network setup for non-IPv6 (rime). */ +#define UIP_CONF_IP_FORWARD 1 + +#define RIME_CONF_NO_POLITE_ANNOUCEMENTS 0 + +#endif /* NETSTACK_CONF_WITH_IPV6 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Generic Configuration directives + * + * @{ + */ +#ifndef ENERGEST_CONF_ON +#define ENERGEST_CONF_ON 0 /**< Energest Module */ +#endif + +#ifndef STARTUP_CONF_VERBOSE +#define STARTUP_CONF_VERBOSE 1 /**< Set to 0 to decrease startup verbosity */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Character I/O Configuration + * + * @{ + */ +#ifndef CC26XX_UART_CONF_ENABLE +#define CC26XX_UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ +#endif + +#ifndef CC26XX_UART_CONF_BAUD_RATE +#define CC26XX_UART_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ +#endif + +/* Turn off example-provided putchars */ +#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 +#define SLIP_RADIO_CONF_NO_PUTCHAR 1 + +#ifndef SLIP_ARCH_CONF_ENABLED +/* + * Determine whether we need SLIP + * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT + * keep using SLIP + */ +#if defined (UIP_FALLBACK_INTERFACE) || defined (CMD_CONF_OUTPUT) +#define SLIP_ARCH_CONF_ENABLED 1 +#endif +#endif + +/** + * \brief Define this as 1 to build a headless node. + * + * The UART will not be initialised its clock will be gated, offering some + * energy savings. The USB will not be initialised either + */ +#ifndef CC26XX_CONF_QUIET +#define CC26XX_CONF_QUIET 0 +#endif + +/* CC26XX_CONF_QUIET is hard and overrides all other related defines */ +#if CC26XX_CONF_QUIET +#undef CC26XX_UART_CONF_ENABLE +#define CC26XX_UART_CONF_ENABLE 0 + +#undef STARTUP_CONF_VERBOSE +#define STARTUP_CONF_VERBOSE 0 +#endif /* CC26XX_CONF_QUIET */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Button configurations + * + * Configure a button as power on/off: We use the right button for both boards. + * @{ + */ +#ifndef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 1 +#endif + +/* Notify various examples that we have Buttons */ +#define PLATFORM_HAS_BUTTON 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/* Platform-specific define to signify sensor reading failure */ +#define CC26XX_SENSOR_READING_ERROR 0x80000000 +/*---------------------------------------------------------------------------*/ +/** + * \name Compiler configuration and platform-specific type definitions + * + * Those values are not meant to be modified by the user + * @{ + */ +#define CLOCK_CONF_SECOND 128 + +/* Compiler configurations */ +#define CCIF +#define CLIF + +/* Platform typedefs */ +typedef uint32_t clock_time_t; +typedef uint32_t uip_stats_t; + +/* Clock (time) comparison macro */ +#define CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) + +/* + * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define + * RTIMER_CLOCK_LT to override this + */ +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +/** @} */ +/*---------------------------------------------------------------------------*/ +/* board.h assumes that basic configuration is done */ +#include "board.h" +/*---------------------------------------------------------------------------*/ +#endif /* CONTIKI_CONF_H */ + +/** @} */ diff --git a/platform/srf06-cc26xx/contiki-main.c b/platform/srf06-cc26xx/contiki-main.c new file mode 100644 index 000000000..d28643531 --- /dev/null +++ b/platform/srf06-cc26xx/contiki-main.c @@ -0,0 +1,256 @@ +/* + * 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-srf-tag SmartRF+CC26xx EM and the CC26xx SensorTag 2.0 + * + * This platform supports two different boards: + * 1) A standard TI SmartRF06EB with a CC26xx EM mounted on it and + * 2) The new TI SensorTag2.0 + * @{ + */ +#include "ti-lib.h" +#include "contiki.h" +#include "contiki-net.h" +#include "leds.h" +#include "lpm.h" +#include "gpio-interrupt.h" +#include "dev/watchdog.h" +#include "ieee-addr.h" +#include "vims.h" +#include "cc26xx-model.h" +#include "dev/cc26xx-uart.h" +#include "dev/cc26xx-rtc.h" +#include "dev/cc26xx-rf.h" +#include "sys_ctrl.h" +#include "uart.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "lib/sensors.h" +#include "button-sensor.h" +#include "dev/serial-line.h" +#include "net/mac/frame802154.h" + +#include "driverlib/driverlib_ver.h" + +#include +/*---------------------------------------------------------------------------*/ +static void +fade(unsigned char l) +{ + volatile int i; + int k, j; + for(k = 0; k < 800; ++k) { + j = k > 400 ? 800 - k : k; + + leds_on(l); + for(i = 0; i < j; ++i) { + __asm("nop"); + } + leds_off(l); + for(i = 0; i < 400 - j; ++i) { + __asm("nop"); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_rf_params(void) +{ + uint16_t short_addr; + uint8_t ext_addr[8]; + radio_value_t val = 0; + + ieee_addr_cpy_to(ext_addr, 8); + + short_addr = ext_addr[7]; + short_addr |= ext_addr[6] << 8; + + /* Populate linkaddr_node_addr. Maintain endianness */ + memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); + + NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); + NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); + NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC26XX_RF_CHANNEL); + NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); + + NETSTACK_RADIO.get_value(RADIO_PARAM_CHANNEL, &val); + printf(" RF: Channel %d\n", val); + +#if STARTUP_CONF_VERBOSE + { + int i; + printf(" Link layer addr: "); + for(i = 0; i < LINKADDR_SIZE - 1; i++) { + printf("%02x:", linkaddr_node_addr.u8[i]); + } + printf("%02x\n", linkaddr_node_addr.u8[i]); + } +#endif +} +/*---------------------------------------------------------------------------*/ +static void +select_lf_xosc(void) +{ + ti_lib_osc_interface_enable(); + + /* Make sure the SMPH clock within AUX is enabled */ + ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK); + while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY); + + /* Switch LF clock source to the LF RCOSC if required */ + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) { + ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_XOSC_LF); + } + + ti_lib_osc_interface_disable(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Main function for CC26xx-based platforms + * + * The same main() is used for both Srf+CC26xxEM as well as for the SensorTag + */ +int +main(void) +{ + /* Set the LF XOSC as the LF system clock source */ + select_lf_xosc(); + + /* + * Make sure to open the latches - this will be important when returning + * from shutdown + */ + ti_lib_pwr_ctrl_io_freeze_disable(); + + /* Use DCDC instead of LDO to save current */ + ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_DCDC); + + lpm_init(); + + board_init(); + + /* Enable flash cache and prefetch. */ + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED); + ti_lib_vims_configure(VIMS_BASE, true, true); + + gpio_interrupt_init(); + + /* Clock must always be enabled for the semaphore module */ + HWREG(AUX_WUC_BASE + AUX_WUC_O_MODCLKEN1) = AUX_WUC_MODCLKEN1_SMPH; + + leds_init(); + + fade(LEDS_RED); + + cc26xx_rtc_init(); + clock_init(); + rtimer_init(); + + board_init(); + + watchdog_init(); + process_init(); + + random_init(0x1234); + + /* Character I/O Initialisation */ +#if CC26XX_UART_CONF_ENABLE + cc26xx_uart_init(); + cc26xx_uart_set_input(serial_line_input_byte); +#endif + + serial_line_init(); + + printf("Starting " CONTIKI_VERSION_STRING "\n"); + printf("With CC26xxware v%u.%02u.%02u.%u\n", DRIVERLIB_MAJOR_VER, + DRIVERLIB_MINOR_VER, DRIVERLIB_PATCH_VER, DRIVERLIB_BUILD_ID); + printf(BOARD_STRING " using CC%u\n", CC26XX_MODEL_CPU_VARIANT); + + process_start(&etimer_process, NULL); + ctimer_init(); + + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); + + fade(LEDS_YELLOW); + + printf(" Net: "); + printf("%s\n", NETSTACK_NETWORK.name); + printf(" MAC: "); + printf("%s\n", NETSTACK_MAC.name); + printf(" RDC: "); + printf("%s", NETSTACK_RDC.name); + + if(NETSTACK_RDC.channel_check_interval() != 0) { + printf(", Channel Check Interval: %u ticks", + NETSTACK_RDC.channel_check_interval()); + } + printf("\n"); + + netstack_init(); + + set_rf_params(); + +#if NETSTACK_CONF_WITH_IPV6 + memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr)); + queuebuf_init(); + process_start(&tcpip_process, NULL); +#endif /* NETSTACK_CONF_WITH_IPV6 */ + + fade(LEDS_GREEN); + + process_start(&sensors_process, NULL); + + autostart_start(autostart_processes); + + watchdog_start(); + + fade(LEDS_ORANGE); + + while(1) { + uint8_t r; + do { + r = process_run(); + watchdog_periodic(); + } while(r > 0); + + /* Drop to some low power mode */ + lpm_drop(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/platform/srf06-cc26xx/sensortag/Makefile.sensortag new file mode 100644 index 000000000..98fad7a68 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -0,0 +1,8 @@ +CFLAGS += -DBOARD_SENSORTAG=1 -DTI_BSP_BOARD_HDR=\"ti-bsp-st.h\" +CFLAGS += -DBACKDOOR_IOID=0x00000000 + +BOARD_SOURCEFILES += leds-arch.c sensortag-sensors.c sensor-common.c +BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c +BOARD_SOURCEFILES += sht-21-sensor.c mpu-9250-sensor.c button-sensor.c +BOARD_SOURCEFILES += reed-relay.c ext-flash.c buzzer.c +BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c diff --git a/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c new file mode 100644 index 000000000..a3b85ccc2 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c @@ -0,0 +1,391 @@ +/* + * 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 sensortag-cc26xx-bmp-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26XX BMP280 Altimeter / Pressure Sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "bmp-280-sensor.h" +#include "sys/ctimer.h" +#include "sensor-common.h" +#include "board-i2c.h" +#include "ti-lib.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +#define BMP280_I2C_ADDRESS 0x77 +/*---------------------------------------------------------------------------*/ +/* Registers */ +#define ADDR_CALIB 0x88 +#define ADDR_PROD_ID 0xD0 +#define ADDR_RESET 0xE0 +#define ADDR_STATUS 0xF3 +#define ADDR_CTRL_MEAS 0xF4 +#define ADDR_CONFIG 0xF5 +#define ADDR_PRESS_MSB 0xF7 +#define ADDR_PRESS_LSB 0xF8 +#define ADDR_PRESS_XLSB 0xF9 +#define ADDR_TEMP_MSB 0xFA +#define ADDR_TEMP_LSB 0xFB +#define ADDR_TEMP_XLSB 0xFC +/*---------------------------------------------------------------------------*/ +/* Reset values */ +#define VAL_PROD_ID 0x58 +#define VAL_RESET 0x00 +#define VAL_STATUS 0x00 +#define VAL_CTRL_MEAS 0x00 +#define VAL_CONFIG 0x00 +#define VAL_PRESS_MSB 0x80 +#define VAL_PRESS_LSB 0x00 +#define VAL_TEMP_MSB 0x80 +#define VAL_TEMP_LSB 0x00 +/*---------------------------------------------------------------------------*/ +/* Test values */ +#define VAL_RESET_EXECUTE 0xB6 +#define VAL_CTRL_MEAS_TEST 0x55 +/*---------------------------------------------------------------------------*/ +/* Misc. */ +#define MEAS_DATA_SIZE 6 +#define CALIB_DATA_SIZE 24 +/*---------------------------------------------------------------------------*/ +#define RES_OFF 0 +#define RES_ULTRA_LOW_POWER 1 +#define RES_LOW_POWER 2 +#define RES_STANDARD 3 +#define RES_HIGH 5 +#define RES_ULTRA_HIGH 6 +/*---------------------------------------------------------------------------*/ +/* Bit fields in CTRL_MEAS register */ +#define PM_OFF 0 +#define PM_FORCED 1 +#define PM_NORMAL 3 +/*---------------------------------------------------------------------------*/ +#define OSRST(v) ((v) << 5) +#define OSRSP(v) ((v) << 2) +/*---------------------------------------------------------------------------*/ +typedef struct bmp_280_calibration { + uint16_t dig_t1; + int16_t dig_t2; + int16_t dig_t3; + uint16_t dig_p1; + int16_t dig_p2; + int16_t dig_p3; + int16_t dig_p4; + int16_t dig_p5; + int16_t dig_p6; + int16_t dig_p7; + int16_t dig_p8; + int16_t dig_p9; + int32_t t_fine; +} bmp_280_calibration_t; +/*---------------------------------------------------------------------------*/ +static uint8_t calibration_data[CALIB_DATA_SIZE]; +/*---------------------------------------------------------------------------*/ +#define SENSOR_STATUS_DISABLED 0 +#define SENSOR_STATUS_INITIALISED 1 +#define SENSOR_STATUS_NOT_READY 2 +#define SENSOR_STATUS_READY 3 + +static int enabled = SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/* A buffer for the raw reading from the sensor */ +#define SENSOR_DATA_BUF_SIZE 6 + +static uint8_t sensor_value[SENSOR_DATA_BUF_SIZE]; +/*---------------------------------------------------------------------------*/ +/* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - ~80ms */ +#define SENSOR_STARTUP_DELAY 11 + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + enabled = SENSOR_STATUS_READY; + sensors_changed(&bmp_280_sensor); +} +/*---------------------------------------------------------------------------*/ +static void +select(void) +{ + /* Set up I2C */ + board_i2c_select(BOARD_I2C_INTERFACE_0, BMP280_I2C_ADDRESS); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initalise the sensor + */ +static void +init(void) +{ + uint8_t val; + + select(); + + /* Read and store calibration data */ + sensor_common_read_reg(ADDR_CALIB, calibration_data, CALIB_DATA_SIZE); + + /* Reset the sensor */ + val = VAL_RESET_EXECUTE; + sensor_common_write_reg(ADDR_RESET, &val, sizeof(val)); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Enable/disable measurements + * \param enable 0: disable, enable otherwise + * + * @return none + */ +static void +enable_sensor(bool enable) +{ + uint8_t val; + + select(); + + if(enable) { + /* Enable forced mode */ + val = PM_NORMAL | OSRSP(1) | OSRST(1); + } else { + val = PM_OFF; + } + sensor_common_write_reg(ADDR_CTRL_MEAS, &val, sizeof(val)); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read temperature and pressure data + * \param data Pointer to a buffer where temperature and pressure will be + * written (6 bytes) + * \return True if valid data could be retrieved + */ +static bool +read_data(uint8_t *data) +{ + bool success; + + select(); + + success = sensor_common_read_reg(ADDR_PRESS_MSB, data, MEAS_DATA_SIZE); + if(!success) { + sensor_common_set_error_data(data, MEAS_DATA_SIZE); + } + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert raw data to values in degrees C (temp) and Pascal (pressure) + * \param data Pointer to a buffer that holds raw sensor data + * \param temp Pointer to a variable where the converted temperature will be + * written + * \param press Pointer to a variable where the converted pressure will be + * written + */ +static void +convert(uint8_t *data, int32_t *temp, uint32_t *press) +{ + int32_t utemp, upress; + bmp_280_calibration_t *p = (bmp_280_calibration_t *)calibration_data; + int32_t v_x1_u32r; + int32_t v_x2_u32r; + int32_t temperature; + uint32_t pressure; + + /* Pressure */ + upress = (int32_t)((((uint32_t)(data[0])) << 12) + | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4)); + + /* Temperature */ + utemp = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) + | ((uint32_t)data[5] >> 4)); + + /* Compensate temperature */ + v_x1_u32r = ((((utemp >> 3) - ((int32_t)p->dig_t1 << 1))) + * ((int32_t)p->dig_t2)) >> 11; + v_x2_u32r = (((((utemp >> 4) - ((int32_t)p->dig_t1)) + * ((utemp >> 4) - ((int32_t)p->dig_t1))) >> 12) + * ((int32_t)p->dig_t3)) + >> 14; + p->t_fine = v_x1_u32r + v_x2_u32r; + temperature = (p->t_fine * 5 + 128) >> 8; + *temp = temperature; + + /* Compensate pressure */ + v_x1_u32r = (((int32_t)p->t_fine) >> 1) - (int32_t)64000; + v_x2_u32r = (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 11) + * ((int32_t)p->dig_p6); + v_x2_u32r = v_x2_u32r + ((v_x1_u32r * ((int32_t)p->dig_p5)) << 1); + v_x2_u32r = (v_x2_u32r >> 2) + (((int32_t)p->dig_p4) << 16); + v_x1_u32r = + (((p->dig_p3 * (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 13)) >> 3) + + ((((int32_t)p->dig_p2) * v_x1_u32r) >> 1)) >> 18; + v_x1_u32r = ((((32768 + v_x1_u32r)) * ((int32_t)p->dig_p1)) >> 15); + + if(v_x1_u32r == 0) { + return; /* Avoid exception caused by division by zero */ + } + + pressure = (((uint32_t)(((int32_t)1048576) - upress) - (v_x2_u32r >> 12))) + * 3125; + if(pressure < 0x80000000) { + pressure = (pressure << 1) / ((uint32_t)v_x1_u32r); + } else { + pressure = (pressure / (uint32_t)v_x1_u32r) * 2; + } + + v_x1_u32r = (((int32_t)p->dig_p9) + * ((int32_t)(((pressure >> 3) * (pressure >> 3)) >> 13))) >> 12; + v_x2_u32r = (((int32_t)(pressure >> 2)) * ((int32_t)p->dig_p8)) >> 13; + pressure = (uint32_t)((int32_t)pressure + + ((v_x1_u32r + v_x2_u32r + p->dig_p7) >> 4)); + + *press = pressure; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param BMP_280_SENSOR_TYPE_TEMP or BMP_280_SENSOR_TYPE_PRESS + * \return Temperature (centi degrees C) or Pressure (Pascal). + */ +static int +value(int type) +{ + int rv; + int32_t temp = 0; + uint32_t pres = 0; + + if(enabled != SENSOR_STATUS_READY) { + PRINTF("Sensor disabled or starting up (%d)\n", enabled); + return CC26XX_SENSOR_READING_ERROR; + } + + if((type != BMP_280_SENSOR_TYPE_TEMP) && type != BMP_280_SENSOR_TYPE_PRESS) { + PRINTF("Invalid type\n"); + return CC26XX_SENSOR_READING_ERROR; + } else { + memset(sensor_value, 0, SENSOR_DATA_BUF_SIZE); + + rv = read_data(sensor_value); + + if(rv == 0) { + return CC26XX_SENSOR_READING_ERROR; + } + + PRINTF("val: %02x%02x%02x %02x%02x%02x\n", + sensor_value[0], sensor_value[1], sensor_value[2], + sensor_value[3], sensor_value[4], sensor_value[5]); + + convert(sensor_value, &temp, &pres); + + if(type == BMP_280_SENSOR_TYPE_TEMP) { + rv = (int)temp; + } else if(type == BMP_280_SENSOR_TYPE_PRESS) { + rv = (int)pres; + } + } + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the BMP280 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + enabled = SENSOR_STATUS_INITIALISED; + init(); + break; + case SENSORS_ACTIVE: + /* Must be initialised first */ + if(enabled == SENSOR_STATUS_DISABLED) { + return SENSOR_STATUS_DISABLED; + } + if(enable) { + enable_sensor(1); + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); + enabled = SENSOR_STATUS_NOT_READY; + } else { + ctimer_stop(&startup_timer); + enable_sensor(0); + enabled = SENSOR_STATUS_INITIALISED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the sensor is enabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(bmp_280_sensor, "BMP280", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h new file mode 100644 index 000000000..e27013c40 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h @@ -0,0 +1,70 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-bmp-sensor SensorTag 2.0 Pressure Sensor + * + * Due to the time required for the sensor to startup, this driver is meant to + * be used in an asynchronous fashion. The caller must first activate the + * sensor by calling SENSORS_ACTIVATE(). This will trigger the sensor's startup + * sequence, but the call will not wait for it to complete so that the CPU can + * perform other tasks or drop to a low power mode. + * + * Once the sensor is stable, the driver will generate a sensors_changed event. + * + * Once a reading has been taken, the caller has two options: + * - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take + * subsequent readings SENSORS_ACTIVATE must be called again + * - Leave the sensor on. In this scenario, the caller can simply keep calling + * value() for subsequent readings, but having the sensor on will consume + * energy + * @{ + * + * \file + * Header file for the Sensortag-CC26xx BMP280 Altimeter / Pressure Sensor + */ +/*---------------------------------------------------------------------------*/ +#ifndef BMP_280_SENSOR_H_ +#define BMP_280_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#define BMP_280_SENSOR_TYPE_TEMP 1 +#define BMP_280_SENSOR_TYPE_PRESS 2 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor bmp_280_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* BMP_280_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/board-i2c.c b/platform/srf06-cc26xx/sensortag/board-i2c.c new file mode 100644 index 000000000..0e1f544a6 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board-i2c.c @@ -0,0 +1,269 @@ +/* + * 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 sensortag-cc26xx-i2c + * @{ + * + * \file + * Board-specific I2C driver for the Sensortag-CC26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "ti-lib.h" +#include "board-i2c.h" +/*---------------------------------------------------------------------------*/ +static uint8_t slave_addr = 0x00; +static uint8_t interface = 0xFF; +/*---------------------------------------------------------------------------*/ +static bool +i2c_status() +{ + uint32_t status; + + status = ti_lib_i2c_master_err(I2C0_BASE); + if(status & (I2C_MSTAT_DATACK_N_M | I2C_MSTAT_ADRACK_N_M)) { + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP); + } + + return status == I2C_MASTER_ERR_NONE; +} +/*---------------------------------------------------------------------------*/ +void +board_i2c_init() +{ + /* The I2C peripheral must be enabled */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Reset the I2C controller */ + HWREG(PRCM_BASE + PRCM_O_RESETI2C) = PRCM_RESETI2C_I2C; + + /* Enable and initialize the I2C master module */ + ti_lib_i2c_master_init_exp_clk(I2C0_BASE, + ti_lib_sys_ctrl_peripheral_clock_get( + PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON), + true); +} +/*---------------------------------------------------------------------------*/ +bool +board_i2c_write(uint8_t *data, uint8_t len) +{ + uint32_t i; + bool success; + + /* Write slave address */ + ti_lib_i2c_master_slave_addr_set(I2C0_BASE, slave_addr, false); + + /* Write first byte */ + ti_lib_i2c_master_data_put(I2C0_BASE, data[0]); + + /* Check if another master has access */ + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + + /* Assert RUN + START */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + + for(i = 1; i < len && success; i++) { + /* Write next byte */ + ti_lib_i2c_master_data_put(I2C0_BASE, data[i]); + if(i < len - 1) { + /* Clear START */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + } + } + + /* Assert stop */ + if(success) { + /* Assert STOP */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + } + + return success; +} +/*---------------------------------------------------------------------------*/ +bool +board_i2c_write_single(uint8_t data) +{ + bool success; + + /* Write slave address */ + ti_lib_i2c_master_slave_addr_set(I2C0_BASE, slave_addr, false); + + /* Write first byte */ + ti_lib_i2c_master_data_put(I2C0_BASE, data); + + /* Check if another master has access */ + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + + /* Assert RUN + START + STOP */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + + return success; +} +/*---------------------------------------------------------------------------*/ +bool +board_i2c_read(uint8_t *data, uint8_t len) +{ + uint8_t i; + bool success; + + /* Set slave address */ + ti_lib_i2c_master_slave_addr_set(I2C0_BASE, slave_addr, true); + + /* Check if another master has access */ + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + + /* Assert RUN + START + ACK */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); + + i = 0; + success = true; + while(i < (len - 1) && success) { + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + if(success) { + data[i] = ti_lib_i2c_master_data_get(I2C0_BASE); + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); + i++; + } + } + + if(success) { + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + if(success) { + data[len - 1] = ti_lib_i2c_master_data_get(I2C0_BASE); + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + } + } + + return success; +} +/*---------------------------------------------------------------------------*/ +bool +board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata, uint8_t rlen) +{ + uint32_t i; + bool success; + + /* Set slave address for write */ + ti_lib_i2c_master_slave_addr_set(I2C0_BASE, slave_addr, false); + + /* Write first byte */ + ti_lib_i2c_master_data_put(I2C0_BASE, wdata[0]); + + /* Check if another master has access */ + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + + /* Assert RUN + START */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + + for(i = 1; i < wlen && success; i++) { + /* Write next byte */ + ti_lib_i2c_master_data_put(I2C0_BASE, wdata[i]); + if(i < wlen - 1) { + /* Clear START */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + } + } + if(!success) { + return false; + } + + /* Set slave address for read */ + ti_lib_i2c_master_slave_addr_set(I2C0_BASE, slave_addr, true); + + /* Assert ACK */ + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); + + i = 0; + while(i < (rlen - 1) && success) { + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + if(success) { + rdata[i] = ti_lib_i2c_master_data_get(I2C0_BASE); + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); + i++; + } + } + + if(success) { + while(ti_lib_i2c_master_busy(I2C0_BASE)); + success = i2c_status(); + if(success) { + rdata[rlen - 1] = ti_lib_i2c_master_data_get(I2C0_BASE); + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); + } + } + + return success; +} +/*---------------------------------------------------------------------------*/ +void +board_i2c_select(uint8_t new_interface, uint8_t address) +{ + slave_addr = address; + + if(new_interface != interface) { + interface = new_interface; + if(interface == BOARD_I2C_INTERFACE_0) { + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_NO_IOPULL); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_NO_IOPULL); + ti_lib_ioc_pin_type_i2c(I2C0_BASE, BOARD_IOID_SDA, BOARD_IOID_SCL); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA_HP); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL_HP); + } else if(interface == BOARD_I2C_INTERFACE_1) { + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA_HP, IOC_NO_IOPULL); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL_HP, IOC_NO_IOPULL); + ti_lib_ioc_pin_type_i2c(I2C0_BASE, BOARD_IOID_SDA_HP, BOARD_IOID_SCL_HP); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL); + } + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/board-i2c.h b/platform/srf06-cc26xx/sensortag/board-i2c.h new file mode 100644 index 000000000..bed78cf46 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board-i2c.h @@ -0,0 +1,108 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-i2c SensorTag 2.0 I2C functions + * @{ + * + * \file + * Header file for the Sensortag-CC26xx I2C Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_I2C_H_ +#define BOARD_I2C_H_ +/*---------------------------------------------------------------------------*/ +#include +#include +/*---------------------------------------------------------------------------*/ +#define BOARD_I2C_INTERFACE_0 0 +#define BOARD_I2C_INTERFACE_1 1 +/*---------------------------------------------------------------------------*/ +#define board_i2c_deselect(...) +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the I2C controller with defaults for the sensortag + */ +void board_i2c_init(void); + +/** + * \brief Select an I2C slave + * \param interface The I2C interface to be used (BOARD_I2C_INTERFACE_0 or _1) + * \param slave_addr The slave's address + * + * The various sensors on the sensortag are connected either on interface 0 or + * 1. All sensors are connected to interface 0, with the exception of the MPU + * that is connected to 1. + */ +void board_i2c_select(uint8_t interface, uint8_t slave_addr); + +/** + * \brief Burst read from an I2C device + * \param buf Pointer to a buffer where the read data will be stored + * \param len Number of bytes to read + * \return True on success + */ +bool board_i2c_read(uint8_t *buf, uint8_t len); + +/** + * \brief Burst write to an I2C device + * \param buf Pointer to the buffer to be written + * \param len Number of bytes to write + * \return True on success + */ +bool board_i2c_write(uint8_t *buf, uint8_t len); + +/** + * \brief Single write to an I2C device + * \param data The byte to write + * \return True on success + */ +bool board_i2c_write_single(uint8_t data); + +/** + * \brief Write and read in one operation + * \param wdata Pointer to the buffer to be written + * \param wlen Number of bytes to write + * \param rdata Pointer to a buffer where the read data will be stored + * \param rlen Number of bytes to read + * \return True on success + */ +bool board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata, + uint8_t rlen); +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_I2C_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/board-peripherals.h b/platform/srf06-cc26xx/sensortag/board-peripherals.h new file mode 100644 index 000000000..aa61ab333 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board-peripherals.h @@ -0,0 +1,56 @@ +/* + * 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-srf-tag + * @{ + * + * \file + * Header file with definitions related to the sensors on the Sensortag-CC26xx + * + * \note Do not include this file directly. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_PERIPHERALS_H_ +#define BOARD_PERIPHERALS_H_ +/*---------------------------------------------------------------------------*/ +#include "bmp-280-sensor.h" +#include "tmp-007-sensor.h" +#include "opt-3001-sensor.h" +#include "sht-21-sensor.h" +#include "mpu-9250-sensor.h" +#include "reed-relay.h" +#include "buzzer.h" +#include "ext-flash.h" +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_PERIPHERALS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/board-spi.c b/platform/srf06-cc26xx/sensortag/board-spi.c new file mode 100644 index 000000000..01dd65857 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board-spi.c @@ -0,0 +1,118 @@ +/* + * 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 sensortag-cc26xx-spi + * @{ + * + * \file + * Board-specific SPI driver for the Sensortag-CC26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "ti-lib.h" +#include "board-spi.h" +#include "board.h" +/*---------------------------------------------------------------------------*/ +#define CPU_FREQ 48000000ul +/*---------------------------------------------------------------------------*/ +int +board_spi_write(const uint8_t *buf, size_t len) +{ + while(len > 0) { + uint32_t ul; + + ti_lib_ssi_data_put(SSI0_BASE, *buf); + ti_lib_rom_ssi_data_get(SSI0_BASE, &ul); + len--; + buf++; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +int +board_spi_read(uint8_t *buf, size_t len) +{ + while(len > 0) { + uint32_t ul; + + if(!ti_lib_rom_ssi_data_put_non_blocking(SSI0_BASE, 0)) { + /* Error */ + return -1; + } + ti_lib_rom_ssi_data_get(SSI0_BASE, &ul); + *buf = (uint8_t)ul; + len--; + buf++; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +board_spi_flush() +{ + uint32_t ul; + while(ti_lib_rom_ssi_data_get_non_blocking(SSI0_BASE, &ul)); +} +/*---------------------------------------------------------------------------*/ +void +board_spi_open(uint32_t bit_rate, uint32_t clk_pin) +{ + uint32_t buf; + + /* SPI power */ + ti_lib_rom_prcm_peripheral_run_enable(PRCM_PERIPH_SSI0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* SPI configuration */ + ti_lib_ssi_int_disable(SSI0_BASE, SSI_RXOR | SSI_RXFF | SSI_RXTO | SSI_TXFF); + ti_lib_ssi_int_clear(SSI0_BASE, SSI_RXOR | SSI_RXTO); + ti_lib_rom_ssi_config_set_exp_clk(SSI0_BASE, CPU_FREQ, SSI_FRF_MOTO_MODE_0, + SSI_MODE_MASTER, bit_rate, 8); + ti_lib_rom_ioc_pin_type_ssi_master(SSI0_BASE, BOARD_IOID_SPI_MISO, + BOARD_IOID_SPI_MOSI, IOID_UNUSED, clk_pin); + ti_lib_ssi_enable(SSI0_BASE); + + /* Get rid of residual data from SSI port */ + while(ti_lib_ssi_data_get_non_blocking(SSI0_BASE, &buf)); +} +/*---------------------------------------------------------------------------*/ +void +board_spi_close() +{ + /* Power down SSI0 */ + ti_lib_rom_prcm_peripheral_run_disable(PRCM_PERIPH_SSI0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/board-spi.h b/platform/srf06-cc26xx/sensortag/board-spi.h new file mode 100644 index 000000000..0c1e49d1f --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board-spi.h @@ -0,0 +1,90 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-spi SensorTag 2.0 SPI functions + * @{ + * + * \file + * Header file for the Sensortag-CC26xx SPI Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_SPI_H_ +#define BOARD_SPI_H_ +/*---------------------------------------------------------------------------*/ +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the SPI interface + * \param bit_rate The bit rate to use + * \param clk_pin The IOID for the clock pin. This can be IOID_0 etc + * \return none + */ +void board_spi_open(uint32_t bit_rate, uint32_t clk_pin); + +/** + * \brief Close the SPI interface + * \return True when successful. + */ +void board_spi_close(void); + +/** + * \brief Clear data from the SPI interface + * \return none + */ +void board_spi_flush(void); + +/** + * \brief Read from an SPI device + * \param buf The buffer to store data + * \param length The number of bytes to read + * \return True when successful. + */ +int board_spi_read(uint8_t *buf, size_t length); + +/** + * \brief Write to an SPI device + * \param buf The buffer with the data to write + * \param length The number of bytes to write + * \return True when successful. + */ +int board_spi_write(const uint8_t *buf, size_t length); +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_SPI_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/board.c b/platform/srf06-cc26xx/sensortag/board.c new file mode 100644 index 000000000..5246a85ef --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board.c @@ -0,0 +1,152 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \file + * Sensortag-specific board initialisation driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "buzzer.h" +#include "lpm.h" +#include "ti-lib.h" +#include "board-peripherals.h" +#include "board-i2c.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define PRCM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH) +/*---------------------------------------------------------------------------*/ +static void +power_domains_on(void) +{ + /* Turn on relevant power domains */ + ti_lib_prcm_power_domain_on(PRCM_DOMAINS); + + /* Wait for domains to power on */ + while((ti_lib_prcm_power_domain_status(PRCM_DOMAINS) + != PRCM_DOMAIN_POWER_ON)); +} +/*---------------------------------------------------------------------------*/ +static void +lpm_wakeup_handler(void) +{ + power_domains_on(); + + board_i2c_init(); +} +/*---------------------------------------------------------------------------*/ +static void +shutdown_handler(uint8_t mode) +{ + if(mode == LPM_MODE_SHUTDOWN) { + buzzer_stop(); + SENSORS_DEACTIVATE(bmp_280_sensor); + SENSORS_DEACTIVATE(opt_3001_sensor); + SENSORS_DEACTIVATE(tmp_007_sensor); + SENSORS_DEACTIVATE(sht_21_sensor); + mpu_9250_sensor.configure(MPU_9250_SENSOR_SHUTDOWN, 0); + } +} +/*---------------------------------------------------------------------------*/ +/* + * Declare a data structure to register with LPM. + * We don't care about what power mode we'll drop to, we don't care about + * getting notified before deep sleep. All we need is to be notified when we + * wake up so we can turn power domains back on for I2C and SSI, and to make + * sure everything on the board is off before CM3 shutdown. + */ +LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler); +/*---------------------------------------------------------------------------*/ +void +board_init() +{ + /* Disable global interrupts */ + uint8_t int_disabled = ti_lib_int_master_disable(); + + power_domains_on(); + + /* Configure all clock domains to run at full speed */ + ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS, PRCM_CLOCK_DIV_1); + ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_CPU, PRCM_CLOCK_DIV_1); + ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_TIMER, PRCM_CLOCK_DIV_1); + ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SERIAL, PRCM_CLOCK_DIV_1); + ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_PERIPH, PRCM_CLOCK_DIV_1); + + /* Enable GPIO peripheral */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); + + /* Apply settings and wait for them to take effect */ + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Enable GPT0 module - Wait for the clock to be enabled */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Keys (input pullup) */ + ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT); + ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_LEFT, IOC_IOPULL_UP); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP); + + /* I2C controller */ + board_i2c_init(); + + /* Sensor interface */ + ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN); + + ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_REED_RELAY); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_REED_RELAY, IOC_IOPULL_DOWN); + + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER); + + /* Flash interface */ + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS); + ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1); + + buzzer_init(); + + lpm_register_module(&sensortag_module); + + /* Re-enable interrupt if initially enabled. */ + if(!int_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/board.h b/platform/srf06-cc26xx/sensortag/board.h new file mode 100644 index 000000000..00afb98f2 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/board.h @@ -0,0 +1,206 @@ +/* + * 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-srf-tag + * @{ + * + * \defgroup sensortag-cc26xx-peripherals Sensortag Peripherals + * + * Defines related to the Sensortag-CC26XX + * + * This file provides connectivity information on LEDs, Buttons, UART and + * other peripherals + * + * This file can be used as the basis to configure other boards using the + * CC26XX code as their basis. + * + * This file is not meant to be modified by the user. + * @{ + * + * \file + * Header file with definitions related to the I/O connections on the TI + * Sensortag + * + * \note Do not include this file directly. It gets included by contiki-conf + * after all relevant directives have been set. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_H_ +#define BOARD_H_ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +/*---------------------------------------------------------------------------*/ +/** + * \name LED configurations + * + * Those values are not meant to be modified by the user + * @{ + */ +/* Some files include leds.h before us, so we need to get rid of defaults in + * leds.h before we provide correct definitions */ +#undef LEDS_GREEN +#undef LEDS_YELLOW +#undef LEDS_RED +#undef LEDS_CONF_ALL + +#define LEDS_RED 1 +#define LEDS_GREEN 2 +#define LEDS_YELLOW LEDS_GREEN +#define LEDS_ORANGE LEDS_RED + +#define LEDS_CONF_ALL 3 + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LED IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_LED_1 IOID_10 +#define BOARD_IOID_LED_2 IOID_15 +#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) +#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) +#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name UART IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_UART_RX IOID_17 +#define BOARD_IOID_UART_TX IOID_16 +#define BOARD_IOID_UART_CTS IOID_UNUSED +#define BOARD_IOID_UART_RTS IOID_UNUSED +#define BOARD_UART_RXD (1 << BOARD_IOID_UART_RXD) +#define BOARD_UART_TXD (1 << BOARD_IOID_UART_TXD) +#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) +#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Button IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_KEY_LEFT IOID_0 +#define BOARD_IOID_KEY_RIGHT IOID_4 +#define BOARD_KEY_LEFT (1 << BOARD_IOID_KEY_LEFT) +#define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief SPI IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SPI_MOSI IOID_19 +#define BOARD_IOID_SPI_MISO IOID_18 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Buzzer configuration + * @{ + */ +#define BOARD_IOID_BUZZER IOID_21 /**< Buzzer Pin */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Reed Relay IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_REED_RELAY IOID_3 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name External flash IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_FLASH_CS IOID_14 +#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) +#define BOARD_SPI_CLK_FLASH IOID_11 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief I2C IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SDA IOID_5 /**< Interface 0 SDA: All sensors bar MPU */ +#define BOARD_IOID_SCL IOID_6 /**< Interface 0 SCL: All sensors bar MPU */ +#define BOARD_IOID_SDA_HP IOID_8 /**< Interface 1 SDA: MPU */ +#define BOARD_IOID_SCL_HP IOID_9 /**< Interface 1 SCL: MPU */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief MPU IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_MPU_INT IOID_7 +#define BOARD_IOID_MPU_POWER IOID_12 +#define BOARD_MPU_INT (1 << BOARD_IOID_MPU_INT) +#define BOARD_MPU_POWER (1 << BOARD_IOID_MPU_POWER) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "TI CC2650 SensorTag" + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Board specific iniatialisation + * @{ + */ +void board_init(void); +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/button-sensor.c b/platform/srf06-cc26xx/sensortag/button-sensor.c new file mode 100644 index 000000000..089ea7332 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/button-sensor.c @@ -0,0 +1,282 @@ +/* + * 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 sensortag-cc26xx-button-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26xx buttons + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "sensortag/button-sensor.h" +#include "gpio-interrupt.h" +#include "sys/timer.h" +#include "lpm.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#else +#define BUTTON_SENSOR_ENABLE_SHUTDOWN 1 +#endif +/*---------------------------------------------------------------------------*/ +#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ + IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ + IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ + IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ + IOC_JTAG_DISABLE) +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) + +struct btn_timer { + struct timer debounce; + clock_time_t start; + clock_time_t duration; +}; + +static struct btn_timer left_timer, right_timer; +/*---------------------------------------------------------------------------*/ +/** + * \brief Handler for Sensortag-CC26XX button presses + */ +static void +button_press_handler(uint8_t ioid) +{ + if(ioid == BOARD_IOID_KEY_LEFT) { + if(!timer_expired(&left_timer.debounce)) { + return; + } + + timer_set(&left_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0) { + left_timer.start = clock_time(); + left_timer.duration = 0; + } else { + left_timer.duration = clock_time() - left_timer.start; + sensors_changed(&button_left_sensor); + } + } + + if(ioid == BOARD_IOID_KEY_RIGHT) { + if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { + if(!timer_expired(&right_timer.debounce)) { + return; + } + + timer_set(&right_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0) { + right_timer.start = clock_time(); + right_timer.duration = 0; + } else { + right_timer.duration = clock_time() - right_timer.start; + sensors_changed(&button_right_sensor); + } + } else { + lpm_shutdown(BOARD_IOID_KEY_RIGHT); + } + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the button sensor for all buttons. + * + * \param type This function does nothing unless type == SENSORS_ACTIVE + * \param c 0: disable the button, non-zero: enable + * \param key: One of BOARD_KEY_LEFT, BOARD_KEY_RIGHT etc + */ +static void +config_buttons(int type, int c, uint32_t key) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_gpio_event_clear(1 << key); + ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); + ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN); + gpio_interrupt_register_handler(key, button_press_handler); + break; + case SENSORS_ACTIVE: + if(c) { + ti_lib_gpio_event_clear(1 << key); + ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); + ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN); + ti_lib_ioc_int_enable(key); + } else { + ti_lib_ioc_int_disable(key); + } + break; + default: + break; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the left button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor API. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_left(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_LEFT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the right button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor api. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_right(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_RIGHT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for all buttons + * \param type SENSORS_ACTIVE or SENSORS_READY + * \param key_io_id BOARD_IOID_KEY_LEFT, BOARD_IOID_KEY_RIGHT etc + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will only be called by status_left, status_right and the + * called will pass the correct key_io_id + */ +static int +status(int type, uint32_t key_io_id) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) { + return 1; + } + break; + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_left(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)left_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_right(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)right_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the left button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_left(int type) +{ + return status(type, BOARD_IOID_KEY_LEFT); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the right button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_right(int type) +{ + return status(type, BOARD_IOID_KEY_RIGHT); +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left, + status_left); +SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right, + status_right); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/button-sensor.h b/platform/srf06-cc26xx/sensortag/button-sensor.h new file mode 100644 index 000000000..6e15b4d4c --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/button-sensor.h @@ -0,0 +1,66 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-button-sensor SensorTag 2.0 Button Sensor + * + * One of the buttons can be configured as general purpose or as an on/off key + * @{ + * + * \file + * Header file for the Sensortag-CC26xx Button Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_VALUE_STATE 0 +#define BUTTON_SENSOR_VALUE_DURATION 1 + +#define BUTTON_SENSOR_VALUE_RELEASED 0 +#define BUTTON_SENSOR_VALUE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +#define button_sensor button_left_sensor +extern const struct sensors_sensor button_left_sensor; +extern const struct sensors_sensor button_right_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/buzzer.c b/platform/srf06-cc26xx/sensortag/buzzer.c new file mode 100644 index 000000000..57d063897 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/buzzer.c @@ -0,0 +1,124 @@ +/* + * 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 sensortag-cc26xx-buzzer + * @{ + * + * \file + * Driver for the Sensortag-CC26XX Buzzer + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "buzzer.h" +#include "ti-lib.h" +#include "lpm.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +static uint8_t buzzer_on; +static lpm_power_domain_lock_t lock; +/*---------------------------------------------------------------------------*/ +void +buzzer_init() +{ + buzzer_on = 0; + + /* Drive the I/O ID with GPT0 / Timer A */ + ti_lib_ioc_port_configure_set(BOARD_IOID_BUZZER, IOC_PORT_MCU_PORT_EVENT0, + IOC_STD_OUTPUT); + + /* GPT0 / Timer A: PWM, Interrupt Enable */ + HWREG(GPT0_BASE + GPT_O_TAMR) = (TIMER_CFG_A_PWM & 0xFF) | GPT_TAMR_TAPWMIE; +} +/*---------------------------------------------------------------------------*/ +uint8_t +buzzer_state() +{ + return buzzer_on; +} +/*---------------------------------------------------------------------------*/ +void +buzzer_start(int freq) +{ + uint32_t load; + + buzzer_on = 1; + + lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_PERIPH); + + /* Stop the timer */ + ti_lib_timer_disable(GPT0_BASE, TIMER_A); + + if(freq > 0) { + load = (GET_MCU_CLOCK / freq); + + ti_lib_timer_load_set(GPT0_BASE, TIMER_A, load); + ti_lib_timer_match_set(GPT0_BASE, TIMER_A, load / 2); + + /* Start */ + ti_lib_timer_enable(GPT0_BASE, TIMER_A); + } + + /* Run in sleep mode */ + ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +void +buzzer_stop() +{ + buzzer_on = 0; + + lpm_pd_lock_release(&lock); + + /* Stop the timer */ + ti_lib_timer_disable(GPT0_BASE, TIMER_A); + + /* + * Stop running in sleep mode. + * ToDo: Currently GPT0 is in use by clock_delay_usec (GPT0/TB) and by this + * module here (GPT0/TA). clock_delay_usec will never need GPT0/TB in sleep + * mode and we control TA here. Thus, with the current setup, it's OK to + * control whether GPT0 runs in sleep mode in this module here. However, if + * some other module at some point starts using GPT0, we should change this + * to happen through an umbrella module + */ + ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/buzzer.h b/platform/srf06-cc26xx/sensortag/buzzer.h new file mode 100644 index 000000000..653b46f88 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/buzzer.h @@ -0,0 +1,74 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-buzzer SensorTag 2.0 Buzzer + * @{ + * + * \file + * Header file for the Sensortag-CC26xx Buzzer + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUZZER_H_ +#define BUZZER_H_ +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the buzzer + */ +void buzzer_init(void); + +/** + * \brief Start the buzzer + * \param freq The buzzer frequency + */ +void buzzer_start(int freq); + +/** + * \brief Stop the buzzer + */ +void buzzer_stop(void); + +/** + * \brief Retrieve the buzzer state + * \return 1: on, 0: off + */ +uint8_t buzzer_state(void); +/*---------------------------------------------------------------------------*/ +#endif /* BUZZER_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/ext-flash.c b/platform/srf06-cc26xx/sensortag/ext-flash.c new file mode 100644 index 000000000..83d2758a4 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/ext-flash.c @@ -0,0 +1,409 @@ +/* + * 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 sensortag-cc26xx-ext-flash + * @{ + * + * \file + * Driver for the Sensortag-CC26xx WinBond W25X20CL Flash + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "ext-flash.h" +#include "ti-lib.h" +#include "board-spi.h" +/*---------------------------------------------------------------------------*/ +/* Instruction codes */ + +#define BLS_CODE_PROGRAM 0x02 /**< Page Program */ +#define BLS_CODE_READ 0x03 /**< Read Data */ +#define BLS_CODE_READ_STATUS 0x05 /**< Read Status Register */ +#define BLS_CODE_WRITE_ENABLE 0x06 /**< Write Enable */ +#define BLS_CODE_SECTOR_ERASE 0x20 /**< Sector Erase */ +#define BLS_CODE_MDID 0x90 /**< Manufacturer Device ID */ + +#define BLS_CODE_DP 0xB9 /**< Power down */ +#define BLS_CODE_RDP 0xAB /**< Power standby */ +/*---------------------------------------------------------------------------*/ +/* Erase instructions */ + +#define BLS_CODE_ERASE_4K 0x20 /**< Sector Erase */ +#define BLS_CODE_ERASE_32K 0x52 +#define BLS_CODE_ERASE_64K 0xD8 +#define BLS_CODE_ERASE_ALL 0xC7 /**< Mass Erase */ +/*---------------------------------------------------------------------------*/ +/* Bitmasks of the status register */ + +#define BLS_STATUS_SRWD_BM 0x80 +#define BLS_STATUS_BP_BM 0x0C +#define BLS_STATUS_WEL_BM 0x02 +#define BLS_STATUS_WIP_BM 0x01 + +#define BLS_STATUS_BIT_BUSY 0x01 /**< Busy bit of the status register */ +/*---------------------------------------------------------------------------*/ +/* Part specific constants */ + +#define BLS_MANUFACTURER_ID 0xEF +#define BLS_DEVICE_ID 0x11 + +#define BLS_PROGRAM_PAGE_SIZE 256 +#define BLS_ERASE_SECTOR_SIZE 4096 +/*---------------------------------------------------------------------------*/ +/** + * Clear external flash CSN line + */ +static void +select(void) +{ + ti_lib_gpio_pin_write(BOARD_FLASH_CS, 0); +} +/*---------------------------------------------------------------------------*/ +/** + * Set external flash CSN line + */ +static void +deselect(void) +{ + ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Wait till previous erase/program operation completes. + * \return Zero when successful. + */ +static int +wait_ready(void) +{ + const uint8_t wbuf[1] = { BLS_CODE_READ_STATUS }; + + select(); + + /* Throw away all garbages */ + board_spi_flush(); + + int ret = board_spi_write(wbuf, sizeof(wbuf)); + + if(ret) { + deselect(); + return -2; + } + + for(;;) { + uint8_t buf; + /* Note that this temporary implementation is not + * energy efficient. + * Thread could have yielded while waiting for flash + * erase/program to complete. + */ + ret = board_spi_read(&buf, sizeof(buf)); + + if(ret) { + /* Error */ + deselect(); + return -2; + } + if(!(buf & BLS_STATUS_BIT_BUSY)) { + /* Now ready */ + break; + } + } + deselect(); + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Put the device in power save mode. No access to data; only + * the status register is accessible. + * \return True when SPI transactions succeed + */ +static bool +power_down(void) +{ + uint8_t cmd; + bool success; + + cmd = BLS_CODE_DP; + select(); + success = board_spi_write(&cmd, sizeof(cmd)); + deselect(); + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Take device out of power save mode and prepare it for normal operation + * \return True if the command was written successfully + */ +static bool +power_standby(void) +{ + uint8_t cmd; + bool success; + + cmd = BLS_CODE_RDP; + select(); + success = board_spi_write(&cmd, sizeof(cmd)); + + if(success) { + success = wait_ready() == 0; + } + + deselect(); + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * Verify the flash part. + * @return True when successful. + */ +static bool +verify_part(void) +{ + const uint8_t wbuf[] = { BLS_CODE_MDID, 0xFF, 0xFF, 0x00 }; + uint8_t rbuf[2]; + int ret; + + select(); + + ret = board_spi_write(wbuf, sizeof(wbuf)); + + if(ret) { + deselect(); + return false; + } + + ret = board_spi_read(rbuf, sizeof(rbuf)); + deselect(); + + if(ret || rbuf[0] != BLS_MANUFACTURER_ID || rbuf[1] != BLS_DEVICE_ID) { + return false; + } + return true; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Enable write. + * \return Zero when successful. + */ +static int +write_enable(void) +{ + const uint8_t wbuf[] = { BLS_CODE_WRITE_ENABLE }; + + select(); + int ret = board_spi_write(wbuf, sizeof(wbuf)); + deselect(); + + if(ret) { + return -3; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +bool +ext_flash_open() +{ + board_spi_open(4000000, BOARD_SPI_CLK_FLASH); + + /* GPIO pin configuration */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS); + + /* Default output to clear chip select */ + deselect(); + + /* Put the part is standby mode */ + power_standby(); + + return verify_part(); +} +/*---------------------------------------------------------------------------*/ +void +ext_flash_close() +{ + /* Put the part in low power mode */ + power_down(); + + board_spi_close(); +} +/*---------------------------------------------------------------------------*/ +bool +ext_flash_read(size_t offset, size_t length, uint8_t *buf) +{ + uint8_t wbuf[4]; + + /* Wait till previous erase/program operation completes */ + int ret = wait_ready(); + if(ret) { + return false; + } + + /* + * SPI is driven with very low frequency (1MHz < 33MHz fR spec) + * in this implementation, hence it is not necessary to use fast read. + */ + wbuf[0] = BLS_CODE_READ; + wbuf[1] = (offset >> 16) & 0xff; + wbuf[2] = (offset >> 8) & 0xff; + wbuf[3] = offset & 0xff; + + select(); + + if(board_spi_write(wbuf, sizeof(wbuf))) { + /* failure */ + deselect(); + return false; + } + + ret = board_spi_read(buf, length); + + deselect(); + + return ret == 0; +} +/*---------------------------------------------------------------------------*/ +bool +ext_flash_write(size_t offset, size_t length, const uint8_t *buf) +{ + uint8_t wbuf[4]; + int ret; + size_t ilen; /* interim length per instruction */ + + while(length > 0) { + /* Wait till previous erase/program operation completes */ + ret = wait_ready(); + if(ret) { + return false; + } + + ret = write_enable(); + if(ret) { + return false; + } + + ilen = BLS_PROGRAM_PAGE_SIZE - (offset % BLS_PROGRAM_PAGE_SIZE); + if(length < ilen) { + ilen = length; + } + + wbuf[0] = BLS_CODE_PROGRAM; + wbuf[1] = (offset >> 16) & 0xff; + wbuf[2] = (offset >> 8) & 0xff; + wbuf[3] = offset & 0xff; + + offset += ilen; + length -= ilen; + + /* Upto 100ns CS hold time (which is not clear + * whether it's application only inbetween reads) + * is not imposed here since above instructions + * should be enough to delay + * as much. */ + select(); + + if(board_spi_write(wbuf, sizeof(wbuf))) { + /* failure */ + deselect(); + return false; + } + + if(board_spi_write(buf, ilen)) { + /* failure */ + deselect(); + return false; + } + buf += ilen; + deselect(); + } + + return true; +} +/*---------------------------------------------------------------------------*/ +bool +ext_flash_erase(size_t offset, size_t length) +{ + /* + * Note that Block erase might be more efficient when the floor map + * is well planned for OTA, but to simplify this implementation, + * sector erase is used blindly. + */ + uint8_t wbuf[4]; + size_t i, numsectors; + size_t endoffset = offset + length - 1; + + offset = (offset / BLS_ERASE_SECTOR_SIZE) * BLS_ERASE_SECTOR_SIZE; + numsectors = (endoffset - offset + BLS_ERASE_SECTOR_SIZE - 1) / BLS_ERASE_SECTOR_SIZE; + + wbuf[0] = BLS_CODE_SECTOR_ERASE; + + for(i = 0; i < numsectors; i++) { + /* Wait till previous erase/program operation completes */ + int ret = wait_ready(); + if(ret) { + return false; + } + + ret = write_enable(); + if(ret) { + return false; + } + + wbuf[1] = (offset >> 16) & 0xff; + wbuf[2] = (offset >> 8) & 0xff; + wbuf[3] = offset & 0xff; + + select(); + + if(board_spi_write(wbuf, sizeof(wbuf))) { + /* failure */ + deselect(); + return false; + } + deselect(); + + offset += BLS_ERASE_SECTOR_SIZE; + } + + return true; +} +/*---------------------------------------------------------------------------*/ +bool +ext_flash_test(void) +{ + bool ret; + + ret = ext_flash_open(); + ext_flash_close(); + + return ret; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/ext-flash.h b/platform/srf06-cc26xx/sensortag/ext-flash.h new file mode 100644 index 000000000..ca2ef80ea --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/ext-flash.h @@ -0,0 +1,103 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-ext-flash SensorTag 2.0 External Flash + * @{ + * + * \file + * Header file for the Sensortag-CC26xx External Flash Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef EXT_FLASH_H_ +#define EXT_FLASH_H_ +/*---------------------------------------------------------------------------*/ +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize storage driver. + * \return True when successful. + */ +bool ext_flash_open(void); + +/** + * \brief Close the storage driver + */ +void ext_flash_close(void); + +/** + * \brief Read storage content + * \param offset Address to read from + * \param length Number of bytes to read + * \param buf Buffer where to store the read bytes + * \return True when successful. + * + * buf must be allocated by the caller + */ +bool ext_flash_read(size_t offset, size_t length, uint8_t *buf); + +/** + * \brief Erase storage sectors corresponding to the range. + * \param offset Address to start erasing + * \param length Number of bytes to erase + * \return True when successful. + * + * The erase operation will be sector-wise, therefore a call to this function + * will generally start the erase procedure at an address lower than offset + */ +bool ext_flash_erase(size_t offset, size_t length); + +/** + * \brief Write to storage sectors. + * \param offset Address to write to + * \param length Number of bytes to write + * \param buf Buffer holding the bytes to be written + * + * \return True when successful. + */ +bool ext_flash_write(size_t offset, size_t length, const uint8_t *buf); + +/** + * \brief Test the flash (power on self-test) + * \return True when successful. + */ +bool ext_flash_test(void); +/*---------------------------------------------------------------------------*/ +#endif /* EXT_FLASH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/leds-arch.c b/platform/srf06-cc26xx/sensortag/leds-arch.c new file mode 100644 index 000000000..e415dca55 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/leds-arch.c @@ -0,0 +1,81 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \file + * Driver for the Sensortag-CC26XX LEDs + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" + +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +static unsigned char c; +static int inited = 0; +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + if(inited) { + return; + } + inited = 1; + + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); + + ti_lib_gpio_pin_write(BOARD_LED_ALL, 0); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return c; +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + c = leds; + ti_lib_gpio_pin_write(BOARD_LED_ALL, 0); + + if((leds & LEDS_RED) == LEDS_RED) { + ti_lib_gpio_pin_write(BOARD_LED_1, 1); + } + if((leds & LEDS_YELLOW) == LEDS_YELLOW) { + ti_lib_gpio_pin_write(BOARD_LED_2, 1); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c new file mode 100644 index 000000000..fd7bff688 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c @@ -0,0 +1,685 @@ +/* + * 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 sensortag-cc26xx-mpu + * @{ + * + * \file + * Driver for the Sensortag-CC26XX Invensense MPU9250 motion processing unit + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "mpu-9250-sensor.h" +#include "sys/rtimer.h" +#include "sensor-common.h" +#include "board-i2c.h" + +#include "ti-lib.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Sensor I2C address */ +#define SENSOR_I2C_ADDRESS 0x68 +#define SENSOR_MAG_I2_ADDRESS 0x0C +/*---------------------------------------------------------------------------*/ +/* Registers */ +#define SELF_TEST_X_GYRO 0x00 /* R/W */ +#define SELF_TEST_Y_GYRO 0x01 /* R/W */ +#define SELF_TEST_Z_GYRO 0x02 /* R/W */ +#define SELF_TEST_X_ACCEL 0x0D /* R/W */ +#define SELF_TEST_Z_ACCEL 0x0E /* R/W */ +#define SELF_TEST_Y_ACCEL 0x0F /* R/W */ +/*---------------------------------------------------------------------------*/ +#define XG_OFFSET_H 0x13 /* R/W */ +#define XG_OFFSET_L 0x14 /* R/W */ +#define YG_OFFSET_H 0x15 /* R/W */ +#define YG_OFFSET_L 0x16 /* R/W */ +#define ZG_OFFSET_H 0x17 /* R/W */ +#define ZG_OFFSET_L 0x18 /* R/W */ +/*---------------------------------------------------------------------------*/ +#define SMPLRT_DIV 0x19 /* R/W */ +#define CONFIG 0x1A /* R/W */ +#define GYRO_CONFIG 0x1B /* R/W */ +#define ACCEL_CONFIG 0x1C /* R/W */ +#define ACCEL_CONFIG_2 0x1D /* R/W */ +#define LP_ACCEL_ODR 0x1E /* R/W */ +#define WOM_THR 0x1F /* R/W */ +#define FIFO_EN 0x23 /* R/W */ +/*---------------------------------------------------------------------------*/ +/* + * Registers 0x24 - 0x36 are not applicable to the SensorTag HW configuration + * (IC2 Master) + */ +#define INT_PIN_CFG 0x37 /* R/W */ +#define INT_ENABLE 0x38 /* R/W */ +#define INT_STATUS 0x3A /* R */ +#define ACCEL_XOUT_H 0x3B /* R */ +#define ACCEL_XOUT_L 0x3C /* R */ +#define ACCEL_YOUT_H 0x3D /* R */ +#define ACCEL_YOUT_L 0x3E /* R */ +#define ACCEL_ZOUT_H 0x3F /* R */ +#define ACCEL_ZOUT_L 0x40 /* R */ +#define TEMP_OUT_H 0x41 /* R */ +#define TEMP_OUT_L 0x42 /* R */ +#define GYRO_XOUT_H 0x43 /* R */ +#define GYRO_XOUT_L 0x44 /* R */ +#define GYRO_YOUT_H 0x45 /* R */ +#define GYRO_YOUT_L 0x46 /* R */ +#define GYRO_ZOUT_H 0x47 /* R */ +#define GYRO_ZOUT_L 0x48 /* R */ +/*---------------------------------------------------------------------------*/ +/* + * Registers 0x49 - 0x60 are not applicable to the SensorTag HW configuration + * (external sensor data) + * + * Registers 0x63 - 0x67 are not applicable to the SensorTag HW configuration + * (I2C master) + */ +#define SIGNAL_PATH_RESET 0x68 /* R/W */ +#define ACCEL_INTEL_CTRL 0x69 /* R/W */ +#define USER_CTRL 0x6A /* R/W */ +#define PWR_MGMT_1 0x6B /* R/W */ +#define PWR_MGMT_2 0x6C /* R/W */ +#define FIFO_COUNT_H 0x72 /* R/W */ +#define FIFO_COUNT_L 0x73 /* R/W */ +#define FIFO_R_W 0x74 /* R/W */ +#define WHO_AM_I 0x75 /* R/W */ +/*---------------------------------------------------------------------------*/ +/* Masks is mpuConfig valiable */ +#define ACC_CONFIG_MASK 0x38 +#define GYRO_CONFIG_MASK 0x07 +/*---------------------------------------------------------------------------*/ +/* Values PWR_MGMT_1 */ +#define MPU_SLEEP 0x4F /* Sleep + stop all clocks */ +#define MPU_WAKE_UP 0x09 /* Disable temp. + intern osc */ +/*---------------------------------------------------------------------------*/ +/* Values PWR_MGMT_2 */ +#define ALL_AXES 0x3F +#define GYRO_AXES 0x07 +#define ACC_AXES 0x38 +/*---------------------------------------------------------------------------*/ +/* Data sizes */ +#define DATA_SIZE 6 +/*---------------------------------------------------------------------------*/ +/* Output data rates */ +#define INV_LPA_0_3125HZ 0 +#define INV_LPA_0_625HZ 1 +#define INV_LPA_1_25HZ 2 +#define INV_LPA_2_5HZ 3 +#define INV_LPA_5HZ 4 +#define INV_LPA_10HZ 5 +#define INV_LPA_20HZ 6 +#define INV_LPA_40HZ 7 +#define INV_LPA_80HZ 8 +#define INV_LPA_160HZ 9 +#define INV_LPA_320HZ 10 +#define INV_LPA_640HZ 11 +#define INV_LPA_STOPPED 255 +/*---------------------------------------------------------------------------*/ +/* Bit values */ +#define BIT_ANY_RD_CLR 0x10 +#define BIT_RAW_RDY_EN 0x01 +#define BIT_WOM_EN 0x40 +#define BIT_LPA_CYCLE 0x20 +#define BIT_STBY_XA 0x20 +#define BIT_STBY_YA 0x10 +#define BIT_STBY_ZA 0x08 +#define BIT_STBY_XG 0x04 +#define BIT_STBY_YG 0x02 +#define BIT_STBY_ZG 0x01 +#define BIT_STBY_XYZA (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA) +#define BIT_STBY_XYZG (BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG) +/*---------------------------------------------------------------------------*/ +/* User control register */ +#define BIT_ACTL 0x80 +#define BIT_LATCH_EN 0x20 +/*---------------------------------------------------------------------------*/ +/* INT Pin / Bypass Enable Configuration */ +#define BIT_AUX_IF_EN 0x20 /* I2C_MST_EN */ +#define BIT_BYPASS_EN 0x02 +/*---------------------------------------------------------------------------*/ +#define ACC_RANGE_INVALID -1 + +#define ACC_RANGE_2G 0 +#define ACC_RANGE_4G 1 +#define ACC_RANGE_8G 2 +#define ACC_RANGE_16G 3 + +#define MPU_AX_GYR_X 2 +#define MPU_AX_GYR_Y 1 +#define MPU_AX_GYR_Z 0 +#define MPU_AX_GYR 0x07 + +#define MPU_AX_ACC_X 5 +#define MPU_AX_ACC_Y 4 +#define MPU_AX_ACC_Z 3 +#define MPU_AX_ACC 0x38 + +#define MPU_AX_MAG 6 +/*---------------------------------------------------------------------------*/ +#define MPU_DATA_READY 0x01 +#define MPU_MOVEMENT 0x40 +/*---------------------------------------------------------------------------*/ +/* Sensor selection/deselection */ +#define SENSOR_SELECT() board_i2c_select(BOARD_I2C_INTERFACE_1, SENSOR_I2C_ADDRESS) +#define SENSOR_DESELECT() board_i2c_deselect() +/*---------------------------------------------------------------------------*/ +/* Delay */ +#define delay_ms(i) (ti_lib_cpu_delay(8000 * (i))) +/*---------------------------------------------------------------------------*/ +static uint8_t mpu_config; +static uint8_t acc_range; +static uint8_t acc_range_reg; +static uint8_t val; +static uint8_t interrupt_status; +/*---------------------------------------------------------------------------*/ +#define SENSOR_STATUS_DISABLED 0 +#define SENSOR_STATUS_BOOTING 1 +#define SENSOR_STATUS_ENABLED 2 + +static int enabled = SENSOR_STATUS_DISABLED; +static int elements; +/*---------------------------------------------------------------------------*/ +/* 3 16-byte words for all sensor readings */ +#define SENSOR_DATA_BUF_SIZE 3 + +static uint16_t sensor_value[SENSOR_DATA_BUF_SIZE]; +/*---------------------------------------------------------------------------*/ +/* + * Wait SENSOR_BOOT_DELAY ticks for the sensor to boot and + * SENSOR_STARTUP_DELAY for readings to be ready + * Gyro is a little slower than Acc + */ +#define SENSOR_BOOT_DELAY 8 +#define SENSOR_STARTUP_DELAY 5 + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +/* Wait for the MPU to have data ready */ +rtimer_clock_t t0; + +/* + * Wait timeout in rtimer ticks. This is just a random low number, since the + * first time we read the sensor status, it should be ready to return data + */ +#define READING_WAIT_TIMEOUT 10 +/*---------------------------------------------------------------------------*/ +/** + * \brief Place the MPU in low power mode + */ +static void +sensor_sleep(void) +{ + SENSOR_SELECT(); + + val = ALL_AXES; + sensor_common_write_reg(PWR_MGMT_2, &val, 1); + + val = MPU_SLEEP; + sensor_common_write_reg(PWR_MGMT_1, &val, 1); + SENSOR_DESELECT(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Exit low power mode + */ +static void +sensor_wakeup(void) +{ + SENSOR_SELECT(); + val = MPU_WAKE_UP; + sensor_common_write_reg(PWR_MGMT_1, &val, 1); + + /* All axis initially disabled */ + val = ALL_AXES; + sensor_common_write_reg(PWR_MGMT_2, &val, 1); + mpu_config = 0; + + /* Restore the range */ + sensor_common_write_reg(ACCEL_CONFIG, &acc_range_reg, 1); + + /* Clear interrupts */ + sensor_common_read_reg(INT_STATUS, &val, 1); + SENSOR_DESELECT(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Select gyro and accelerometer axes + */ +static void +select_axes(void) +{ + val = ~mpu_config; + sensor_common_write_reg(PWR_MGMT_2, &val, 1); +} +/*---------------------------------------------------------------------------*/ +static void +convert_to_le(uint8_t *data, uint8_t len) +{ + int i; + for(i = 0; i < len; i += 2) { + uint8_t tmp; + tmp = data[i]; + data[i] = data[i + 1]; + data[i + 1] = tmp; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the range of the accelerometer + * \param new_range: ACC_RANGE_2G, ACC_RANGE_4G, ACC_RANGE_8G, ACC_RANGE_16G + * \return true if the write to the sensor succeeded + */ +static bool +acc_set_range(uint8_t new_range) +{ + bool success; + + if(new_range == acc_range) { + return true; + } + + success = false; + + acc_range_reg = (new_range << 3); + + /* Apply the range */ + SENSOR_SELECT(); + success = sensor_common_write_reg(ACCEL_CONFIG, &acc_range_reg, 1); + SENSOR_DESELECT(); + + if(success) { + acc_range = new_range; + } + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the MPU + * \return True if success + */ +static bool +init_sensor(void) +{ + bool ret; + + interrupt_status = false; + acc_range = ACC_RANGE_INVALID; + mpu_config = 0; /* All axes off */ + + /* Device reset */ + val = 0x80; + SENSOR_SELECT(); + ret = sensor_common_write_reg(PWR_MGMT_1, &val, 1); + SENSOR_DESELECT(); + + if(ret) { + delay_ms(200); + + /* Initial configuration */ + acc_set_range(ACC_RANGE_8G); + /* Power save */ + sensor_sleep(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Check whether a data or wake on motion interrupt has occurred + * \return Return the interrupt status + * + * This driver does not use interrupts, however this function allows us to + * determine whether a new sensor reading is available + */ +static uint8_t +int_status(void) +{ + SENSOR_SELECT(); + sensor_common_read_reg(INT_STATUS, &interrupt_status, 1); + SENSOR_DESELECT(); + + return interrupt_status; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Enable the MPU + * \param axes: Gyro bitmap [0..2], X = 1, Y = 2, Z = 4. 0 = gyro off + * Acc bitmap [3..5], X = 8, Y = 16, Z = 32. 0 = accelerometer off + */ +static void +enable_sensor(uint16_t axes) +{ + if(mpu_config == 0 && axes != 0) { + /* Wake up the sensor if it was off */ + sensor_wakeup(); + } + + mpu_config = axes; + + if(mpu_config != 0) { + /* Enable gyro + accelerometer readout */ + select_axes(); + delay_ms(10); + } else if(mpu_config == 0) { + sensor_sleep(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read data from the accelerometer - X, Y, Z - 3 words + * \return True if a valid reading could be taken, false otherwise + */ +static bool +acc_read(uint16_t *data) +{ + bool success; + + if(interrupt_status & BIT_RAW_RDY_EN) { + /* Burst read of all accelerometer values */ + SENSOR_SELECT(); + success = sensor_common_read_reg(ACCEL_XOUT_H, (uint8_t *)data, DATA_SIZE); + SENSOR_DESELECT(); + + if(success) { + convert_to_le((uint8_t *)data, DATA_SIZE); + } else { + sensor_common_set_error_data((uint8_t *)data, DATA_SIZE); + } + } else { + /* Data not ready */ + success = false; + } + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read data from the gyroscope - X, Y, Z - 3 words + * \return True if a valid reading could be taken, false otherwise + */ +static bool +gyro_read(uint16_t *data) +{ + bool success; + + if(interrupt_status & BIT_RAW_RDY_EN) { + /* Select this sensor */ + SENSOR_SELECT(); + + /* Burst read of all gyroscope values */ + success = sensor_common_read_reg(GYRO_XOUT_H, (uint8_t *)data, DATA_SIZE); + + SENSOR_DESELECT(); + + if(success) { + convert_to_le((uint8_t *)data, DATA_SIZE); + } else { + sensor_common_set_error_data((uint8_t *)data, DATA_SIZE); + } + } else { + success = false; + } + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert accelerometer raw reading to a value in G + * \param raw_data The raw accelerometer reading + * \return The converted value + */ +static float +acc_convert(int16_t raw_data) +{ + float v = 0; + + switch(acc_range) { + case ACC_RANGE_2G: + /* Calculate acceleration, unit G, range -2, +2 */ + v = (raw_data * 1.0) / (32768 / 2); + break; + case ACC_RANGE_4G: + /* Calculate acceleration, unit G, range -4, +4 */ + v = (raw_data * 1.0) / (32768 / 4); + break; + case ACC_RANGE_8G: + /* Calculate acceleration, unit G, range -8, +8 */ + v = (raw_data * 1.0) / (32768 / 8); + break; + case ACC_RANGE_16G: + /* Calculate acceleration, unit G, range -16, +16 */ + v = (raw_data * 1.0) / (32768 / 16); + break; + default: + v = 0; + break; + } + + return v; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert gyro raw reading to a value in deg/sec + * \param raw_data The raw accelerometer reading + * \return The converted value + */ +static float +gyro_convert(int16_t raw_data) +{ + /* calculate rotation, unit deg/s, range -250, +250 */ + return (raw_data * 1.0) / (65536 / 500); +} +/*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + enabled = SENSOR_STATUS_ENABLED; + sensors_changed(&mpu_9250_sensor); +} +/*---------------------------------------------------------------------------*/ +static void +initialise(void *not_used) +{ + init_sensor(); + + /* Configure the accelerometer range */ + if((elements & MPU_9250_SENSOR_TYPE_ACC) != 0) { + acc_set_range(MPU_9250_SENSOR_ACC_RANGE); + } + + enable_sensor(elements & MPU_9250_SENSOR_TYPE_ALL); + + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +power_up(void) +{ + ti_lib_gpio_pin_write(BOARD_MPU_POWER, 1); + enabled = SENSOR_STATUS_BOOTING; + + ctimer_set(&startup_timer, SENSOR_BOOT_DELAY, initialise, NULL); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type MPU_9250_SENSOR_TYPE_ACC_[XYZ] or MPU_9250_SENSOR_TYPE_GYRO_[XYZ] + * \return centi-G (ACC) or centi-Deg/Sec (Gyro) + */ +static int +value(int type) +{ + int rv; + float converted_val = 0; + + if(enabled == SENSOR_STATUS_DISABLED) { + PRINTF("MPU: Sensor Disabled\n"); + return CC26XX_SENSOR_READING_ERROR; + } + + memset(sensor_value, 0, sizeof(sensor_value)); + + if((type & MPU_9250_SENSOR_TYPE_ACC) != 0) { + t0 = RTIMER_NOW(); + + while(!int_status() && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + READING_WAIT_TIMEOUT))); + + rv = acc_read(sensor_value); + + if(rv == 0) { + return CC26XX_SENSOR_READING_ERROR; + } + + PRINTF("MPU: ACC = 0x%04x 0x%04x 0x%04x = ", + sensor_value[0], sensor_value[1], sensor_value[2]); + + /* Convert */ + if(type == MPU_9250_SENSOR_TYPE_ACC_X) { + converted_val = acc_convert(sensor_value[0]); + } else if(type == MPU_9250_SENSOR_TYPE_ACC_Y) { + converted_val = acc_convert(sensor_value[1]); + } else if(type == MPU_9250_SENSOR_TYPE_ACC_Z) { + converted_val = acc_convert(sensor_value[2]); + } + rv = (int)(converted_val * 100); + } else if((type & MPU_9250_SENSOR_TYPE_GYRO) != 0) { + t0 = RTIMER_NOW(); + + while(!int_status() && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + READING_WAIT_TIMEOUT))); + + rv = gyro_read(sensor_value); + + if(rv == 0) { + return CC26XX_SENSOR_READING_ERROR; + } + + PRINTF("MPU: Gyro = 0x%04x 0x%04x 0x%04x = ", + sensor_value[0], sensor_value[1], sensor_value[2]); + + if(type == MPU_9250_SENSOR_TYPE_GYRO_X) { + converted_val = gyro_convert(sensor_value[0]); + } else if(type == MPU_9250_SENSOR_TYPE_GYRO_Y) { + converted_val = gyro_convert(sensor_value[1]); + } else if(type == MPU_9250_SENSOR_TYPE_GYRO_Z) { + converted_val = gyro_convert(sensor_value[2]); + } + rv = (int)(converted_val * 100); + } else { + PRINTF("MPU: Invalid type\n"); + rv = CC26XX_SENSOR_READING_ERROR; + } + + PRINTF("%ld\n", (long int)(converted_val * 100)); + + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the MPU9250 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + elements = MPU_9250_SENSOR_TYPE_NONE; + break; + case SENSORS_ACTIVE: + if((enable & MPU_9250_SENSOR_TYPE_ACC) != 0 || + (enable & MPU_9250_SENSOR_TYPE_GYRO) != 0) { + PRINTF("MPU: Enabling\n"); + elements = enable & MPU_9250_SENSOR_TYPE_ALL; + + power_up(); + + enabled = SENSOR_STATUS_BOOTING; + } else { + PRINTF("MPU: Disabling\n"); + ctimer_stop(&startup_timer); + elements = MPU_9250_SENSOR_TYPE_NONE; + enable_sensor(0); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + enabled = SENSOR_STATUS_DISABLED; + } + break; + case MPU_9250_SENSOR_SHUTDOWN: + ti_lib_gpio_pin_write(BOARD_MPU_POWER, 0); + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the sensor is enabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(mpu_9250_sensor, "MPU9250", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h new file mode 100644 index 000000000..46836a538 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h @@ -0,0 +1,112 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-mpu SensorTag 2.0 Motion Processing Unit + * + * Driver for the Invensense MPU9250 Motion Processing Unit. + * + * Due to the time required between triggering a reading and the reading + * becoming available, this driver is meant to be used in an asynchronous + * fashion. The caller must first activate the sensor by calling + * mpu_9250_sensor.configure(SENSORS_ACTIVE, xyz); + * The value for the xyz arguments depends on the required readings. If the + * caller intends to read both the accelerometer as well as the gyro then + * xyz should be MPU_9250_SENSOR_TYPE_ALL. If the caller only needs to take a + * reading from one of the two elements, xyz should be one of + * MPU_9250_SENSOR_TYPE_ACC or MPU_9250_SENSOR_TYPE_GYRO + * + * Calling .configure() will power up the sensor and initialise it. When the + * sensor is ready to provide readings, the driver will generate a + * sensors_changed event. + * + * Calls to .status() will return the driver's state which could indicate that + * the sensor is off, booting or on. + * + * Once a reading has been taken, the caller has two options: + * - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take + * subsequent readings the sensor must be started up all over + * - Leave the sensor on. In this scenario, the caller can simply keep calling + * value() for subsequent readings, but having the sensor on will consume + * more energy, especially if both accelerometer and the gyro are on. + * @{ + * + * \file + * Header file for the Sensortag-CC26XX Invensense MPU9250 motion processing unit + */ +/*---------------------------------------------------------------------------*/ +#ifndef MPU_9250_SENSOR_H_ +#define MPU_9250_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +/* ACC / Gyro Axes */ +#define MPU_9250_SENSOR_TYPE_GYRO_Z 0x01 +#define MPU_9250_SENSOR_TYPE_GYRO_Y 0x02 +#define MPU_9250_SENSOR_TYPE_GYRO_X 0x04 +#define MPU_9250_SENSOR_TYPE_GYRO_ALL 0x07 + +#define MPU_9250_SENSOR_TYPE_ACC_Z 0x08 +#define MPU_9250_SENSOR_TYPE_ACC_Y 0x10 +#define MPU_9250_SENSOR_TYPE_ACC_X 0x20 +#define MPU_9250_SENSOR_TYPE_ACC_ALL 0x38 + +#define MPU_9250_SENSOR_TYPE_MASK 0x3F +#define MPU_9250_SENSOR_TYPE_ACC 0x38 +#define MPU_9250_SENSOR_TYPE_GYRO 0x07 + +#define MPU_9250_SENSOR_TYPE_NONE 0 +#define MPU_9250_SENSOR_TYPE_ALL (MPU_9250_SENSOR_TYPE_ACC | \ + MPU_9250_SENSOR_TYPE_GYRO) + +#define MPU_9250_SENSOR_SHUTDOWN 0xFF +/*---------------------------------------------------------------------------*/ +/* Accelerometer range */ +#define MPU_9250_SENSOR_ACC_RANGE_2G 0 +#define MPU_9250_SENSOR_ACC_RANGE_4G 1 +#define MPU_9250_SENSOR_ACC_RANGE_8G 2 +#define MPU_9250_SENSOR_ACC_RANGE_16G 3 +/*---------------------------------------------------------------------------*/ +/* Accelerometer range configuration */ +#ifdef MPU_9250_SENSOR_CONF_ACC_RANGE +#define MPU_9250_SENSOR_ACC_RANGE MPU_9250_SENSOR_CONF_ACC_RANGE +#else +#define MPU_9250_SENSOR_ACC_RANGE MPU_9250_SENSOR_ACC_RANGE_2G +#endif +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor mpu_9250_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* MPU_9250_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c new file mode 100644 index 000000000..7cb41bf6d --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c @@ -0,0 +1,273 @@ +/* + * 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 sensortag-cc26xx-opt-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26xx Opt3001 light sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "opt-3001-sensor.h" +#include "sys/ctimer.h" +#include "ti-lib.h" +#include "board-i2c.h" +#include "sensor-common.h" + +#include +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Slave address */ +#define OPT3001_I2C_ADDRESS 0x45 +/*---------------------------------------------------------------------------*/ +/* Register addresses */ +#define REG_RESULT 0x00 +#define REG_CONFIGURATION 0x01 +#define REG_LOW_LIMIT 0x02 +#define REG_HIGH_LIMIT 0x03 + +#define REG_MANUFACTURER_ID 0x7E +#define REG_DEVICE_ID 0x7F +/*---------------------------------------------------------------------------*/ +/* Register values */ +#define MANUFACTURER_ID 0x5449 /* TI */ +#define DEVICE_ID 0x3001 /* Opt 3001 */ +#define CONFIG_RESET 0xC810 +#define CONFIG_TEST 0xCC10 +#define CONFIG_ENABLE 0x10CC /* 0xCC10 */ +#define CONFIG_DISABLE 0x108C /* 0xC810 */ +/*---------------------------------------------------------------------------*/ +/* Bit values */ +#define DATA_RDY_BIT 0x0080 /* Data ready */ +/*---------------------------------------------------------------------------*/ +/* Register length */ +#define REGISTER_LENGTH 2 +/*---------------------------------------------------------------------------*/ +/* Sensor data size */ +#define DATA_LENGTH 2 +/*---------------------------------------------------------------------------*/ +#define SENSOR_STATUS_DISABLED 0 +#define SENSOR_STATUS_NOT_READY 1 +#define SENSOR_STATUS_ENABLED 2 + +static int enabled = SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/* Wait SENSOR_STARTUP_DELAY for the sensor to be ready - 125ms */ +#define SENSOR_STARTUP_DELAY (CLOCK_SECOND >> 3) + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + enabled = SENSOR_STATUS_ENABLED; + sensors_changed(&opt_3001_sensor); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Select the sensor on the I2C bus + */ +static void +select(void) +{ + /* Select slave and set clock rate */ + board_i2c_select(BOARD_I2C_INTERFACE_0, OPT3001_I2C_ADDRESS); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Turn the sensor on/off + * \param enable TRUE: on, FALSE: off + */ +static void +enable_sensor(bool enable) +{ + uint16_t val; + + select(); + + if(enable) { + val = CONFIG_ENABLE; + } else { + val = CONFIG_DISABLE; + } + + sensor_common_write_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read the result register + * \param raw_data Pointer to a buffer to store the reading + * \return TRUE if valid data + */ +static bool +read_data(uint16_t *raw_data) +{ + bool success; + uint16_t val; + + select(); + + success = sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val, + REGISTER_LENGTH); + + if(success) { + success = (val & DATA_RDY_BIT) == DATA_RDY_BIT; + } + + if(success) { + success = sensor_common_read_reg(REG_RESULT, (uint8_t *)&val, DATA_LENGTH); + } + + if(success) { + /* Swap bytes */ + *raw_data = (val << 8) | (val >> 8 & 0xFF); + } else { + sensor_common_set_error_data((uint8_t *)raw_data, DATA_LENGTH); + } + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert raw data to a value in lux + * \param data Pointer to a buffer with a raw sensor reading + * \return Converted value (lux) + */ +static float +convert(uint16_t raw_data) +{ + uint16_t e, m; + + m = raw_data & 0x0FFF; + e = (raw_data & 0xF000) >> 12; + + return m * (0.01 * exp2(e)); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type Ignored + * \return Illuminance in centilux + */ +static int +value(int type) +{ + int rv; + uint16_t raw_val; + float converted_val; + + if(enabled != SENSOR_STATUS_ENABLED) { + PRINTF("Sensor disabled or starting up (%d)\n", enabled); + return CC26XX_SENSOR_READING_ERROR; + } + + rv = read_data(&raw_val); + + if(rv == 0) { + return CC26XX_SENSOR_READING_ERROR; + } + + converted_val = convert(raw_val); + PRINTF("OPT: %04X r=%d (centilux)\n", raw_val, + (int)(converted_val * 100)); + + rv = (int)(converted_val * 100); + + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the OPT3001 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + break; + case SENSORS_ACTIVE: + if(enable) { + enable_sensor(1); + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); + enabled = SENSOR_STATUS_NOT_READY; + } else { + ctimer_stop(&startup_timer); + enable_sensor(0); + enabled = SENSOR_STATUS_DISABLED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the sensor is enabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(opt_3001_sensor, "OPT3001", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h new file mode 100644 index 000000000..205ab00ff --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h @@ -0,0 +1,67 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-opt-sensor SensorTag 2.0 Light Sensor + * + * Due to the time required for the sensor to startup, this driver is meant to + * be used in an asynchronous fashion. The caller must first activate the + * sensor by calling SENSORS_ACTIVATE(). This will trigger the sensor's startup + * sequence, but the call will not wait for it to complete so that the CPU can + * perform other tasks or drop to a low power mode. + * + * Once the sensor is stable, the driver will generate a sensors_changed event. + * + * Once a reading has been taken, the caller has two options: + * - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take + * subsequent readings SENSORS_ACTIVATE must be called again + * - Leave the sensor on. In this scenario, the caller can simply keep calling + * value() for subsequent readings, but having the sensor on will consume + * energy + * @{ + * + * \file + * Header file for the Sensortag-CC26xx Opt3001 light sensor + */ +/*---------------------------------------------------------------------------*/ +#ifndef OPT_3001_SENSOR_H_ +#define OPT_3001_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor opt_3001_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* OPT_3001_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/reed-relay.c b/platform/srf06-cc26xx/sensortag/reed-relay.c new file mode 100644 index 000000000..b5956f6f8 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/reed-relay.c @@ -0,0 +1,140 @@ +/* + * 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 sensortag-cc26xx-reed-relay + * @{ + * + * \file + * Driver for the Sensortag-CC26XX Reed Relay + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/clock.h" +#include "sys/timer.h" +#include "lib/sensors.h" +#include "sensortag/reed-relay.h" +#include "gpio-interrupt.h" +#include "sys/timer.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +static struct timer debouncetimer; +/*---------------------------------------------------------------------------*/ +#define REED_ISR_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ + IOC_IOPULL_DOWN | IOC_SLEW_DISABLE | \ + IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ + IOC_INT_DISABLE | IOC_IOMODE_NORMAL | \ + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ + IOC_JTAG_DISABLE) +/*---------------------------------------------------------------------------*/ +/** + * \brief Handler for Sensortag-CC26XX reed interrupts + */ +static void +reed_interrupt_handler(uint8_t ioid) +{ + if(!timer_expired(&debouncetimer)) { + ENERGEST_OFF(ENERGEST_TYPE_IRQ); + return; + } + + sensors_changed(&reed_relay_sensor); + timer_set(&debouncetimer, CLOCK_SECOND / 2); +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + return (int)ti_lib_gpio_pin_read(1 << BOARD_IOID_REED_RELAY); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the button sensor for all buttons. + * + * \param type SENSORS_HW_INIT: Initialise. SENSORS_ACTIVE: Enables/Disables + * depending on 'value' + * \param value 0: disable, non-zero: enable + * \return Always returns 1 + */ +static int +configure(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_ioc_int_disable(BOARD_IOID_REED_RELAY); + ti_lib_gpio_event_clear(1 << BOARD_IOID_REED_RELAY); + + /* Enabled the GPIO clock when the CM3 is running */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); + ti_lib_ioc_port_configure_set(BOARD_IOID_REED_RELAY, IOC_PORT_GPIO, + REED_ISR_CFG); + + gpio_interrupt_register_handler(BOARD_IOID_REED_RELAY, + reed_interrupt_handler); + break; + case SENSORS_ACTIVE: + if(value) { + ti_lib_ioc_int_enable(BOARD_IOID_REED_RELAY); + } else { + ti_lib_ioc_int_disable(BOARD_IOID_REED_RELAY); + } + break; + default: + break; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the reed + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 Interrupt enabled, 0: Disabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return (ti_lib_ioc_port_configure_get(BOARD_IOID_REED_RELAY) + & IOC_INT_ENABLE) == IOC_INT_ENABLE; + break; + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(reed_relay_sensor, "REED", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/reed-relay.h b/platform/srf06-cc26xx/sensortag/reed-relay.h new file mode 100644 index 000000000..3ec712719 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/reed-relay.h @@ -0,0 +1,59 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-reed-relay SensorTag 2.0 Reed Relay + * + * The reed relay acts like a button without a button. To trigger the reed, + * approach a magnet to the sensortag and a sensors_changed event will be + * generated, in a fashion similar to as if a button had been pressed + * + * @{ + * + * \file + * Header file for the Sensortag-CC26XX Reed Relay + */ +/*---------------------------------------------------------------------------*/ +#ifndef REED_RELAY_H +#define REED_RELAY_H +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor reed_relay_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* REED_RELAY_H */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/sensor-common.c b/platform/srf06-cc26xx/sensortag/sensor-common.c new file mode 100644 index 000000000..0c09bf630 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/sensor-common.c @@ -0,0 +1,79 @@ +/* + * 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 sensortag-cc26xx-sensor-common + * @{ + * + * \file + * Utilities common among SensorTag sensors + */ +/*---------------------------------------------------------------------------*/ +#include "sensor-common.h" +#include "board-i2c.h" +/*---------------------------------------------------------------------------*/ +/* Data to use when an error occurs */ +#define ERROR_DATA 0xCC +/*---------------------------------------------------------------------------*/ +static uint8_t buffer[32]; +/*---------------------------------------------------------------------------*/ +bool +sensor_common_read_reg(uint8_t addr, uint8_t *buf, uint8_t len) +{ + return board_i2c_write_read(&addr, 1, buf, len); +} +/*---------------------------------------------------------------------------*/ +bool +sensor_common_write_reg(uint8_t addr, uint8_t *buf, uint8_t len) +{ + uint8_t i; + uint8_t *p = buffer; + + /* Copy address and data to local buffer for burst write */ + *p++ = addr; + for(i = 0; i < len; i++) { + *p++ = *buf++; + } + len++; + + /* Send data */ + return board_i2c_write(buffer, len); +} +/*---------------------------------------------------------------------------*/ +void +sensor_common_set_error_data(uint8_t *buf, uint8_t len) +{ + while(len > 0) { + len--; + buf[len] = ERROR_DATA; + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sensor-common.h b/platform/srf06-cc26xx/sensortag/sensor-common.h new file mode 100644 index 000000000..977650d5e --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/sensor-common.h @@ -0,0 +1,85 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-sensor-common SensorTag 2.0 Sensors + * @{ + * + * \file + * Header file for the Sensortag-CC26xx Common sensor utilities + */ +/*---------------------------------------------------------------------------*/ +#ifndef SENSOR_H +#define SENSOR_H +/*---------------------------------------------------------------------------*/ +#include "board-i2c.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Reads a sensor's register over I2C + * \param addr The address of the register to read + * \param buf Pointer to buffer to place data + * \param len Number of bytes to read + * \return TRUE if the required number of bytes are received + * + * The sensor must be selected before this routine is called. + */ +bool sensor_common_read_reg(uint8_t addr, uint8_t *buf, uint8_t len); + +/** + * \brief Write to a sensor's register over I2C + * \param addr The address of the register to read + * \param buf Pointer to buffer containing data to be written + * \param len Number of bytes to write + * \return TRUE if successful write + * + * The sensor must be selected before this routine is called. + */ +bool sensor_common_write_reg(uint8_t addr, uint8_t *buf, uint8_t len); + +/** + * \brief Fill a result buffer with dummy error data + * \param buf Pointer to the buffer where to write the data + * \param len Number of bytes to fill + * \return bitmask of error flags + */ +void sensor_common_set_error_data(uint8_t *buf, uint8_t len); +/*---------------------------------------------------------------------------*/ +#endif /* SENSOR_H */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/sensortag-sensors.c b/platform/srf06-cc26xx/sensortag/sensortag-sensors.c new file mode 100644 index 000000000..a8f26aefe --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/sensortag-sensors.c @@ -0,0 +1,55 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \file + * Generic module controlling sensors on CC26XX Sensortag + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sensortag/button-sensor.h" +#include "sensortag/bmp-280-sensor.h" +#include "sensortag/tmp-007-sensor.h" +#include "sensortag/opt-3001-sensor.h" +#include "sensortag/sht-21-sensor.h" +#include "sensortag/mpu-9250-sensor.h" +#include "sensortag/reed-relay.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \brief Exports a global symbol to be used by the sensor API */ +SENSORS(&button_left_sensor, &button_right_sensor, + &bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &sht_21_sensor, + &mpu_9250_sensor, &reed_relay_sensor); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sht-21-sensor.c b/platform/srf06-cc26xx/sensortag/sht-21-sensor.c new file mode 100644 index 000000000..f90e12f55 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/sht-21-sensor.c @@ -0,0 +1,386 @@ +/* + * 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 sensortag-cc26xx-sht-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26xx Sensirion SHT21 Humidity sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "sys/ctimer.h" +#include "lib/sensors.h" +#include "sht-21-sensor.h" +#include "sensor-common.h" +#include "board-i2c.h" + +#include "ti-lib.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Sensor I2C address */ +#define HAL_SHT21_I2C_ADDRESS 0x40 +/*---------------------------------------------------------------------------*/ +#define S_REG_LEN 2 +#define DATA_LEN 3 +/*---------------------------------------------------------------------------*/ +/* Internal commands */ +#define SHT21_CMD_TEMP_T_NH 0xF3 /* command trig. temp meas. no hold master */ +#define SHT21_CMD_HUMI_T_NH 0xF5 /* command trig. humidity meas. no hold master */ +#define SHT21_CMD_WRITE_U_R 0xE6 /* command write user register */ +#define SHT21_CMD_READ_U_R 0xE7 /* command read user register */ +#define SHT21_CMD_SOFT_RST 0xFE /* command soft reset */ +/*---------------------------------------------------------------------------*/ +#define HUMIDITY 0x00 +#define TEMPERATURE 0x01 +/*---------------------------------------------------------------------------*/ +#define USR_REG_MASK 0x38 /* Mask off reserved bits (3,4,5) */ +#define USR_REG_DEFAULT 0x02 /* Disable OTP reload */ +#define USR_REG_RES_MASK 0x7E /* Only change bits 0 and 7 (meas. res.) */ +#define USR_REG_11BITRES 0x81 /* 11-bit resolution */ +/*---------------------------------------------------------------------------*/ +#define USR_REG_TEST_VAL 0x83 +/*---------------------------------------------------------------------------*/ +#define DATA_SIZE 6 +/*---------------------------------------------------------------------------*/ +static uint8_t usr; /* User register value */ +static uint8_t buf[DATA_SIZE]; /* Data buffer */ +static bool success; +/*---------------------------------------------------------------------------*/ +static int enabled = SHT_21_SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/* + * Maximum measurement durations in clock ticks. We use 11bit resolution, thus: + * - Tmp: 11ms + * - RH: 15ms + */ +#define MEASUREMENT_DURATION 3 + +/* + * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a + * reading + */ +#define SENSOR_STARTUP_DELAY 4 + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +/** + * \brief Select the SHT sensor on the I2C-bus + */ +static void +select(void) +{ + /* Select the SHT21 address */ + board_i2c_select(BOARD_I2C_INTERFACE_0, HAL_SHT21_I2C_ADDRESS); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Write a command over I2C + * \param cmd The command to send + * \return TRUE if the command was sent successfully + */ +static bool +write_cmd(uint8_t cmd) +{ + /* Send command */ + return board_i2c_write_single(cmd); +} +/*---------------------------------------------------------------------------*/ +/* + * \brief Read data from the SHT over I2C + * \param buf Pointer to buffer where data will be stored + * \param len Number of bytes to read + * \return TRUE if the required number of bytes were received + */ +static bool +read_data(uint8_t *buf, uint8_t len) +{ + /* Read data */ + return board_i2c_read(buf, len); +} +/*---------------------------------------------------------------------------*/ +/** + * @brief Initialise the SHT21 sensor + */ +static void +sensor_init(void) +{ + select(); + + /* Set 11 bit resolution */ + sensor_common_read_reg(SHT21_CMD_READ_U_R, &usr, 1); + usr &= USR_REG_RES_MASK; + usr |= USR_REG_11BITRES; + sensor_common_write_reg(SHT21_CMD_WRITE_U_R, &usr, 1); + success = true; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Start a temperature measurement + */ +static void +start_temp(void) +{ + if(success) { + select(); + success = write_cmd(SHT21_CMD_TEMP_T_NH); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Latch the last temperature measurement + */ +static void +latch_temp(void) +{ + if(success) { + select(); + success = read_data(buf, DATA_LEN); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Start a humidity measurement + */ +static void +start_humidity(void) +{ + if(success) { + select(); + success = write_cmd(SHT21_CMD_HUMI_T_NH); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Latch the last humidity measurement + */ +static void +latch_humidity(void) +{ + if(success) { + select(); + success = read_data(buf + DATA_LEN, DATA_LEN); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Retrieve latched raw readings from buffer and store in variables + * \param raw_temp Pointer to a buffer where the temperature reading will be + * stored + * \param raw_hum Pointer to a buffer where the humidity reading will be + * stored + * \return TRUE on success + */ +static bool +get_readings(uint16_t *raw_temp, uint16_t *raw_hum) +{ + bool valid; + + valid = success; + if(!success) { + sensor_common_set_error_data(buf, DATA_SIZE); + } + + /* Store temperature */ + *raw_temp = buf[0] << 8 | buf[1]; + + /* [2] We ignore the CRC */ + + /* Store humidity */ + *raw_hum = buf[3] << 8 | buf[4]; + + /* [5] We ignore the CRC */ + + success = true; + + return valid; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert raw data to temperature (degrees C) and rel. humidity (%RH) + * \param raw_temp Raw temperature data (little endian) + * \param raw_hum Raw humidity data (little endian) + * \param temp Converted temperature value + * \param hum Converted humidity value + */ +static void +convert(uint16_t raw_temp, uint16_t raw_hum, float *temp, float *hum) +{ + /* Convert temperature to degrees C */ + raw_temp &= ~0x0003; /* clear bits [1..0] (status bits) */ + *temp = -46.85 + 175.72 / 65536 * (double)(int16_t)raw_temp; + + /* Convert relative humidity to a %RH value */ + raw_hum &= ~0x0003; /* clear bits [1..0] (status bits) */ + + /* RH= -6 + 125 * SRH / 2^16 */ + *hum = -6.0 + 125.0 / 65536 * (double)raw_hum; +} +/*---------------------------------------------------------------------------*/ +static void +state_machine(void *not_used) +{ + switch(enabled) { + case SHT_21_SENSOR_STATUS_INITIALISED: + start_temp(); + enabled = SHT_21_SENSOR_STATUS_READING_TEMP; + break; + case SHT_21_SENSOR_STATUS_READING_TEMP: + latch_temp(); + start_humidity(); + enabled = SHT_21_SENSOR_STATUS_READING_HUMIDITY; + break; + case SHT_21_SENSOR_STATUS_READING_HUMIDITY: + latch_humidity(); + enabled = SHT_21_SENSOR_STATUS_READINGS_READY; + sensors_changed(&sht_21_sensor); + return; + case SHT_21_SENSOR_STATUS_READINGS_READY: + case SHT_21_SENSOR_STATUS_DISABLED: + default: + ctimer_stop(&startup_timer); + return; + } + + ctimer_set(&startup_timer, MEASUREMENT_DURATION, state_machine, NULL); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type SHT_21_SENSOR_TYPE_TEMP or SHT_21_SENSOR_TYPE_HUMIDITY + * \return Temperature (centi degrees C) or Humidity (centi %RH) + */ +static int +value(int type) +{ + int rv; + uint16_t raw_temp; + uint16_t raw_hum; + float temp; + float hum; + + if(enabled != SHT_21_SENSOR_STATUS_READINGS_READY) { + PRINTF("Sensor disabled or starting up (%d)\n", enabled); + return CC26XX_SENSOR_READING_ERROR; + } + + if((type != SHT_21_SENSOR_TYPE_TEMP) && type != SHT_21_SENSOR_TYPE_HUMIDITY) { + PRINTF("Invalid type\n"); + return CC26XX_SENSOR_READING_ERROR; + } else { + rv = get_readings(&raw_temp, &raw_hum); + + if(rv == 0) { + return CC26XX_SENSOR_READING_ERROR; + } + + convert(raw_temp, raw_hum, &temp, &hum); + PRINTF("SHT: %04X %04X t=%d h=%d\n", raw_temp, raw_hum, + (int)(temp * 100), (int)(hum * 100)); + + if(type == SHT_21_SENSOR_TYPE_TEMP) { + rv = (int)(temp * 100); + } else if(type == SHT_21_SENSOR_TYPE_HUMIDITY) { + rv = (int)(hum * 100); + } + } + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the SHT21 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + sensor_init(); + enabled = SHT_21_SENSOR_STATUS_INITIALISED; + break; + case SENSORS_ACTIVE: + /* Must be initialised first */ + if(enabled == SHT_21_SENSOR_STATUS_DISABLED) { + return SHT_21_SENSOR_STATUS_DISABLED; + } + if(enable) { + enabled = SHT_21_SENSOR_STATUS_INITIALISED; + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, state_machine, NULL); + } else { + ctimer_stop(&startup_timer); + enabled = SHT_21_SENSOR_STATUS_INITIALISED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return One of the SENSOR_STATUS_xyz defines + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SHT_21_SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(sht_21_sensor, "SHT21", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sht-21-sensor.h b/platform/srf06-cc26xx/sensortag/sht-21-sensor.h new file mode 100644 index 000000000..af2f5d401 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/sht-21-sensor.h @@ -0,0 +1,85 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-sht-sensor SensorTag 2.0 Humidity Sensor + * + * Due to the time required between triggering a reading and the reading + * becoming available, this driver is meant to be used in an asynchronous + * fashion. The caller must first activate the sensor by calling + * SENSORS_ACTIVATE(). This will trigger a cycle which will read both + * temperature and humidity, but the call will not wait for the cycle to + * complete so that the CPU can perform other tasks or drop to a low power + * mode. + * + * Once readings are available, the driver will generate a sensors_changed + * event. + * + * Calls to .status() will return the driver's state which could indicate that + * a measurement is in progress (different return values for each) or that + * readings are ready. + * + * Multiple calls to value() will simply return the reading that was latched + * after the last cycle. In order to obtain fresh readings, a new cycle must be + * started by a new call to SENSORS_ACTIVATE. + * @{ + * + * \file + * Header file for the Sensortag-CC26ss Sensirion SHT21 Humidity sensor + */ +/*---------------------------------------------------------------------------*/ +#ifndef SHT_21_SENSOR_H_ +#define SHT_21_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#define SHT_21_SENSOR_TYPE_TEMP 1 +#define SHT_21_SENSOR_TYPE_HUMIDITY 2 +/*---------------------------------------------------------------------------*/ +/** + * \name SHT21 driver states + * @{ + */ +#define SHT_21_SENSOR_STATUS_DISABLED 0 /**< Not initialised */ +#define SHT_21_SENSOR_STATUS_INITIALISED 1 /**< Initialised but idle */ +#define SHT_21_SENSOR_STATUS_READING_TEMP 2 /**< Temp reading in progress */ +#define SHT_21_SENSOR_STATUS_READING_HUMIDITY 3 /**< Humidity reading in progress */ +#define SHT_21_SENSOR_STATUS_READINGS_READY 4 /**< Both readings ready */ +/** @} */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor sht_21_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* SHT_21_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c b/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c new file mode 100644 index 000000000..8f880cb54 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c @@ -0,0 +1,315 @@ +/* + * 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 sensortag-cc26xx-tmp-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26xx TI TMP007 infrared thermophile sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "tmp-007-sensor.h" +#include "sys/ctimer.h" +#include "board-i2c.h" +#include "sensor-common.h" +#include "ti-lib.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Slave address */ +#define SENSOR_I2C_ADDRESS 0x44 +/*---------------------------------------------------------------------------*/ +/* TMP007 register addresses */ +#define TMP007_REG_ADDR_VOLTAGE 0x00 +#define TMP007_REG_ADDR_LOCAL_TEMP 0x01 +#define TMP007_REG_ADDR_CONFIG 0x02 +#define TMP007_REG_ADDR_OBJ_TEMP 0x03 +#define TMP007_REG_ADDR_STATUS 0x04 +#define TMP007_REG_PROD_ID 0x1F +/*---------------------------------------------------------------------------*/ +/* TMP007 register values */ +#define TMP007_VAL_CONFIG_ON 0x1000 /* Sensor on state */ +#define TMP007_VAL_CONFIG_OFF 0x0000 /* Sensor off state */ +#define TMP007_VAL_CONFIG_RESET 0x8000 +#define TMP007_VAL_PROD_ID 0x0078 /* Product ID */ +/*---------------------------------------------------------------------------*/ +/* Conversion ready (status register) bit values */ +#define CONV_RDY_BIT 0x4000 +/*---------------------------------------------------------------------------*/ +/* Register length */ +#define REGISTER_LENGTH 2 +/*---------------------------------------------------------------------------*/ +/* Sensor data size */ +#define DATA_SIZE 4 +/*---------------------------------------------------------------------------*/ +/* Byte swap of 16-bit register value */ +#define HI_UINT16(a) (((a) >> 8) & 0xFF) +#define LO_UINT16(a) ((a) & 0xFF) + +#define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v)) +/*---------------------------------------------------------------------------*/ +#define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS); +/*---------------------------------------------------------------------------*/ +static uint8_t buf[DATA_SIZE]; +static uint16_t val; +/*---------------------------------------------------------------------------*/ +#define SENSOR_STATUS_DISABLED 0 +#define SENSOR_STATUS_INITIALISED 1 +#define SENSOR_STATUS_NOT_READY 2 +#define SENSOR_STATUS_READY 3 + +static int enabled = SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - 275ms */ +#define SENSOR_STARTUP_DELAY 36 + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +/* Latched values */ +static int obj_temp_latched; +static int amb_temp_latched; +/*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + enabled = SENSOR_STATUS_READY; + sensors_changed(&tmp_007_sensor); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Turn the sensor on/off + */ +static bool +enable_sensor(bool enable) +{ + bool success; + + SELECT() + + if(enable) { + val = TMP007_VAL_CONFIG_ON; + } else { + val = TMP007_VAL_CONFIG_OFF; + } + val = SWAP(val); + + success = sensor_common_write_reg(TMP007_REG_ADDR_CONFIG, (uint8_t *)&val, + REGISTER_LENGTH); + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read the sensor value registers + * \param raw_temp Temperature in 16 bit format + * \param raw_obj_temp object temperature in 16 bit format + * \return TRUE if valid data could be retrieved + */ +static bool +read_data(uint16_t *raw_temp, uint16_t *raw_obj_temp) +{ + bool success; + + SELECT(); + + success = sensor_common_read_reg(TMP007_REG_ADDR_STATUS, (uint8_t *)&val, + REGISTER_LENGTH); + + if(success) { + val = SWAP(val); + success = val & CONV_RDY_BIT; + } + + if(success) { + success = sensor_common_read_reg(TMP007_REG_ADDR_LOCAL_TEMP, &buf[0], + REGISTER_LENGTH); + if(success) { + success = sensor_common_read_reg(TMP007_REG_ADDR_OBJ_TEMP, &buf[2], + REGISTER_LENGTH); + } + } + + if(!success) { + sensor_common_set_error_data(buf, 4); + } + + /* Swap byte order */ + *raw_temp = buf[0] << 8 | buf[1]; + *raw_obj_temp = buf[2] << 8 | buf[3]; + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert raw data to values in degrees C + * \param raw_temp raw ambient temperature from sensor + * \param raw_obj_temp raw object temperature from sensor + * \param obj converted object temperature + * \param amb converted ambient temperature + */ +static void +convert(uint16_t raw_temp, uint16_t raw_obj_temp, float *obj, float *amb) +{ + const float SCALE_LSB = 0.03125; + float t; + int it; + + it = (int)((raw_obj_temp) >> 2); + t = ((float)(it)) * SCALE_LSB; + *obj = t; + + it = (int)((raw_temp) >> 2); + t = (float)it; + *amb = t * SCALE_LSB; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type TMP_007_SENSOR_TYPE_OBJECT or TMP_007_SENSOR_TYPE_AMBIENT + * \return Object or Ambient temperature in milli degrees C + */ +static int +value(int type) +{ + int rv; + uint16_t raw_temp; + uint16_t raw_obj_temp; + float obj_temp; + float amb_temp; + + if(enabled != SENSOR_STATUS_READY) { + PRINTF("Sensor disabled or starting up (%d)\n", enabled); + return CC26XX_SENSOR_READING_ERROR; + } + + if((type & TMP_007_SENSOR_TYPE_ALL) == 0) { + PRINTF("Invalid type\n"); + return CC26XX_SENSOR_READING_ERROR; + } + + rv = CC26XX_SENSOR_READING_ERROR; + + if(type == TMP_007_SENSOR_TYPE_ALL) { + rv = read_data(&raw_temp, &raw_obj_temp); + + if(rv == 0) { + return CC26XX_SENSOR_READING_ERROR; + } + + convert(raw_temp, raw_obj_temp, &obj_temp, &amb_temp); + PRINTF("TMP: %04X %04X o=%d a=%d\n", raw_temp, raw_obj_temp, + (int)(obj_temp * 1000), (int)(amb_temp * 1000)); + + obj_temp_latched = (int)(obj_temp * 1000); + amb_temp_latched = (int)(amb_temp * 1000); + rv = 1; + } else if(type == TMP_007_SENSOR_TYPE_OBJECT) { + rv = obj_temp_latched; + } else if(type == TMP_007_SENSOR_TYPE_AMBIENT) { + rv = amb_temp_latched; + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the TMP007 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + enable_sensor(false); + enabled = SENSOR_STATUS_INITIALISED; + break; + case SENSORS_ACTIVE: + /* Must be initialised first */ + if(enabled == SENSOR_STATUS_DISABLED) { + return SENSOR_STATUS_DISABLED; + } + if(enable) { + enable_sensor(true); + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); + enabled = SENSOR_STATUS_NOT_READY; + } else { + ctimer_stop(&startup_timer); + enable_sensor(false); + enabled = SENSOR_STATUS_INITIALISED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the sensor is enabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(tmp_007_sensor, "TMP007", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/tmp-007-sensor.h b/platform/srf06-cc26xx/sensortag/tmp-007-sensor.h new file mode 100644 index 000000000..10c96c8a0 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/tmp-007-sensor.h @@ -0,0 +1,76 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-tmp-sensor SensorTag 2.0 IR thermophile sensor + * + * Due to the time required for the sensor to startup, this driver is meant to + * be used in an asynchronous fashion. The caller must first activate the + * sensor by calling SENSORS_ACTIVATE(). This will trigger the sensor's startup + * sequence, but the call will not wait for it to complete so that the CPU can + * perform other tasks or drop to a low power mode. + * + * Once the sensor is stable, the driver will generate a sensors_changed event. + * + * The caller should then use value(TMP_007_SENSOR_TYPE_ALL) to read sensor + * values and latch them. Once completed successfully, individual readings can + * be retrieved with calls to value(TMP_007_SENSOR_TYPE_OBJECT) or + * value(TMP_007_SENSOR_TYPE_AMBIENT). + * + * Once required readings have been taken, the caller has two options: + * - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take + * subsequent readings SENSORS_ACTIVATE must be called again + * - Leave the sensor on. In this scenario, the caller can simply keep calling + * value(TMP_007_SENSOR_TYPE_ALL) to read and latch new values. However + * keeping the sensor on will consume more energy + * @{ + * + * \file + * Header file for the Sensortag-CC26xx TI TMP007 infrared thermophile sensor + */ +/*---------------------------------------------------------------------------*/ +#ifndef TMP_007_SENSOR_H_ +#define TMP_007_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#define TMP_007_SENSOR_TYPE_OBJECT 1 +#define TMP_007_SENSOR_TYPE_AMBIENT 2 +#define TMP_007_SENSOR_TYPE_ALL 3 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor tmp_007_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* TMP_007_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/srf06/Makefile.srf06 b/platform/srf06-cc26xx/srf06/Makefile.srf06 new file mode 100644 index 000000000..7d64aac94 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -0,0 +1,5 @@ +CFLAGS += -DBOARD_SMARTRF06EB=1 + +BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c + +CONTIKI_TARGET_DIRS += $(BOARD)/bsp diff --git a/platform/srf06-cc26xx/srf06/board-peripherals.h b/platform/srf06-cc26xx/srf06/board-peripherals.h new file mode 100644 index 000000000..def762b56 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/board-peripherals.h @@ -0,0 +1,49 @@ +/* + * 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 srf06-cc26xx-peripherals + * @{ + * + * \file + * Header file with definitions related to the Srf06EB peripherals + * + * \note Do not include this file directly. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_PERIPHERALS_H_ +#define BOARD_PERIPHERALS_H_ +/*---------------------------------------------------------------------------*/ +/* ToDo: Include things here */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_PERIPHERALS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/platform/srf06-cc26xx/srf06/board.c b/platform/srf06-cc26xx/srf06/board.c new file mode 100644 index 000000000..b62f3fc24 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/board.c @@ -0,0 +1,143 @@ +/* + * 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 sensortag-cc26xx-peripherals + * @{ + * + * \file + * Board-initialisation for the Srf06EB with a CC26xx EM. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "ti-lib.h" +#include "lpm.h" +#include "prcm.h" +#include "hw_sysctl.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define PRCM_DOMAINS (PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL | \ + PRCM_DOMAIN_PERIPH | PRCM_DOMAIN_CPU | \ + PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_VIMS) +/*---------------------------------------------------------------------------*/ +#define LPM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH) +/*---------------------------------------------------------------------------*/ +static void +power_domains_on(void) +{ + /* Turn on relevant power domains */ + ti_lib_prcm_power_domain_on(LPM_DOMAINS); + + /* Wait for domains to power on */ + while((ti_lib_prcm_power_domain_status(LPM_DOMAINS) + != PRCM_DOMAIN_POWER_ON)); +} +/*---------------------------------------------------------------------------*/ +static void +lpm_wakeup_handler(void) +{ + power_domains_on(); +} +/*---------------------------------------------------------------------------*/ +/* + * Declare a data structure to register with LPM. + * We don't care about what power mode we'll drop to, we don't care about + * getting notified before deep sleep. All we need is to be notified when we + * wake up so we can turn power domains back on + */ +LPM_MODULE(srf_module, NULL, NULL, lpm_wakeup_handler); +/*---------------------------------------------------------------------------*/ +void +board_init() +{ + uint8_t int_disabled = ti_lib_int_master_disable(); + + /* Turn on all power domains */ + ti_lib_prcm_power_domain_on(PRCM_DOMAINS); + + /* Wait for power on domains */ + while((ti_lib_prcm_power_domain_status(PRCM_DOMAINS) + != PRCM_DOMAIN_POWER_ON)); + + /* Configure all clock domains to run at full speed */ + ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_CPU | + PRCM_DOMAIN_CPU | PRCM_DOMAIN_TIMER | + PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH, + PRCM_CLOCK_DIV_1); + + /* Enable GPIO peripheral */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); + + /* Apply settings and wait for them to take effect */ + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()) ; + + /* Keys (input pullup) */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_UP); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_DOWN); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_SELECT); + + /* Turn off 3.3V domain (Powers the LCD and SD card reader): Output, low */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_3V3_EN); + ti_lib_gpio_pin_write(BOARD_3V3_EN, 0); + + /* LCD CSn (output high) */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LCD_CS); + ti_lib_gpio_pin_write(BOARD_LCD_CS, 1); + + /* SD Card reader CSn (output high) */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_SDCARD_CS); + ti_lib_gpio_pin_write(BOARD_SDCARD_CS, 1); + + /* Accelerometer (PWR output low, CSn output high) */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_PWR); + ti_lib_gpio_pin_write(BOARD_ACC_PWR, 0); + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_CS); + ti_lib_gpio_pin_write(BOARD_IOID_ACC_CS, 1); + + /* Ambient light sensor (off, output low) */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_ALS_OUT, IOC_NO_IOPULL); + + lpm_register_module(&srf_module); + + /* Re-enable interrupt if initially enabled. */ + if(!int_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/board.h b/platform/srf06-cc26xx/srf06/board.h new file mode 100644 index 000000000..42c060b9b --- /dev/null +++ b/platform/srf06-cc26xx/srf06/board.h @@ -0,0 +1,249 @@ +/* + * 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-srf-tag + * @{ + * + * \defgroup srf06-cc26xx-peripherals Peripherals for the SmartRF06EB + CC26xxEM + * + * Defines related to the SmartRF06 Evaluation Board with a CC26xxEM + * + * This file provides connectivity information on LEDs, Buttons, UART and + * other peripherals + * + * This file can be used as the basis to configure other boards using the + * CC26xx code as their basis. + * + * This file is not meant to be modified by the user. + * @{ + * + * \file + * Header file with definitions related to the I/O connections on the TI + * SmartRF06 Evaluation Board with a CC26xxEM + * + * \note Do not include this file directly. It gets included by contiki-conf + * after all relevant directives have been set. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_H_ +#define BOARD_H_ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +/*---------------------------------------------------------------------------*/ +/** + * \name LED configurations + * + * Those values are not meant to be modified by the user + * @{ + */ +/* Some files include leds.h before us, so we need to get rid of defaults in + * leds.h before we provide correct definitions */ +#undef LEDS_GREEN +#undef LEDS_YELLOW +#undef LEDS_RED +#undef LEDS_CONF_ALL + +#define LEDS_RED 1 /**< LED1 (Red) */ +#define LEDS_YELLOW 2 /**< LED2 (Yellow) */ +#define LEDS_GREEN 4 /**< LED3 (Green) */ +#define LEDS_ORANGE 8 /**< LED4 (Orange) */ + +#define LEDS_CONF_ALL 15 + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LED IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_LED_1 IOID_25 +#define BOARD_IOID_LED_2 IOID_27 +#define BOARD_IOID_LED_3 IOID_7 +#define BOARD_IOID_LED_4 IOID_6 +#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) +#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) +#define BOARD_LED_3 (1 << BOARD_IOID_LED_3) +#define BOARD_LED_4 (1 << BOARD_IOID_LED_4) +#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2 | BOARD_LED_3 | \ + BOARD_LED_4) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name UART IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_UART_RX IOID_2 +#define BOARD_IOID_UART_TX IOID_3 +#define BOARD_IOID_UART_CTS IOID_0 +#define BOARD_IOID_UART_RTS IOID_21 +#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) +#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) +#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) +#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Button IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_KEY_LEFT IOID_15 +#define BOARD_IOID_KEY_RIGHT IOID_18 +#define BOARD_IOID_KEY_UP IOID_19 +#define BOARD_IOID_KEY_DOWN IOID_12 +#define BOARD_IOID_KEY_SELECT IOID_11 +#define BOARD_KEY_LEFT (1 << BOARD_IOID_KEY_LEFT) +#define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) +#define BOARD_KEY_UP (1 << BOARD_IOID_KEY_UP) +#define BOARD_KEY_DOWN (1 << BOARD_IOID_KEY_DOWN) +#define BOARD_KEY_SELECT (1 << BOARD_IOID_KEY_SELECT) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name 3.3V domain IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_3V3_EN IOID_13 +#define BOARD_3V3_EN (1 << BOARD_IOID_3V3_EN) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SPI IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SPI_SCK IOID_10 +#define BOARD_IOID_SPI_MOSI IOID_9 +#define BOARD_IOID_SPI_MISO IOID_8 +#define BOARD_SPI_SCK (1 << BOARD_IOID_SPI_SCK) +#define BOARD_SPI_MOSI (1 << BOARD_IOID_SPI_MOSI) +#define BOARD_SPI_MISO (1 << BOARD_IOID_SPI_MISO) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LCD IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_LCD_MODE IOID_4 +#define BOARD_IOID_LCD_RST IOID_5 +#define BOARD_IOID_LCD_CS IOID_14 +#define BOARD_IOID_LCD_SCK BOARD_IOID_SPI_SCK +#define BOARD_IOID_LCD_MOSI BOARD_IOID_SPI_MOSI +#define BOARD_LCD_MODE (1 << BOARD_IOID_LCD_MODE) +#define BOARD_LCD_RST (1 << BOARD_IOID_LCD_RST) +#define BOARD_LCD_CS (1 << BOARD_IOID_LCD_CS) +#define BOARD_LCD_SCK BOARD_SPI_SCK +#define BOARD_LCD_MOSI BOARD_SPI_MOSI +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SD Card IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SDCARD_CS IOID_30 +#define BOARD_SDCARD_CS (1 << BOARD_IOID_SDCARD_CS) +#define BOARD_IOID_SDCARD_SCK BOARD_IOID_SPI_SCK +#define BOARD_SDCARD_SCK BOARD_SPI_SCK +#define BOARD_IOID_SDCARD_MOSI BOARD_IOID_SPI_MOSI +#define BOARD_SDCARD_MOSI BOARD_SPI_MOSI +#define BOARD_IOID_SDCARD_MISO BOARD_IOID_SPI_MISO +#define BOARD_SDCARD_MISO BOARD_SPI_MISO +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name ALS IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_ALS_PWR IOID_26 +#define BOARD_IOID_ALS_OUT IOID_23 +#define BOARD_ALS_PWR (1 << BOARD_IOID_ALS_PWR) +#define BOARD_ALS_OUT (1 << BOARD_IOID_ALS_OUT) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name ACC IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_ACC_PWR IOID_20 +#define BOARD_IOID_ACC_INT IOID_28 +#define BOARD_IOID_ACC_INT1 IOID_28 +#define BOARD_IOID_ACC_INT2 IOID_29 +#define BOARD_IOID_ACC_CS IOID_24 +#define BOARD_ACC_PWR (1 << BOARD_IOID_ACC_PWR) +#define BOARD_ACC_INT (1 << BOARD_IOID_ACC_INT) +#define BOARD_ACC_INT1 (1 << BOARD_IOID_ACC_INT1) +#define BOARD_ACC_INT2 (1 << BOARD_IOID_ACC_INT2) +#define BOARD_ACC_CS (1 << BOARD_IOID_ACC_CS) +#define BOARD_IOID_ACC_SCK BOARD_IOID_SPI_SCK +#define BOARD_ACC_SCK BOARD_SPI_SCK +#define BOARD_IOID_ACC_MOSI BOARD_IOID_SPI_MOSI +#define BOARD_ACC_MOSI BOARD_SPI_MOSI +#define BOARD_IOID_ACC_MISO BOARD_IOID_SPI_MISO +#define BOARD_ACC_MISO BOARD_SPI_MISO +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "TI SmartRF06EB+CC26xx EM" +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Board specific iniatialisation + * @{ + */ +void board_init(void); +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/srf06/button-sensor.c b/platform/srf06-cc26xx/srf06/button-sensor.c new file mode 100644 index 000000000..5c6dae6f1 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/button-sensor.c @@ -0,0 +1,492 @@ +/* + * 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 srf06-cc26xx-peripherals + * @{ + * + * \file + * Driver for the SmartRF06EB buttons when a CC26xxEM is mounted on the board + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "srf06/button-sensor.h" +#include "gpio-interrupt.h" +#include "sys/timer.h" +#include "lpm.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#else +#define BUTTON_SENSOR_ENABLE_SHUTDOWN 1 +#endif +/*---------------------------------------------------------------------------*/ +#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ + IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ + IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ + IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ + IOC_JTAG_DISABLE) +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) + +struct btn_timer { + struct timer debounce; + clock_time_t start; + clock_time_t duration; +}; + +static struct btn_timer sel_timer, left_timer, right_timer, up_timer, + down_timer; +/*---------------------------------------------------------------------------*/ +/** + * \brief Handler for SmartRF button presses + */ +static void +button_press_handler(uint8_t ioid) +{ + if(ioid == BOARD_IOID_KEY_SELECT) { + if(!timer_expired(&sel_timer.debounce)) { + return; + } + + timer_set(&sel_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_SELECT) == 0) { + sel_timer.start = clock_time(); + sel_timer.duration = 0; + } else { + sel_timer.duration = clock_time() - sel_timer.start; + sensors_changed(&button_select_sensor); + } + } + + if(ioid == BOARD_IOID_KEY_LEFT) { + if(!timer_expired(&left_timer.debounce)) { + return; + } + + timer_set(&left_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0) { + left_timer.start = clock_time(); + left_timer.duration = 0; + } else { + left_timer.duration = clock_time() - left_timer.start; + sensors_changed(&button_left_sensor); + } + } + + if(ioid == BOARD_IOID_KEY_RIGHT) { + if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { + if(!timer_expired(&right_timer.debounce)) { + return; + } + + timer_set(&right_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0) { + right_timer.start = clock_time(); + right_timer.duration = 0; + } else { + right_timer.duration = clock_time() - right_timer.start; + sensors_changed(&button_right_sensor); + } + } else { + lpm_shutdown(BOARD_IOID_KEY_RIGHT); + } + } + + if(ioid == BOARD_IOID_KEY_UP) { + if(!timer_expired(&up_timer.debounce)) { + return; + } + + timer_set(&up_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_UP) == 0) { + up_timer.start = clock_time(); + up_timer.duration = 0; + } else { + up_timer.duration = clock_time() - up_timer.start; + sensors_changed(&button_up_sensor); + } + } + + if(ioid == BOARD_IOID_KEY_DOWN) { + if(!timer_expired(&down_timer.debounce)) { + return; + } + + timer_set(&down_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_DOWN) == 0) { + down_timer.start = clock_time(); + down_timer.duration = 0; + } else { + down_timer.duration = clock_time() - down_timer.start; + sensors_changed(&button_down_sensor); + } + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the button sensor for all buttons. + * + * \param type This function does nothing unless type == SENSORS_ACTIVE + * \param c 0: disable the button, non-zero: enable + * \param key: One of BOARD_KEY_LEFT, BOARD_KEY_RIGHT etc + */ +static void +config_buttons(int type, int c, uint32_t key) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_gpio_event_clear(1 << key); + ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); + ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN); + gpio_interrupt_register_handler(key, button_press_handler); + break; + case SENSORS_ACTIVE: + if(c) { + ti_lib_gpio_event_clear(1 << key); + ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); + ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN); + ti_lib_ioc_int_enable(key); + } else { + ti_lib_ioc_int_disable(key); + } + break; + default: + break; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the select button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor api. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_select(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_SELECT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the left button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor api. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_left(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_LEFT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the right button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor api. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_right(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_RIGHT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the up button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor api. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_up(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_UP); + + return 1; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the down button. + * + * Parameters are passed onto config_buttons, which does the actual + * configuration + * Parameters are ignored. They have been included because the prototype is + * dictated by the core sensor api. The return value is also required by + * the API but otherwise ignored. + * + * \param type passed to config_buttons as-is + * \param value passed to config_buttons as-is + * + * \return ignored + */ +static int +config_down(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_DOWN); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +value_select(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_SELECT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)sel_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_left(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)left_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_right(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)right_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_up(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_UP) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)up_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_down(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_DOWN) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)down_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for all buttons + * \param type SENSORS_ACTIVE or SENSORS_READY + * \param key_io_id BOARD_IOID_KEY_LEFT, BOARD_IOID_KEY_RIGHT etc + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will only be called by status_left, status_right and the + * called will pass the correct key_io_id + */ +static int +status(int type, uint32_t key_io_id) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) { + return 1; + } + break; + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the select button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_select(int type) +{ + return status(type, BOARD_IOID_KEY_SELECT); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the left button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_left(int type) +{ + return status(type, BOARD_IOID_KEY_LEFT); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the right button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_right(int type) +{ + return status(type, BOARD_IOID_KEY_RIGHT); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the up button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_up(int type) +{ + return status(type, BOARD_IOID_KEY_UP); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for the down button. + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the button's port interrupt is enabled (edge detect) + * + * This function will call status. It will pass type verbatim and it will also + * pass the correct key_io_id + */ +static int +status_down(int type) +{ + return status(type, BOARD_IOID_KEY_DOWN); +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(button_select_sensor, BUTTON_SENSOR, value_select, + config_select, status_select); +SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left, + status_left); +SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right, + status_right); +SENSORS_SENSOR(button_up_sensor, BUTTON_SENSOR, value_up, config_up, status_up); +SENSORS_SENSOR(button_down_sensor, BUTTON_SENSOR, value_down, config_down, + status_down); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/button-sensor.h b/platform/srf06-cc26xx/srf06/button-sensor.h new file mode 100644 index 000000000..1f5752059 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/button-sensor.h @@ -0,0 +1,61 @@ +/* + * 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 srf06-cc26xx-peripherals + * @{ + * + * \file + * Header file for the SmartRF06EB + CC26xxEM Button Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_VALUE_STATE 0 +#define BUTTON_SENSOR_VALUE_DURATION 1 + +#define BUTTON_SENSOR_VALUE_RELEASED 0 +#define BUTTON_SENSOR_VALUE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +#define button_sensor button_select_sensor +extern const struct sensors_sensor button_select_sensor; +extern const struct sensors_sensor button_left_sensor; +extern const struct sensors_sensor button_right_sensor; +extern const struct sensors_sensor button_up_sensor; +extern const struct sensors_sensor button_down_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/leds-arch.c b/platform/srf06-cc26xx/srf06/leds-arch.c new file mode 100644 index 000000000..ce1c29c50 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/leds-arch.c @@ -0,0 +1,90 @@ +/* + * 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 srf06-cc26xx-peripherals + * @{ + * + * \file + * Driver for the SmartRF06EB LEDs when a CC26xx is mounted on the board + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +static unsigned char c; +static int inited = 0; +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + if(inited) { + return; + } + inited = 1; + + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_3); + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_4); + + ti_lib_gpio_pin_write(BOARD_LED_ALL, 0); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return c; +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + c = leds; + + /* Clear everything */ + ti_lib_gpio_pin_write(BOARD_LED_ALL, 0); + + if((leds & LEDS_RED) == LEDS_RED) { + ti_lib_gpio_pin_write(BOARD_LED_1, 1); + } + if((leds & LEDS_YELLOW) == LEDS_YELLOW) { + ti_lib_gpio_pin_write(BOARD_LED_2, 1); + } + if((leds & LEDS_GREEN) == LEDS_GREEN) { + ti_lib_gpio_pin_write(BOARD_LED_3, 1); + } + if((leds & LEDS_ORANGE) == LEDS_ORANGE) { + ti_lib_gpio_pin_write(BOARD_LED_4, 1); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/srf06-sensors.c b/platform/srf06-cc26xx/srf06/srf06-sensors.c new file mode 100644 index 000000000..c69b4c22f --- /dev/null +++ b/platform/srf06-cc26xx/srf06/srf06-sensors.c @@ -0,0 +1,49 @@ +/* + * 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 srf06-cc26xx-peripherals + * @{ + * + * \file + * Generic module controlling sensors on the SmartRF06EB when a CC26xx is + * mounted on the board + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "srf06/button-sensor.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \brief Exports a global symbol to be used by the sensor API */ +SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, + &button_up_sensor, &button_down_sensor); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/regression-tests/18-compile-arm-ports/Makefile b/regression-tests/18-compile-arm-ports/Makefile index 2de35da6d..4389c6d86 100644 --- a/regression-tests/18-compile-arm-ports/Makefile +++ b/regression-tests/18-compile-arm-ports/Makefile @@ -7,6 +7,7 @@ ipv6/rpl-border-router/ev-aducrf101mkxz \ webserver-ipv6/ev-aducrf101mkxz \ ipv6/multicast/ev-aducrf101mkxz \ cc2538dk/sniffer/ev-aducrf101mkxz \ +cc26xx/cc26xx-web-demo/srf06-cc26xx \ TOOLS=