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); +/*---------------------------------------------------------------------------*/ +/** @} */