From afe5f706f63d4f73565076af7840afbc3dc8c12a Mon Sep 17 00:00:00 2001 From: "Author: lihaichen" Date: Sat, 3 Mar 2018 08:53:51 -0600 Subject: [PATCH] Squashed commit of the following: cc1101: Changes from review of last PR. remove gpio remove cc1101 frame len remove FLAGS_RXONLY flags add cc1101 function remove some waring add cc1101 poll function add cc1101 register add cc1101 isr read data add cc1101 spi deviceId add cc1101 init2 add wait cc1101 chip ready raw init cc1101 --- configs/nucleo-l476rg/src/Makefile | 4 + configs/nucleo-l476rg/src/nucleo-l476rg.h | 24 +- configs/nucleo-l476rg/src/stm32_appinit.c | 32 +- configs/nucleo-l476rg/src/stm32_cc1101.c | 148 +++ configs/nucleo-l476rg/src/stm32_spi.c | 23 +- drivers/wireless/ISM2_433MHzMSK500kbps.c | 133 +++ drivers/wireless/Kconfig | 13 + drivers/wireless/Make.defs | 1 + drivers/wireless/cc1101.c | 1060 +++++++++++++++++---- include/nuttx/wireless/cc1101.h | 219 +++-- 10 files changed, 1400 insertions(+), 257 deletions(-) create mode 100644 configs/nucleo-l476rg/src/stm32_cc1101.c create mode 100644 drivers/wireless/ISM2_433MHzMSK500kbps.c diff --git a/configs/nucleo-l476rg/src/Makefile b/configs/nucleo-l476rg/src/Makefile index 1a5357555d..a21fd2956d 100644 --- a/configs/nucleo-l476rg/src/Makefile +++ b/configs/nucleo-l476rg/src/Makefile @@ -55,6 +55,10 @@ CSRCS += stm32_io.c endif endif +ifeq ($(CONFIG_WL_CC1101),y) +CSRCS += stm32_cc1101.c +endif + ifeq ($(CONFIG_ADC),y) CSRCS += stm32_adc.c ifeq ($(CONFIG_AJOYSTICK),y) diff --git a/configs/nucleo-l476rg/src/nucleo-l476rg.h b/configs/nucleo-l476rg/src/nucleo-l476rg.h index b249da652c..d8524b3340 100644 --- a/configs/nucleo-l476rg/src/nucleo-l476rg.h +++ b/configs/nucleo-l476rg/src/nucleo-l476rg.h @@ -1,7 +1,7 @@ /************************************************************************************ * configs/nucleo-l476rg/src/nucleo-l476rg.h * - * Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2016, 2018 Gregory Nutt. All rights reserved. * Authors: Frank Bennett * Gregory Nutt * Sebastien Lorquet @@ -166,6 +166,16 @@ GPIO_PORTB | GPIO_PIN6) #endif +#ifdef CONFIG_WL_CC1101 +# define GPIO_CC1101_PWR (GPIO_PORTC | GPIO_PIN6 | GPIO_OUTPUT_SET | \ + GPIO_OUTPUT | GPIO_PULLUP | GPIO_SPEED_50MHz) +# define GPIO_CC1101_CS (GPIO_PORTB | GPIO_PIN12 | GPIO_OUTPUT_SET | \ + GPIO_OUTPUT | GPIO_PULLUP | GPIO_SPEED_50MHz) +# define GPIO_CC1101_MISO (GPIO_PORTB | GPIO_PIN14) +# define GPIO_CC1101_GDO2 (GPIO_PORTC | GPIO_PIN10 | \ + GPIO_EXTI | GPIO_SPEED_50MHz) +#endif + #ifdef HAVE_MMCSD # define GPIO_SPI_CS_SD_CARD_OFF \ (GPIO_INPUT | GPIO_PULLDOWN | GPIO_SPEED_2MHz | \ @@ -387,4 +397,16 @@ int board_timer_driver_initialize(FAR const char *devpath, int timer); int stm32l4_qencoder_initialize(FAR const char *devpath, int timer); #endif +/**************************************************************************** + * Name: stm32_cc1101_initialize + * + * Description: + * Initialize and register the cc1101 radio driver + * + ****************************************************************************/ + +#ifdef CONFIG_WL_CC1101 +int stm32_cc1101_initialize(void); +#endif + #endif /* __CONFIGS_NUCLEO_L476RG_SRC_NUCLEO_L476RG_H */ diff --git a/configs/nucleo-l476rg/src/stm32_appinit.c b/configs/nucleo-l476rg/src/stm32_appinit.c index 65357c162b..5dbfa215b4 100644 --- a/configs/nucleo-l476rg/src/stm32_appinit.c +++ b/configs/nucleo-l476rg/src/stm32_appinit.c @@ -173,7 +173,7 @@ int board_app_initialize(uintptr_t arg) /* Now bind the SDIO interface to the MMC/SD driver */ ret = mmcsd_slotinitialize(CONFIG_NSH_MMCSDMINOR, g_sdio); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to bind SDIO to the MMC/SD driver: %d\n", @@ -214,7 +214,7 @@ int board_app_initialize(uintptr_t arg) /* Initialize and register the joystick driver */ ret = board_ajoy_initialize(); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the joystick driver: %d\n", @@ -227,7 +227,7 @@ int board_app_initialize(uintptr_t arg) /* Initialize and register the timer driver */ ret = board_timer_driver_initialize("/dev/timer0", 2); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the timer driver: %d\n", @@ -237,7 +237,6 @@ int board_app_initialize(uintptr_t arg) #endif #ifdef CONFIG_SENSORS_QENCODER - /* Initialize and register the qencoder driver */ index = 0; @@ -245,7 +244,7 @@ int board_app_initialize(uintptr_t arg) #ifdef CONFIG_STM32L4_TIM1_QE sprintf(buf, "/dev/qe%d", index++); ret = stm32l4_qencoder_initialize(buf, 1); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", @@ -257,7 +256,7 @@ int board_app_initialize(uintptr_t arg) #ifdef CONFIG_STM32L4_TIM2_QE sprintf(buf, "/dev/qe%d", index++); ret = stm32l4_qencoder_initialize(buf, 2); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", @@ -269,7 +268,7 @@ int board_app_initialize(uintptr_t arg) #ifdef CONFIG_STM32L4_TIM3_QE sprintf(buf, "/dev/qe%d", index++); ret = stm32l4_qencoder_initialize(buf, 3); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", @@ -281,7 +280,7 @@ int board_app_initialize(uintptr_t arg) #ifdef CONFIG_STM32L4_TIM4_QE sprintf(buf, "/dev/qe%d", index++); ret = stm32l4_qencoder_initialize(buf, 4); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", @@ -293,7 +292,7 @@ int board_app_initialize(uintptr_t arg) #ifdef CONFIG_STM32L4_TIM5_QE sprintf(buf, "/dev/qe%d", index++); ret = stm32l4_qencoder_initialize(buf, 5); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", @@ -305,7 +304,7 @@ int board_app_initialize(uintptr_t arg) #ifdef CONFIG_STM32L4_TIM8_QE sprintf(buf, "/dev/qe%d", index++); ret = stm32l4_qencoder_initialize(buf, 8); - if (ret != OK) + if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to register the qencoder: %d\n", @@ -313,7 +312,19 @@ int board_app_initialize(uintptr_t arg) return ret; } #endif +#endif /* CONFIG_SENSORS_QENCODER */ +#ifdef CONFIG_WL_CC1101 + /* Initialize and register the cc1101 radio */ + + ret = stm32_cc1101_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: stm32_cc1101_initialize failed: %d\n", + ret); + return ret; + } #endif UNUSED(ret); @@ -339,4 +350,3 @@ int board_uniqueid(uint8_t *uniqueid) return OK; } #endif - diff --git a/configs/nucleo-l476rg/src/stm32_cc1101.c b/configs/nucleo-l476rg/src/stm32_cc1101.c new file mode 100644 index 0000000000..9617a77f1d --- /dev/null +++ b/configs/nucleo-l476rg/src/stm32_cc1101.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * configs/nucleo-l476rg/src/stm32_cc1101.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: lihaichen + * + * 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 NuttX 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "stm32l4.h" +#include "nucleo-l476rg.h" + +#ifdef CONFIG_WL_CC1101 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cc1101_wait + * + * Description: + * + ****************************************************************************/ + +static void cc1101_wait(struct cc1101_dev_s *dev, uint32_t pin) +{ + while (stm32l4_gpioread(pin) == true) + { + } +} + +/**************************************************************************** + * Name: cc1101_irq + * + * Description: + * + ****************************************************************************/ + +static void cc1101_irq(FAR struct cc1101_dev_s *dev, bool enable) +{ + if (enable) + { + stm32l4_gpiosetevent(dev->isr_pin, false, true, true, cc1101_isr, dev); + } + else + { + stm32l4_gpiosetevent(dev->isr_pin, false, true, true, NULL, NULL); + } +} + +/**************************************************************************** + * Name: cc1101_pwr + * + * Description: + * + ****************************************************************************/ + +static void cc1101_pwr(FAR struct cc1101_dev_s *dev, bool enable) +{ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_cc1101_initialize + * + * Description: + * Initialize and register the cc1101 radio driver + * + ****************************************************************************/ + +int stm32_cc1101_initialize(void) +{ + FAR struct spi_dev_s *spi = NULL; + FAR struct cc1101_dev_s *dev = NULL; + + spi = stm32l4_spibus_initialize(CONFIG_CC1101_SPIDEV); + if (spi == NULL) + { + ierr("ERROR: Failed to initialize SPI bus %d\n", CONFIG_CC1101_SPIDEV); + return -ENODEV; + } + + dev = kmm_malloc(sizeof(struct cc1101_dev_s)); + if (dev == NULL) + { + return -ENOMEM; + } + + dev->spi = spi; + dev->isr_pin = GPIO_CC1101_GDO2; + dev->miso_pin = GPIO_CC1101_MISO; + dev->gdo = CC1101_PIN_GDO2; + dev->rfsettings = &cc1101_rfsettings_ISM2_433MHzMSK500kbps; + dev->dev_id = SPIDEV_WIRELESS(5); + dev->channel = 0; + dev->power = 1; + dev->ops.wait = cc1101_wait; + dev->ops.pwr = cc1101_pwr; + dev->ops.irq = cc1101_irq; + + return cc1101_register("/dev/cc1101", dev); +} +#endif diff --git a/configs/nucleo-l476rg/src/stm32_spi.c b/configs/nucleo-l476rg/src/stm32_spi.c index 5047ee3d0a..d6d07d64f8 100644 --- a/configs/nucleo-l476rg/src/stm32_spi.c +++ b/configs/nucleo-l476rg/src/stm32_spi.c @@ -1,7 +1,7 @@ /**************************************************************************** * configs/nucleo-l476rg/src/stm32l4_spi.c * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,8 @@ #include "nucleo-l476rg.h" -#if defined(CONFIG_STM32L4_SPI1) || defined(CONFIG_STM32L4_SPI2) || defined(CONFIG_STM32L4_SPI3) +#if defined(CONFIG_STM32L4_SPI1) || defined(CONFIG_STM32L4_SPI2) || \ + defined(CONFIG_STM32L4_SPI3) /************************************************************************************ * Public Data @@ -105,13 +106,22 @@ void weak_function stm32l4_spiinitialize(void) g_spi2 = stm32l4_spibus_initialize(2); +#ifdef CONFIG_WL_CC3000 /* Setup CS, EN & IRQ line IOs */ -#ifdef CONFIG_WL_CC3000 stm32l4_configgpio(GPIO_WIFI_CS); stm32l4_configgpio(GPIO_WIFI_EN); stm32l4_configgpio(GPIO_WIFI_INT); #endif + +#ifdef CONFIG_WL_CC1101 + /* Setup CS, IRQ(gdo2) line IOs */ + + stm32l4_configgpio(GPIO_CC1101_PWR); + stm32l4_configgpio(GPIO_CC1101_CS); + stm32l4_configgpio(GPIO_CC1101_GDO2); +#endif + #endif } @@ -177,6 +187,13 @@ void stm32l4_spi2select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected stm32l4_gpiowrite(GPIO_WIFI_CS, !selected); } #endif + +#ifdef CONFIG_WL_CC1101 + if (devid == SPIDEV_WIRELESS(5)) + { + stm32l4_gpiowrite(GPIO_CC1101_CS, !selected); + } +#endif } uint8_t stm32l4_spi2status(FAR struct spi_dev_s *dev, uint32_t devid) diff --git a/drivers/wireless/ISM2_433MHzMSK500kbps.c b/drivers/wireless/ISM2_433MHzMSK500kbps.c new file mode 100644 index 0000000000..b0defec46b --- /dev/null +++ b/drivers/wireless/ISM2_433MHzMSK500kbps.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * drivers/wireless/ISM2_905MHzGFSK250kbps.c + * + * Copyright (C) 2011 Uros Platise. All rights reserved. + * Copyright (C) 2011 Ales Verbic. All rights reserved. + * + * Authors: Uros Platise + * Ales Verbic + * + * 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 NuttX 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Settings for 905 MHz, GFSK at 250kbps + * + * ISM Region 2 (America) only, Band 902–928 MHz + * + * Cordless phones 1 W + * Microwave ovens 750 W + * Industrial heaters 100 kW + * Military radar 1000 kW + * + * Deviation = 126.953125 + * Base frequency = 901.999969 + * Carrier frequency = 905.998993 + * Channel number = 20 + * Carrier frequency = 905.998993 + * Modulated = true + * Modulation format = GFSK + * Manchester enable = false + * Sync word qualifier mode = 30/32 sync word bits detected + * Preamble count = 4 + * Channel spacing = 199.951172 + * Carrier frequency = 905.998993 + * Data rate = 249.939 + * RX filter BW = 541.666667 + * Data format = Normal mode + * Length config = Variable packet length mode. Packet length configured + * by the first byte after sync word + * CRC enable = true + * Packet length = 61 + * Device address = 0 + * Address config = No address check + * CRC autoflush = false + * PA ramping = false + * TX power = 0 + */ + +const struct c1101_rfsettings_s cc1101_rfsettings_ISM2_433MHzMSK500kbps = +{ + .FIFOTHR = 0x07, /* FIFOTHR */ + .SYNC1 = 0x9b, /* SYNC1 */ + .SYNC0 = 0xad, /* SYNC0 */ + .PKTLEN = 0xff, /* PKTLEN */ + .PKTCTRL1 = 0x04, /* Packet Automation Control */ + .PKTCTRL0 = 0x05, /* Packet Automation Control */ + .ADDR = 0xff, /* ADDR */ + .CHANNR = 0x00, /* CHANNR */ + + .FSCTRL1 = 0x0f, /* FSCTRL1 Frequency Synthesizer Control */ + .FSCTRL0 = 0x00, /* FSCTRL0 Frequency Synthesizer Control */ + + .FREQ2 = 0x10, /* FREQ2 Frequency Control Word, High Byte */ + .FREQ1 = 0xa7, /* FREQ1 Frequency Control Word, Middle Byte */ + .FREQ0 = 0x62, /* FREQ0 Frequency Control Word, Low Byte */ + + .MDMCFG4 = 0x1e, /* MDMCFG4 Modem Configuration */ + .MDMCFG3 = 0x3b, /* MDMCFG3 Modem Configuration */ + .MDMCFG2 = 0x73, /* MDMCFG2 Modem Configuration */ + .MDMCFG1 = 0x42, /* MDMCFG1 Modem Configuration */ + .MDMCFG0 = 0xf8, /* MDMCFG0 Modem Configuration */ + + .DEVIATN = 0x44, /* DEVIATN Modem Deviation Setting */ + .FOCCFG = 0x16, /* FOCCFG Frequency Offset Compensation Configuration */ + + .BSCFG = 0x6c, /* BSCFG Bit Synchronization Configuration */ + + .AGCCTRL2 = 0x45, /* AGCCTRL2 AGC Control */ + .AGCCTRL1 = 0x40, /* AGCCTRL1 AGC Control */ + .AGCCTRL0 = 0x91, /* AGCCTRL0 AGC Control */ + + .FREND1 = 0x56, /* FREND1 Front End RX Configuration */ + .FREND0 = 0x10, /* FREND0 Front End TX Configuration */ + + .FSCAL3 = 0xea, /* FSCAL3 Frequency Synthesizer Calibration */ + .FSCAL2 = 0x2A, /* FSCAL2 Frequency Synthesizer Calibration */ + .FSCAL1 = 0x00, /* FSCAL1 Frequency Synthesizer Calibration */ + .FSCAL0 = 0x1f, /* FSCAL0 Frequency Synthesizer Calibration */ + + .CHMIN = 0, /* VERIFY REGULATIONS! */ + .CHMAX = 0xff, + + .PAMAX = 8, /* 0 means power OFF, 8 represents PA[7] */ + .PA = + { + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } +}; diff --git a/drivers/wireless/Kconfig b/drivers/wireless/Kconfig index f4a0dc7191..a8e597f053 100644 --- a/drivers/wireless/Kconfig +++ b/drivers/wireless/Kconfig @@ -9,6 +9,19 @@ config WL_CC1101 bool "CC1101 RF transceiver support" default n select SPI + select SCHED_HPWORK + select SCHED_LPWORK + +if WL_CC1101 + +config CC1101_SPIDEV + int "SPI bus number" + default 2 + ---help--- + Selects the SPI bus number identying that SPI interface that + connects the CC1101 to the MCU. + +endif menuconfig WL_CC3000 bool "CC3000 Wireless Module support" diff --git a/drivers/wireless/Make.defs b/drivers/wireless/Make.defs index 8e41eafbf0..257ea88f4a 100644 --- a/drivers/wireless/Make.defs +++ b/drivers/wireless/Make.defs @@ -51,6 +51,7 @@ endif ifeq ($(CONFIG_WL_CC1101),y) CSRCS += cc1101.c ISM1_868MHzGFSK100kbps.c ISM2_905MHzGFSK250kbps.c +CSRCS += ISM2_433MHzMSK500kbps.c endif ifeq ($(CONFIG_WL_CC3000),y) diff --git a/drivers/wireless/cc1101.c b/drivers/wireless/cc1101.c index e31a6e2a1d..a19a983a07 100644 --- a/drivers/wireless/cc1101.c +++ b/drivers/wireless/cc1101.c @@ -50,7 +50,8 @@ * - Extend max packet length up to 255 bytes or rather infinite < 4096 bytes * - Power up/down modes * - Sequencing between states or add protection for correct termination of - * various different state (so that CC1101 does not block in case of improper use) + * various different state (so that CC1101 does not block in case of + * improper use) * * RSSI and LQI value interpretation * @@ -81,9 +82,11 @@ * * There are four to five "extreme cases" that can be used to illustrate * how RSSI and LQI work: + * * 1. A weak signal in the presence of noise may give low RSSI and low LQI. * 2. A weak signal in "total" absence of noise may give low RSSI and high LQI. - * 3. Strong noise (usually coming from an interferer) may give high RSSI and low LQI. + * 3. Strong noise (usually coming from an interferer) may give high RSSI + * and low LQI. * 4. A strong signal without much noise may give high RSSI and high LQI. * 5. A very strong signal that causes the receiver to saturate may give * high RSSI and low LQI. @@ -98,14 +101,17 @@ #include +#include +#include #include #include -#include +#include #include #include #include #include +#include #include /**************************************************************************** @@ -183,22 +189,22 @@ #define CC1101_WORTIME0 (0x37 | 0xc0) /* Low byte of WOR timer */ #define CC1101_PKTSTATUS (0x38 | 0xc0) /* Current GDOx status and packet status */ #define CC1101_VCO_VC_DAC (0x39 | 0xc0) /* Current setting from PLL cal module */ -#define CC1101_TXBYTES (0x3A | 0xc0) /* Underflow and # of bytes in TXFIFO */ -#define CC1101_RXBYTES (0x3B | 0xc0) /* Overflow and # of bytes in RXFIFO */ -#define CC1101_RCCTRL1_STATUS (0x3C | 0xc0) /* Last RC oscilator calibration results */ -#define CC1101_RCCTRL0_STATUS (0x3D | 0xc0) /* Last RC oscilator calibration results */ +#define CC1101_TXBYTES (0x3a | 0xc0) /* Underflow and # of bytes in TXFIFO */ +#define CC1101_RXBYTES (0x3b | 0xc0) /* Overflow and # of bytes in RXFIFO */ +#define CC1101_RCCTRL1_STATUS (0x3c | 0xc0) /* Last RC oscilator calibration results */ +#define CC1101_RCCTRL0_STATUS (0x3d | 0xc0) /* Last RC oscilator calibration results */ /* Multi byte memory locations */ -#define CC1101_PATABLE 0x3E -#define CC1101_TXFIFO 0x3F -#define CC1101_RXFIFO 0x3F +#define CC1101_PATABLE 0x3e +#define CC1101_TXFIFO 0x3f +#define CC1101_RXFIFO 0x3f /* Definitions for burst/single access to registers */ #define CC1101_WRITE_BURST 0x40 #define CC1101_READ_SINGLE 0x80 -#define CC1101_READ_BURST 0xC0 +#define CC1101_READ_BURST 0xc0 /* Strobe commands */ @@ -213,23 +219,21 @@ #define CC1101_SAFC 0x37 /* Perform AFC adjustment of the frequency synthesizer */ #define CC1101_SWOR 0x38 /* Start automatic RX polling sequence (Wake-on-Radio) */ #define CC1101_SPWD 0x39 /* Enter power down mode when CSn goes high. */ -#define CC1101_SFRX 0x3A /* Flush the RX FIFO buffer. */ -#define CC1101_SFTX 0x3B /* Flush the TX FIFO buffer. */ -#define CC1101_SWORRST 0x3C /* Reset real time clock. */ -#define CC1101_SNOP 0x3D /* No operation. */ +#define CC1101_SFRX 0x3a /* Flush the RX FIFO buffer. */ +#define CC1101_SFTX 0x3b /* Flush the TX FIFO buffer. */ +#define CC1101_SWORRST 0x3c /* Reset real time clock. */ +#define CC1101_SNOP 0x3d /* No operation. */ /* Modem Control */ #define CC1101_MCSM0_XOSC_FORCE_ON 0x01 -/* Chip Status Byte - */ - +/* Chip Status Byte */ /* Bit fields in the chip status byte */ #define CC1101_STATUS_CHIP_RDYn_BM 0x80 #define CC1101_STATUS_STATE_BM 0x70 -#define CC1101_STATUS_FIFO_BYTES_AVAILABLE_BM 0x0F +#define CC1101_STATUS_FIFO_BYTES_AVAILABLE_BM 0x0f /* Chip states */ @@ -272,59 +276,479 @@ /* Part number and version */ #define CC1101_PARTNUM_VALUE 0x00 -#define CC1101_VERSION_VALUE 0x04 +#define CC1101_VERSION_VALUE 0x17 /* Others ... */ #define CC1101_LQI_CRC_OK_BM 0x80 -#define CC1101_LQI_EST_BM 0x7F +#define CC1101_LQI_EST_BM 0x7f +#define FLAGS_RXONLY 1 /* Indicates receive operation only */ +#define FLAGS_XOSCENABLED 2 /* Indicates that one pin is configured as XOSC/n */ + +#ifndef CONFIG_WL_CC1101_RXFIFO_LEN +# define CONFIG_WL_CC1101_RXFIFO_LEN 3 +#endif /**************************************************************************** - * Private Data Types + * Private Function Prototypes ****************************************************************************/ -#define FLAGS_RXONLY 1 /* Indicates receive operation only */ -#define FLAGS_XOSCENABLED 2 /* Indicates that one pin is configured as XOSC/n */ - -struct cc1101_dev_s -{ - const struct c1101_rfsettings_s *rfsettings; - - struct spi_dev_s *spi; - uint8_t isrpin; /* CC1101 pin used to trigger interrupts */ - uint32_t pinset; /* GPIO of the MCU */ - uint8_t flags; - uint8_t channel; - uint8_t power; -}; +static int cc1101_file_open(FAR struct file *filep); +static int cc1101_file_close(FAR struct file *filep); +static ssize_t cc1101_file_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t cc1101_file_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +#ifndef CONFIG_DISABLE_POLL +static int cc1101_file_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif /**************************************************************************** * Private Data ****************************************************************************/ -static volatile int cc1101_interrupt = 0; +static const struct file_operations g_cc1101ops = +{ + cc1101_file_open, /* open */ + cc1101_file_close, /* close */ + cc1101_file_read, /* read */ + cc1101_file_write, /* write */ + NULL, /* seek */ + NULL /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , + cc1101_file_poll /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , + NULL /* unlink */ +#endif +}; /**************************************************************************** * Private Functions ****************************************************************************/ +static int cc1101_takesem(FAR sem_t *sem) +{ + int ret; + + /* Take a count from the semaphore, possibly waiting */ + + ret = nxsem_wait(sem); + + /* The only case that an error should occur here is if the wait + * was awakened by a signal + */ + + DEBUGASSERT(ret == OK || ret == -EINTR); + return ret; +} + +/**************************************************************************** + * Name: cc1101_givesem + ****************************************************************************/ + +#define cc1101_givesem(sem) nxsem_post(sem) + +/**************************************************************************** + * Name: cc1101_file_open + * + * Description: + * This function is called whenever the CC1101 device is opened. + * + ****************************************************************************/ + +static int cc1101_file_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct cc1101_dev_s *dev; + int ret; + + wlinfo("Opening CC1101 dev\n"); + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct cc1101_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = cc1101_takesem(&dev->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + /* Check if device is not already used */ + + if (dev->nopens > 0) + { + ret = -EBUSY; + goto errout; + } + + dev->ops.irq(dev, true); + cc1101_receive(dev); + dev->nopens++; + +errout: + nxsem_post(&dev->devsem); + return ret; +} + +/**************************************************************************** + * Name: cc1101_file_close + * + * Description: + * This routine is called when the CC1101 device is closed. + * It waits for the last remaining data to be sent. + * + ****************************************************************************/ + +static int cc1101_file_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct cc1101_dev_s *dev; + int ret; + + wlinfo("Closing CC1101 dev\n"); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct cc1101_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = cc1101_takesem(&dev->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + dev->ops.irq(dev, false); + // nrf24l01_changestate(dev, ST_POWER_DOWN); + dev->nopens--; + + nxsem_post(&dev->devsem); + return OK; +} + +/**************************************************************************** + * Name: cc1101_file_write + * + * Description: + * Standard driver write method. + * + ****************************************************************************/ + +static ssize_t cc1101_file_write(FAR struct file *filep, + FAR const char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct cc1101_dev_s *dev; + int ret; + + wlinfo("write CC1101 dev\n"); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct cc1101_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = cc1101_takesem(&dev->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + ret = cc1101_write(dev, (const uint8_t *)buffer, buflen); + cc1101_send(dev); + nxsem_post(&dev->devsem); + return ret; +} + +/**************************************************************************** + * Name: fifo_put + * + * Description: + * + ****************************************************************************/ + +static void fifo_put(FAR struct cc1101_dev_s *dev, FAR uint8_t *buffer, + uint8_t buflen) +{ + int ret; + int i; + + ret = cc1101_takesem(&dev->sem_rx_buffer); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return; + } + + dev->fifo_len++; + if (dev->fifo_len >= CONFIG_WL_CC1101_RXFIFO_LEN) + { + dev->fifo_len = CONFIG_WL_CC1101_RXFIFO_LEN; + dev->nxt_read = (dev->nxt_read + 1) % CONFIG_WL_CC1101_RXFIFO_LEN; + } + + for (i = 0; i < buflen && i < CC1101_PACKET_MAXDATALEN + 3; i++) + { + *(dev->rx_buffer + i + dev->nxt_write * (CC1101_PACKET_MAXDATALEN + 3)) = + buffer[i]; + } + + dev->nxt_write = (dev->nxt_write + 1) % CONFIG_WL_CC1101_RXFIFO_LEN; + nxsem_post(&dev->sem_rx_buffer); +} + +/**************************************************************************** + * Name: fifo_get + * + * Description: + * + ****************************************************************************/ + +static uint8_t fifo_get(FAR struct cc1101_dev_s *dev, FAR uint8_t *buffer, + uint8_t buflen) +{ + uint8_t pktlen; + uint8_t i; + int ret; + + ret = cc1101_takesem(&dev->sem_rx_buffer); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + if (dev->fifo_len == 0) + { + pktlen = 0; + goto no_data; + } + + pktlen = + *(dev->rx_buffer + dev->nxt_read * (CC1101_PACKET_MAXDATALEN + 3)) - 3; + + for (i = 0; i < pktlen && i < CC1101_PACKET_MAXDATALEN; i++) + { + *(buffer++) = + dev->rx_buffer[dev->nxt_read * (CC1101_PACKET_MAXDATALEN + 3) + i + + 1]; + } + + dev->nxt_read = (dev->nxt_read + 1) % CONFIG_WL_CC1101_RXFIFO_LEN; + dev->fifo_len--; + +no_data: + nxsem_post(&dev->sem_rx_buffer); + return pktlen; +} + +/**************************************************************************** + * Name: cc1101_file_read + * + * Description: + * Standard driver read method + * + ****************************************************************************/ + +static ssize_t cc1101_file_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct cc1101_dev_s *dev; + FAR struct inode *inode; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct cc1101_dev_s *)inode->i_private; + + ret = cc1101_takesem(&dev->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + if ((filep->f_oflags & O_NONBLOCK) == 0) + { + nxsem_trywait(&dev->sem_rx); + ret = 0; + } + else + { + ret = nxsem_wait(&dev->sem_rx); + } + + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + buflen = fifo_get(dev, (uint8_t *)buffer, buflen); + nxsem_post(&dev->devsem); + return buflen; +} + +/**************************************************************************** + * Name: nrf24l01_poll + * + * Description: + * Standard driver poll method. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int cc1101_file_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct cc1101_dev_s *dev; + int ret; + + wlinfo("setup: %d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct cc1101_dev_s *)inode->i_private; + + /* Exclusive access */ + + ret = cc1101_takesem(&dev->devsem); + if (ret < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); + return ret; + } + + /* Are we setting up the poll? Or tearing it down? */ + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + ret = -EDEADLK; + goto errout; + } + + /* Check if we can accept this poll. + * For now, only one thread can poll the device at any time + * (shorter / simpler code) + */ + + if (dev->pfd) + { + ret = -EBUSY; + goto errout; + } + + dev->pfd = fds; + + /* Is there is already data in the fifo? then trigger POLLIN now - + * don't wait for RX. + */ + + (void)cc1101_takesem(&dev->sem_rx_buffer); + if (dev->fifo_len > 0) + { + dev->pfd->revents |= POLLIN; /* Data available for input */ + nxsem_post(dev->pfd->sem); + } + + nxsem_post(&dev->sem_rx_buffer); + } + else /* Tear it down */ + { + dev->pfd = NULL; + } + +errout: + nxsem_post(&dev->devsem); + return ret; +} +#endif + +/**************************************************************************** + * Name: cc1101_access_begin + * + * Description: + * + ****************************************************************************/ + void cc1101_access_begin(FAR struct cc1101_dev_s *dev) { (void)SPI_LOCK(dev->spi, true); - SPI_SELECT(dev->spi, SPIDEV_WIRELESS(0), true); - SPI_SETMODE(dev->spi, SPIDEV_MODE0); /* CPOL=0, CPHA=0 */ + SPI_SELECT(dev->spi, dev->dev_id, true); + SPI_SETMODE(dev->spi, SPIDEV_MODE0); /* CPOL=0, CPHA=0 */ SPI_SETBITS(dev->spi, 8); (void)SPI_HWFEATURES(dev->spi, 0); + + if (dev->ops.wait) + { + dev->ops.wait(dev, dev->miso_pin); + } + else + { + usleep(150 * 1000); + } } +/**************************************************************************** + * Name: cc1101_access_end + * + * Description: + * + ****************************************************************************/ + void cc1101_access_end(FAR struct cc1101_dev_s *dev) { - SPI_SELECT(dev->spi, SPIDEV_WIRELESS(0), false); + SPI_SELECT(dev->spi, dev->dev_id, false); (void)SPI_LOCK(dev->spi, false); } -/* CC1101 Access with Range Check +/**************************************************************************** + * Name: cc1101_access_end + * + * Description: + * CC1101 Access with Range Check * * Input Parameters: * dev CC1101 Private Structure @@ -336,7 +760,8 @@ void cc1101_access_end(FAR struct cc1101_dev_s *dev) * * Returned Value: * OK on success or a negated errno value on any failure. - */ + * + ****************************************************************************/ int cc1101_access(FAR struct cc1101_dev_s *dev, uint8_t addr, FAR uint8_t *buf, int length) @@ -344,7 +769,7 @@ int cc1101_access(FAR struct cc1101_dev_s *dev, uint8_t addr, int stabyte; /* Address cannot explicitly define READ command while length WRITE. - * Also access to these cells is only permitted as one byte, eventhough + * Also access to these cells is only permitted as one byte, even though * transfer is marked as BURST! */ @@ -399,14 +824,19 @@ int cc1101_access(FAR struct cc1101_dev_s *dev, uint8_t addr, return stabyte; } -/* Strobes command and returns chip status byte +/**************************************************************************** + * Name: cc1101_strobe * - * By default commands are send as Write. To a command, - * CC1101_READ_SINGLE may be OR'ed to obtain the number of RX bytes - * pending in RX FIFO. - */ + * Description: + * Strobes command and returns chip status byte + * + * By default commands are send as Write. To a command, + * CC1101_READ_SINGLE may be OR'ed to obtain the number of RX bytes + * pending in RX FIFO. + * + ****************************************************************************/ -inline uint8_t cc1101_strobe(struct cc1101_dev_s *dev, uint8_t command) +uint8_t cc1101_strobe(struct cc1101_dev_s *dev, uint8_t command) { uint8_t status; @@ -420,12 +850,26 @@ inline uint8_t cc1101_strobe(struct cc1101_dev_s *dev, uint8_t command) return status; } +/**************************************************************************** + * Name: cc1101_reset + * + * Description: + * + ****************************************************************************/ + int cc1101_reset(struct cc1101_dev_s *dev) { cc1101_strobe(dev, CC1101_SRES); return OK; } +/**************************************************************************** + * Name: cc1101_checkpart + * + * Description: + * + ****************************************************************************/ + int cc1101_checkpart(struct cc1101_dev_s *dev) { uint8_t partnum; @@ -437,6 +881,8 @@ int cc1101_checkpart(struct cc1101_dev_s *dev) return -ENODEV; } + winfo("CC1101 cc1101_checkpart 0x%X 0x%X\n", partnum, version); + if (partnum == CC1101_PARTNUM_VALUE && version == CC1101_VERSION_VALUE) { return OK; @@ -445,29 +891,50 @@ int cc1101_checkpart(struct cc1101_dev_s *dev) return -ENOTSUP; } +/**************************************************************************** + * Name: cc1101_dumpregs + * + * Description: + * + ****************************************************************************/ + void cc1101_dumpregs(struct cc1101_dev_s *dev, uint8_t addr, uint8_t length) { - uint8_t buf[0x30], i; + uint8_t buf[0x30]; + int i; cc1101_access(dev, addr, (FAR uint8_t *)buf, length); - /* REVISIT: printf() should not be used from within the OS */ + /* printf() may not be used from within the OS! The following logic + * will not work correctly because of the ornamentationadded by each + * winfo call. printf() is forbidden in the OS; the best option is + * to buffer the formatted data then output with one winfo() call. + */ - printf("CC1101[%2x]: ", addr); + winfo("CC1101[%2x]: ", addr); for (i = 0; i < length; i++) { - printf(" %2x,", buf[i]); + winfo("%02X ", buf[i]); } - printf("\n"); + winfo("\n"); } +/**************************************************************************** + * Name: cc1101_setpacketctrl + * + * Description: + * + ****************************************************************************/ + void cc1101_setpacketctrl(struct cc1101_dev_s *dev) { uint8_t values[3]; - values[0] = 0; /* Rx FIFO threshold = 32, Tx FIFO threshold = 33 */ - cc1101_access(dev, CC1101_FIFOTHR, values, -1); + values[0] = dev->rfsettings->FIFOTHR; + values[1] = dev->rfsettings->SYNC1; + values[2] = dev->rfsettings->SYNC0; + cc1101_access(dev, CC1101_FIFOTHR, values, -3); /* Packet length * Limit it to 61 bytes in total: pktlen, data[61], rssi, lqi @@ -478,19 +945,26 @@ void cc1101_setpacketctrl(struct cc1101_dev_s *dev) /* Packet Control */ - values[0] = 0x04; /* Append status: RSSI and LQI at the end of received packet */ - /* TODO: CRC Auto Flash bit 0x08 ??? */ - values[1] = 0x05; /* CRC in Rx and Tx Enabled: Variable Packet mode, defined by first byte */ - /* TODO: Enable data whitening ... */ + values[0] = dev->rfsettings->PKTCTRL1; /* Append status: RSSI and LQI at the + * end of received packet */ + + /* TODO: CRC Auto Flash bit 0x08 ??? */ + + values[1] = dev->rfsettings->PKTCTRL0; /* CRC in Rx and Tx Enabled: Variable + * Packet mode, defined by first byte */ + + /* TODO: Enable data whitening ... */ + cc1101_access(dev, CC1101_PKTCTRL1, values, -2); /* Main Radio Control State Machine */ - values[0] = 0x07; /* No time-out */ - values[1] = 0x00; /* Clear channel if RSSI < thr && !receiving; - * TX -> RX, RX -> RX: 0x3F */ - values[2] = CC1101_MCSM0_VALUE; /* Calibrate on IDLE -> RX/TX, OSC Timeout = ~500 us - * TODO: has XOSC_FORCE_ON */ + values[0] = 0x07; /* No time-out */ + values[1] = 0x03; /* Clear channel if RSSI < thr && !receiving; + * TX -> RX, RX -> RX: 0x3F */ + values[2] = + CC1101_MCSM0_VALUE; /* Calibrate on IDLE -> RX/TX, OSC Timeout = ~500 us + * TODO: has XOSC_FORCE_ON */ cc1101_access(dev, CC1101_MCSM2, values, -3); /* Wake-On Radio Control */ @@ -499,48 +973,75 @@ void cc1101_setpacketctrl(struct cc1101_dev_s *dev) /* WOREVT1:WOREVT0 - 16-bit timeout register */ } -/**************************************************************************** - * Callbacks - ****************************************************************************/ - -/* External line triggers this callback - * - * The concept todo is: - * - GPIO provides EXTI Interrupt - * - It should handle EXTI Interrupts in ISR, to which chipcon can - * register a callback (and others). The ISR then foreach() calls a - * its callback, and it is up to peripheral to find, whether the cause - * of EXTI ISR was itself. - **/ - -int cc1101_eventcb(int irq, FAR void *context) -{ - cc1101_interrupt++; - return OK; -} - /**************************************************************************** * Public Functions ****************************************************************************/ -FAR struct cc1101_dev_s * - cc1101_init(FAR struct spi_dev_s *spi, uint8_t isrpin, - uint32_t pinset, - FAR const struct c1101_rfsettings_s *rfsettings) +/**************************************************************************** + * Name: cc1101_init2 + * + * Description: + * + ****************************************************************************/ + +FAR int cc1101_init2(FAR struct cc1101_dev_s *dev) +{ + int ret; + + DEBUGASSERT(dev); + + /* Reset chip, check status bytes */ + + ret = cc1101_reset(dev) + if (ret < 0) + { + return ret; + } + + /* Check part compatibility */ + + ret = cc1101_checkpart(dev) + if (ret < 0) + { + return ret; + } + + cc1101_setgdo(dev, CC1101_PIN_GDO0, CC1101_GDO_HIZ); + cc1101_setgdo(dev, CC1101_PIN_GDO1, CC1101_GDO_HIZ); + cc1101_setgdo(dev, CC1101_PIN_GDO2, CC1101_GDO_HIZ); + cc1101_setrf(dev, dev->rfsettings); + cc1101_setpacketctrl(dev); + cc1101_setgdo(dev, dev->gdo, CC1101_GDO_SYNC); + cc1101_dumpregs(dev, CC1101_PIN_GDO2, 39); + dev->status = CC1101_IDLE; + return 0; +} + +/**************************************************************************** + * Name: cc1101_init + * + * Description: + * + ****************************************************************************/ + +FAR struct cc1101_dev_s *cc1101_init( + FAR struct spi_dev_s *spi, uint32_t isr_pin, uint32_t miso_pin, + FAR const struct c1101_rfsettings_s *rfsettings, wait_cc1101_ready wait) { FAR struct cc1101_dev_s *dev; - ASSERT(spi); + DEBUGASSERT(spi); - if ((dev = kmm_malloc(sizeof(struct cc1101_dev_s))) == NULL) + dev = kmm_malloc(sizeof(struct cc1101_dev_s)); + if (dev == NULL) { return NULL; } + dev->isr_pin = isr_pin; + dev->miso_pin = miso_pin; dev->rfsettings = rfsettings; dev->spi = spi; - dev->isrpin = isrpin; - dev->pinset = pinset; dev->flags = 0; dev->channel = rfsettings->CHMIN; dev->power = rfsettings->PAMAX; @@ -573,7 +1074,7 @@ FAR struct cc1101_dev_s * cc1101_setrf(dev, rfsettings); cc1101_setpacketctrl(dev); - /* Set the ISR to be triggerred on falling edge of the: + /* Set the ISR to be triggered on falling edge of the: * * 6 (0x06) Asserts when sync word has been sent / received, and * de-asserts at the end of the packet. In RX, the pin will de-assert @@ -581,7 +1082,7 @@ FAR struct cc1101_dev_s * * In TX the pin will de-assert if the TX FIFO underflows. */ - cc1101_setgdo(dev, dev->isrpin, CC1101_GDO_SYNC); + cc1101_setgdo(dev, dev->gdo, CC1101_GDO_SYNC); /* Configure to receive interrupts on the external GPIO interrupt line. * @@ -592,9 +1093,16 @@ FAR struct cc1101_dev_s * return dev; } -int cc1101_deinit(struct cc1101_dev_s *dev) +/**************************************************************************** + * Name: cc1101_deinit + * + * Description: + * + ****************************************************************************/ + +int cc1101_deinit(FAR struct cc1101_dev_s *dev) { - ASSERT(dev); + DEBUGASSERT(dev); /* Release the external GPIO interrupt * @@ -612,22 +1120,43 @@ int cc1101_deinit(struct cc1101_dev_s *dev) return 0; } -int cc1101_powerup(struct cc1101_dev_s *dev) +/**************************************************************************** + * Name: cc1101_powerup + * + * Description: + * + ****************************************************************************/ + +int cc1101_powerup(FAR struct cc1101_dev_s *dev) { - ASSERT(dev); + DEBUGASSERT(dev); return 0; } -int cc1101_powerdown(struct cc1101_dev_s *dev) +/**************************************************************************** + * Name: cc1101_powerdown + * + * Description: + * + ****************************************************************************/ + +int cc1101_powerdown(FAR struct cc1101_dev_s *dev) { - ASSERT(dev); + DEBUGASSERT(dev); return 0; } -int cc1101_setgdo(struct cc1101_dev_s *dev, uint8_t pin, uint8_t function) +/**************************************************************************** + * Name: cc1101_setgdo + * + * Description: + * + ****************************************************************************/ + +int cc1101_setgdo(FAR struct cc1101_dev_s *dev, uint8_t pin, uint8_t function) { - ASSERT(dev); - ASSERT(pin <= CC1101_IOCFG0); + DEBUGASSERT(dev); + DEBUGASSERT(pin <= CC1101_IOCFG0); if (function >= CC1101_GDO_CLK_XOSC1) { @@ -658,22 +1187,33 @@ int cc1101_setgdo(struct cc1101_dev_s *dev, uint8_t pin, uint8_t function) return cc1101_access(dev, pin, &function, -1); } -int cc1101_setrf(struct cc1101_dev_s *dev, const struct c1101_rfsettings_s *settings) +/**************************************************************************** + * Name: cc1101_setrf + * + * Description: + * + ****************************************************************************/ + +int cc1101_setrf(FAR struct cc1101_dev_s *dev, + FAR const struct c1101_rfsettings_s *settings) { - ASSERT(dev); - ASSERT(settings); + DEBUGASSERT(dev); + DEBUGASSERT(settings); - if (cc1101_access(dev, CC1101_FSCTRL1, (FAR uint8_t *)&settings->FSCTRL1, -11) < 0) + if (cc1101_access( + dev, CC1101_FSCTRL1, (FAR uint8_t *)&settings->FSCTRL1, -11) < 0) { return -EIO; } - if (cc1101_access(dev, CC1101_FOCCFG, (FAR uint8_t *)&settings->FOCCFG, -5) < 0) + if (cc1101_access(dev, CC1101_FOCCFG, (FAR uint8_t *)&settings->FOCCFG, -5) < + 0) { return -EIO; } - if (cc1101_access(dev, CC1101_FREND1, (FAR uint8_t *)&settings->FREND1, -6) < 0) + if (cc1101_access(dev, CC1101_FREND1, (FAR uint8_t *)&settings->FREND1, -6) < + 0) { return -EIO; } @@ -696,11 +1236,18 @@ int cc1101_setrf(struct cc1101_dev_s *dev, const struct c1101_rfsettings_s *sett return OK; } -int cc1101_setchannel(struct cc1101_dev_s *dev, uint8_t channel) -{ - ASSERT(dev); +/**************************************************************************** + * Name: cc1101_setchannel + * + * Description: + * + ****************************************************************************/ - /* Store localy in further checks */ +int cc1101_setchannel(FAR struct cc1101_dev_s *dev, uint8_t channel) +{ + DEBUGASSERT(dev); + + /* Store locally in further checks */ dev->channel = channel; @@ -716,12 +1263,19 @@ int cc1101_setchannel(struct cc1101_dev_s *dev, uint8_t channel) } cc1101_access(dev, CC1101_CHANNR, &dev->channel, -1); - return dev->flags & FLAGS_RXONLY; + return dev->flags; } -uint8_t cc1101_setpower(struct cc1101_dev_s *dev, uint8_t power) +/**************************************************************************** + * Name: cc1101_setpower + * + * Description: + * + ****************************************************************************/ + +uint8_t cc1101_setpower(FAR struct cc1101_dev_s *dev, uint8_t power) { - ASSERT(dev); + DEBUGASSERT(dev); if (power > dev->rfsettings->PAMAX) { @@ -752,9 +1306,16 @@ uint8_t cc1101_setpower(struct cc1101_dev_s *dev, uint8_t power) dev->power = 0; } - return dev->power; + return dev->power; } +/**************************************************************************** + * Name: cc1101_calcRSSIdBm + * + * Description: + * + ****************************************************************************/ + int cc1101_calcRSSIdBm(int rssi) { if (rssi >= 128) @@ -765,81 +1326,98 @@ int cc1101_calcRSSIdBm(int rssi) return (rssi >> 1) - 74; } -int cc1101_receive(struct cc1101_dev_s *dev) +/**************************************************************************** + * Name: cc1101_receive + * + * Description: + * + ****************************************************************************/ + +int cc1101_receive(FAR struct cc1101_dev_s *dev) { - ASSERT(dev); + DEBUGASSERT(dev); - /* \todo Wait for IDLE before going into another state? */ - - cc1101_interrupt = 0; + /* REVISIT: Wait for IDLE before going into another state? */ + dev->status = CC1101_RECV; cc1101_strobe(dev, CC1101_SRX | CC1101_READ_SINGLE); - return 0; } -int cc1101_read(struct cc1101_dev_s *dev, uint8_t * buf, size_t size) +/**************************************************************************** + * Name: cc1101_read + * + * Description: + * + ****************************************************************************/ + +int cc1101_read(FAR struct cc1101_dev_s *dev, FAR uint8_t *buf, size_t size) { - ASSERT(dev); + uint8_t nbytes; + int ret = 0; - if (buf == NULL) + DEBUGASSERT(dev); + + if (buf == NULL || size == 0) { - if (size == 0) - { - return 64; - } - - /* else received packet size */ - + cc1101_strobe(dev, CC1101_SRX); return 0; } - if (cc1101_interrupt == 0) + cc1101_access(dev, CC1101_RXFIFO, &nbytes, 1); + + if (nbytes & 0x80) { - return 0; + wlwarn("RX FIFO full\n"); + ret = 0; + goto breakout; } - int status = cc1101_strobe(dev, CC1101_SNOP | CC1101_READ_SINGLE); + nbytes += 2; /* RSSI and LQI */ + ret = buf[0] = nbytes + 1; + cc1101_access(dev, CC1101_RXFIFO, buf + 1, (nbytes > size) ? size : nbytes); - if (status & CC1101_STATUS_FIFO_BYTES_AVAILABLE_BM && - (status & CC1101_STATE_MASK) == CC1101_STATE_IDLE) + /* Flush remaining bytes, if there is no room to receive or if there is a + * BAD CRC + */ + + if (!(buf[nbytes] & 0x80)) { - uint8_t nbytes; - - cc1101_access(dev, CC1101_RXFIFO, &nbytes, 1); - - nbytes += 2; /* RSSI and LQI */ - - cc1101_access(dev, CC1101_RXFIFO, buf, (nbytes > size) ? size : nbytes); - - /* Flush remaining bytes, if there is no room to receive - * or if there is a BAD CRC - */ - - if (nbytes > size || (nbytes <= size && !(buf[nbytes-1]&0x80))) - { - ninfo("Flushing RX FIFO\n"); - cc1101_strobe(dev, CC1101_SFRX); - } - - return nbytes; + wlwarn("RX CRC error\n"); + ret = 0; } - return 0; +breakout: + cc1101_strobe(dev, CC1101_SIDLE); + cc1101_strobe(dev, CC1101_SFRX); + cc1101_strobe(dev, CC1101_SRX); + return ret; } -int cc1101_write(struct cc1101_dev_s *dev, const uint8_t *buf, size_t size) +/**************************************************************************** + * Name: cc1101_write + * + * Description: + * + ****************************************************************************/ + +int cc1101_write(FAR struct cc1101_dev_s *dev, FAR const uint8_t *buf, + size_t size) { uint8_t packetlen; - ASSERT(dev); - ASSERT(buf); + DEBUGASSERT(dev); + DEBUGASSERT(buf); if (dev->flags & FLAGS_RXONLY) { return -EPERM; } + cc1101_strobe(dev, CC1101_SIDLE); + cc1101_strobe(dev, CC1101_SFTX); + dev->status = CC1101_SEND; + /* Present limit */ if (size > CC1101_PACKET_MAXDATALEN) @@ -853,33 +1431,171 @@ int cc1101_write(struct cc1101_dev_s *dev, const uint8_t *buf, size_t size) cc1101_access(dev, CC1101_TXFIFO, &packetlen, -1); cc1101_access(dev, CC1101_TXFIFO, (FAR uint8_t *)buf, -size); - return 0; } -int cc1101_send(struct cc1101_dev_s *dev) +/**************************************************************************** + * Name: cc1101_send + * + * Description: + * + ****************************************************************************/ + +int cc1101_send(FAR struct cc1101_dev_s *dev) { - ASSERT(dev); + DEBUGASSERT(dev); if (dev->flags & FLAGS_RXONLY) { return -EPERM; } - cc1101_interrupt = 0; - cc1101_strobe(dev, CC1101_STX); + cc1101_takesem(&dev->sem_tx); - /* wait until send, going to IDLE */ - - while (cc1101_interrupt == 0); + /* this is set MCSM1, send auto to rx */ + dev->status = CC1101_RECV; return 0; } -int cc1101_idle(struct cc1101_dev_s *dev) +/**************************************************************************** + * Name: cc1101_idle + * + * Description: + * + ****************************************************************************/ + +int cc1101_idle(FAR struct cc1101_dev_s *dev) { - ASSERT(dev); + DEBUGASSERT(dev); cc1101_strobe(dev, CC1101_SIDLE); return 0; } + +/**************************************************************************** + * Name: cc1101_unregister + * + * Description: + * + ****************************************************************************/ + +int cc1101_unregister(FAR struct cc1101_dev_s *dev) +{ + DEBUGASSERT(dev); + + /* Release IRQ */ + + dev->ops.irq(dev, false); + + /* Free memory */ + + kmm_free(dev->rx_buffer); + kmm_free(dev); + return OK; +} + +/**************************************************************************** + * Name: cc1101_register + * + * Description: + * + ****************************************************************************/ + +int cc1101_register(FAR const char *path, FAR struct cc1101_dev_s *dev) +{ + DEBUGASSERT(path); + DEBUGASSERT(dev); + + dev->status = CC1101_INIT; + dev->rx_buffer = + kmm_malloc((CC1101_PACKET_MAXDATALEN + 3) * CONFIG_WL_CC1101_RXFIFO_LEN); + if (dev->rx_buffer == NULL) + { + return -ENOMEM; + } + + dev->nxt_read = 0; + dev->nxt_write = 0; + dev->fifo_len = 0; + nxsem_init(&(dev->devsem), 0, 1); + nxsem_init(&(dev->sem_rx_buffer), 0, 1); + nxsem_init(&(dev->sem_rx), 0, 0); + nxsem_init(&(dev->sem_tx), 0, 0); + + if (cc1101_init2(dev) < 0) + { + kmm_free(dev); + wlerr("ERROR: Failed to initialize cc1101_init\n"); + return -ENODEV; + } + + return register_driver(path, &g_cc1101ops, 0666, dev); +} + +/**************************************************************************** + * Name: cc1101_isr_process + * + * Description: + * + ****************************************************************************/ + +void cc1101_isr_process(FAR void *arg) +{ + DEBUGASSERT(arg); + FAR struct cc1101_dev_s *dev = (struct cc1101_dev_s *)arg; + switch (dev->status) + { + case CC1101_SEND: + nxsem_post(&dev->sem_tx); + break; + + case CC1101_RECV: + { + uint8_t buf[CC1101_PACKET_MAXDATALEN + 3], len; + + memset(buf, 0, sizeof(buf)); + len = cc1101_read(dev, buf, sizeof(buf)); + wlinfo("recv==>[%d]\n", len); + + if (len < 1) + { + return; + } + + fifo_put(dev, buf, len); + nxsem_post(&dev->sem_rx); + +#ifndef CONFIG_DISABLE_POLL + if (dev->pfd) + { + dev->pfd->revents |= POLLIN; /* Data available for input */ + wlinfo("Wake up polled fd\n"); + nxsem_post(dev->pfd->sem); + } +#endif + } + break; + + default: + wlinfo("not process isr\n"); + break; + } +} + +/**************************************************************************** + * Name: cc1101_isr + * + * Description: + * + ****************************************************************************/ + +int cc1101_isr(int irq, FAR void *context, FAR void *arg) +{ + FAR struct cc1101_dev_s *dev = (struct cc1101_dev_s *)arg; + + DEBUGASSERT(arg); + + work_queue(HPWORK, &dev->irq_work, cc1101_isr_process, arg, 0); + return 0; +} diff --git a/include/nuttx/wireless/cc1101.h b/include/nuttx/wireless/cc1101.h index 0f695744fb..49c7468c7a 100644 --- a/include/nuttx/wireless/cc1101.h +++ b/include/nuttx/wireless/cc1101.h @@ -41,10 +41,14 @@ ****************************************************************************/ #include -#include #include #include +#include +#include + +#include +#include /**************************************************************************** * Pre-Processor Declarations @@ -55,9 +59,7 @@ #define CC1101_PACKET_MAXTOTALLEN 63 #define CC1101_PACKET_MAXDATALEN 61 -/* - * General Purpose, Test Output Pin Options - */ +/* General Purpose, Test Output Pin Options */ /* CC1101 General Purpose Pins */ @@ -113,7 +115,9 @@ #define CC1101_GDO_SYNC 0x06 /* Asserts when a packet has been received with CRC OK. De-asserts when - * the first byte is read from the RX FIFO. */ + * the first byte is read from the RX FIFO. + */ + #define CC1101_GDO_PKTRCV_CRCOK 0x07 /* Preamble Quality Reached. Asserts when the PQI is above the programmed @@ -180,7 +184,7 @@ * instead. */ -#define CC1101_GDO_PA_PD 0x1B +#define CC1101_GDO_PA_PD 0x1b /* LNA_PD. Note: LNA_PD will have the same signal level in SLEEP and RX * states. To control an external LNA or RX/TX switch in applications @@ -188,13 +192,13 @@ * instead. */ -#define CC1101_GDO_LNA_PD 0x1C +#define CC1101_GDO_LNA_PD 0x1c /* RX_SYMBOL_TICK. Can be used together with RX_HARD_DATA for alternative * serial RX output. */ -#define CC1101_GDO_RXSYMTICK 0x1D +#define CC1101_GDO_RXSYMTICK 0x1d #define CC1101_GDO_WOR_EVNT0 0x24 #define CC1101_GDO_WOR_EVNT1 0x25 @@ -210,13 +214,13 @@ /* High impedance (3-state). */ -#define CC1101_GDO_HIZ 0x2E +#define CC1101_GDO_HIZ 0x2e /* HW to 0 (HW1 achieved by setting GDOx_INV=1). Can be used to control * an external LNA/PA or RX/TX switch. */ -#define CC1101_GDO_HW 0x2F +#define CC1101_GDO_HW 0x2f /* There are 3 GDO pins, but only one CLK_XOSC/n can be selected as an * output at any time. If CLK_XOSC/n is to be monitored on one of the @@ -236,12 +240,12 @@ #define CC1101_GDO_CLK_XOSC12 0x37 #define CC1101_GDO_CLK_XOSC16 0x38 #define CC1101_GDO_CLK_XOSC24 0x39 -#define CC1101_GDO_CLK_XOSC32 0x3A -#define CC1101_GDO_CLK_XOSC48 0x3B -#define CC1101_GDO_CLK_XOSC64 0x3C -#define CC1101_GDO_CLK_XOSC96 0x3D -#define CC1101_GDO_CLK_XOSC128 0x3E -#define CC1101_GDO_CLK_XOSC192 0x3F +#define CC1101_GDO_CLK_XOSC32 0x3a +#define CC1101_GDO_CLK_XOSC48 0x3b +#define CC1101_GDO_CLK_XOSC64 0x3c +#define CC1101_GDO_CLK_XOSC96 0x3d +#define CC1101_GDO_CLK_XOSC128 0x3e +#define CC1101_GDO_CLK_XOSC192 0x3f /**************************************************************************** * Public Data Types @@ -250,69 +254,127 @@ #ifndef __ASSEMBLY__ #undef EXTERN #if defined(__cplusplus) -#define EXTERN extern "C" +# define EXTERN extern "C" extern "C" { #else # define EXTERN extern #endif +typedef int (*wait_cc1101_ready)(FAR struct cc1101_dev_s *dev, uint32_t); struct cc1101_dev_s; +struct cc1101_ops_s +{ + CODE void (*wait)(FAR struct cc1101_dev_s *dev, uint32_t); + CODE void (*irq)(FAR struct cc1101_dev_s *dev, bool enable); + CODE void (*pwr)(FAR struct cc1101_dev_s *dev, bool enable); +}; + +enum cc1101_status +{ + CC1101_INIT, + CC1101_IDLE, + CC1101_SEND, + CC1101_RECV, + CC1101_SLEEP, + CC1101_SXOFF +}; + +struct cc1101_dev_s +{ + const struct c1101_rfsettings_s *rfsettings; + struct spi_dev_s *spi; + struct cc1101_ops_s ops; + enum cc1101_status status; + uint8_t flags; + uint8_t channel; + uint8_t power; + uint32_t dev_id; /*SPI device Id*/ + uint32_t gdo; /*GDO for interrupt*/ + uint32_t isr_pin; /*ISR Pin*/ + uint32_t miso_pin; /*MISO Pin*/ + struct work_s irq_work; /* Interrupt handling "bottom half" */ + uint8_t nopens; /* The number of times the device has been opened */ + sem_t devsem; /* Ensures exclusive access to this structure */ + uint8_t *rx_buffer; /* Circular RX buffer. [pipe# / pkt_len] [packet data...] */ + uint16_t fifo_len; /* Number of bytes stored in fifo */ + uint16_t nxt_read; /* Next read index */ + uint16_t nxt_write; /* Next write index */ + sem_t sem_rx_buffer; /* Protect access to rx fifo */ + sem_t sem_rx; /* Wait for availability of received data */ + sem_t sem_tx; /* Wait for availability of send data */ +#ifndef CONFIG_DISABLE_POLL + FAR struct pollfd *pfd; /* Polled file descr (or NULL if any) */ +#endif +}; + /* The RF Settings includes only those fields required to configure * the RF radio. Other configuration fields depended on this driver * are configured by the cc1101_init(). + * + * REVISIT: Upper case field names violates the NuttX coding standard. */ struct c1101_rfsettings_s { - uint8_t FSCTRL1; /* Frequency synthesizer control. */ - uint8_t FSCTRL0; /* Frequency synthesizer control. */ + uint8_t FIFOTHR; /* FIFOTHR */ + uint8_t SYNC1; /* SYNC1 */ + uint8_t SYNC0; /* SYNC0 */ - uint8_t FREQ2; /* Frequency control word, high byte. */ - uint8_t FREQ1; /* Frequency control word, middle byte. */ - uint8_t FREQ0; /* Frequency control word, low byte. */ + uint8_t PKTLEN; /* PKTLEN */ + uint8_t PKTCTRL0; /* Packet Automation Control */ + uint8_t PKTCTRL1; /* Packet Automation Control */ - uint8_t MDMCFG4; /* Modem configuration. */ - uint8_t MDMCFG3; /* Modem configuration. */ - uint8_t MDMCFG2; /* Modem configuration. */ - uint8_t MDMCFG1; /* Modem configuration. */ - uint8_t MDMCFG0; /* Modem configuration. */ + uint8_t ADDR; /* ADDR */ + uint8_t CHANNR; /* CHANNR */ - uint8_t DEVIATN; /* Modem deviation setting (when FSK modulation is enabled). */ + uint8_t FSCTRL1; /* Frequency synthesizer control. */ + uint8_t FSCTRL0; /* Frequency synthesizer control. */ + + uint8_t FREQ2; /* Frequency control word, high byte. */ + uint8_t FREQ1; /* Frequency control word, middle byte. */ + uint8_t FREQ0; /* Frequency control word, low byte. */ + + uint8_t MDMCFG4; /* Modem configuration. */ + uint8_t MDMCFG3; /* Modem configuration. */ + uint8_t MDMCFG2; /* Modem configuration. */ + uint8_t MDMCFG1; /* Modem configuration. */ + uint8_t MDMCFG0; /* Modem configuration. */ + uint8_t DEVIATN; /* Modem deviation setting (when FSK modulation is enabled). */ /* GAP */ - uint8_t FOCCFG; /* Frequency Offset Compensation Configuration. */ + uint8_t FOCCFG; /* Frequency Offset Compensation Configuration. */ - uint8_t BSCFG; /* Bit synchronization Configuration. */ + uint8_t BSCFG; /* Bit synchronization Configuration. */ - uint8_t AGCCTRL2; /* AGC control. */ - uint8_t AGCCTRL1; /* AGC control. */ - uint8_t AGCCTRL0; /* AGC control. */ + uint8_t AGCCTRL2; /* AGC control. */ + uint8_t AGCCTRL1; /* AGC control. */ + uint8_t AGCCTRL0; /* AGC control. */ /* GAP */ - uint8_t FREND1; /* Front end RX configuration. */ - uint8_t FREND0; /* Front end RX configuration. */ + uint8_t FREND1; /* Front end RX configuration. */ + uint8_t FREND0; /* Front end RX configuration. */ - uint8_t FSCAL3; /* Frequency synthesizer calibration. */ - uint8_t FSCAL2; /* Frequency synthesizer calibration. */ - uint8_t FSCAL1; /* Frequency synthesizer calibration. */ - uint8_t FSCAL0; /* Frequency synthesizer calibration. */ + uint8_t FSCAL3; /* Frequency synthesizer calibration. */ + uint8_t FSCAL2; /* Frequency synthesizer calibration. */ + uint8_t FSCAL1; /* Frequency synthesizer calibration. */ + uint8_t FSCAL0; /* Frequency synthesizer calibration. */ /* REGULATORY LIMITS */ - uint8_t CHMIN; /* Channel Range defintion MIN .. */ - uint8_t CHMAX; /* .. and MAX */ - uint8_t PAMAX; /* at given maximum output power */ + uint8_t CHMIN; /* Channel Range defintion MIN .. */ + uint8_t CHMAX; /* .. and MAX */ + uint8_t PAMAX; /* at given maximum output power */ /* Power Table, for ramp-up/down and ASK modulation defined for * output power values as: * PA = {-30, -20, -15, -10, -5, 0, 5, 10} [dBm] */ - uint8_t PA[8]; + uint8_t PA[8]; }; /**************************************************************************** @@ -330,9 +392,10 @@ struct c1101_rfsettings_s * Frequency ERP Duty Cycle Bandwidth Remarks * 868 – 868.6 MHz +14 dBm < 1% No limits * 868.7 – 869.2 MHz +14 dBm < 0.1% No limits - * 869.3 – 869.4 MHz +10 dBm No limits < 25 kHz Appropriate access protocol required - * 869.4 – 869.65 MHz +27 dBm < 10% < 25 kHz Channels may be combined to one high speed channel - * 869.7 -870 MHz +7 dBm No limits No limits + * 869.3 – 869.4 MHz +10 dBm No limits < 25 kHz Appropriate access + * protocol required 869.4 – 869.65 MHz +27 dBm < 10% < 25 kHz + * Channels may be combined to one high speed channel 869.7 -870 MHz +7 + * dBm No limits No limits * * Frequency Band For License-Free Specific Applications in Europe * @@ -344,17 +407,18 @@ struct c1101_rfsettings_s * 863 – 865 MHz Radio Microphones +10 dBm No limits 200 kHz * 863 -865 MHz Wireless Audio Applications +10 dBm No limits 300 kHz * - * Duty Cycle Limit Total On Time Maximum On Time of Minimum Off Time of - * Within One Hour One Transmission Two Transmission - * < 0.1% 3.6 seconds 0.72 seconds 0.72 seconds - * < 1% 36 seconds 3.6 seconds 1.8 seconds - * < 10% 360 seconds 36 seconds 3.6 seconds + * Duty Cycle Limit Total On Time Maximum On Time of Minimum + * Off Time of Within One Hour One Transmission Two Transmission < + * 0.1% 3.6 seconds 0.72 seconds 0.72 seconds < 1% 36 + * seconds 3.6 seconds 1.8 seconds < 10% 360 + * seconds 36 seconds 3.6 seconds * * Reference: TI Application Report: swra048.pdf, May 2005 * ISM-Band and Short Range Device Regulatory Compliance Overview */ -EXTERN const struct c1101_rfsettings_s cc1101_rfsettings_ISM1_868MHzGFSK100kbps; +EXTERN const struct c1101_rfsettings_s + cc1101_rfsettings_ISM1_868MHzGFSK100kbps; /* 905 MHz, GFSK, 250 kbps, ISM Region 2 (America only) * @@ -366,12 +430,18 @@ EXTERN const struct c1101_rfsettings_s cc1101_rfsettings_ISM1_868MHzGFSK100kbps; * Military radar 1000 kW */ -EXTERN const struct c1101_rfsettings_s cc1101_rfsettings_ISM2_905MHzGFSK250kbps; +EXTERN const struct c1101_rfsettings_s + cc1101_rfsettings_ISM2_905MHzGFSK250kbps; + +EXTERN const struct c1101_rfsettings_s + cc1101_rfsettings_ISM2_433MHzMSK500kbps; /**************************************************************************** * Public Function Prototypes ****************************************************************************/ +FAR int cc1101_init2(FAR struct cc1101_dev_s *dev); + /**************************************************************************** * Initialize Chipcon CC1101 Chip. * After initialization CC1101 is ready to listen, receive and transmit @@ -395,8 +465,9 @@ EXTERN const struct c1101_rfsettings_s cc1101_rfsettings_ISM2_905MHzGFSK250kbps; * ****************************************************************************/ -struct cc1101_dev_s *cc1101_init(struct spi_dev_s *spi, uint8_t isrpin, - uint32_t pinset, const struct c1101_rfsettings_s *rfsettings); +struct cc1101_dev_s *cc1101_init( + FAR struct spi_dev_s *spi, uint32_t isr_pin, uint32_t miso_pin, + FAR const struct c1101_rfsettings_s *rfsettings, wait_cc1101_ready wait); /**************************************************************************** ** Deinitialize Chipcon CC1101 Chip @@ -409,32 +480,32 @@ struct cc1101_dev_s *cc1101_init(struct spi_dev_s *spi, uint8_t isrpin, * ****************************************************************************/ -int cc1101_deinit(struct cc1101_dev_s *dev); +int cc1101_deinit(FAR struct cc1101_dev_s *dev); /**************************************************************************** * Power up device, start conversion. Returns zero on success. ****************************************************************************/ -int cc1101_powerup(struct cc1101_dev_s *dev); +int cc1101_powerup(FAR struct cc1101_dev_s *dev); /**************************************************************************** * Power down device, stop conversion. Returns zero on success. ****************************************************************************/ -int cc1101_powerdown(struct cc1101_dev_s *dev); +int cc1101_powerdown(FAR struct cc1101_dev_s *dev); /**************************************************************************** * Set Multi Purpose Output Function. Returns zero on success. ****************************************************************************/ -int cc1101_setgdo(struct cc1101_dev_s *dev, uint8_t pin, uint8_t function); +int cc1101_setgdo(FAR struct cc1101_dev_s *dev, uint8_t pin, uint8_t function); /**************************************************************************** * Set RF settings. Use one from the database above. ****************************************************************************/ -int cc1101_setrf(struct cc1101_dev_s *dev, - const struct c1101_rfsettings_s *settings); +int cc1101_setrf(FAR struct cc1101_dev_s *dev, + FAR const struct c1101_rfsettings_s *settings); /**************************************************************************** * Set Channel. @@ -447,7 +518,7 @@ int cc1101_setrf(struct cc1101_dev_s *dev, * ****************************************************************************/ -int cc1101_setchannel(struct cc1101_dev_s *dev, uint8_t channel); +int cc1101_setchannel(FAR struct cc1101_dev_s *dev, uint8_t channel); /**************************************************************************** * Set Output Power @@ -465,10 +536,12 @@ int cc1101_setchannel(struct cc1101_dev_s *dev, uint8_t channel); * ****************************************************************************/ -uint8_t cc1101_setpower(struct cc1101_dev_s *dev, uint8_t power); +uint8_t cc1101_setpower(FAR struct cc1101_dev_s *dev, uint8_t power); /**************************************************************************** - * Convert RSSI as obtained from CC1101 to [dBm] */ + * Convert RSSI as obtained from CC1101 to [dBm] + * + ****************************************************************************/ int cc1101_calcRSSIdBm(int rssi); @@ -486,7 +559,7 @@ int cc1101_calcRSSIdBm(int rssi); * ****************************************************************************/ -int cc1101_receive(struct cc1101_dev_s *dev); +int cc1101_receive(FAR struct cc1101_dev_s *dev); /**************************************************************************** * Read received packet @@ -508,7 +581,7 @@ int cc1101_receive(struct cc1101_dev_s *dev); * ****************************************************************************/ -int cc1101_read(struct cc1101_dev_s *dev, uint8_t *buf, size_t size); +int cc1101_read(FAR struct cc1101_dev_s *dev, FAR uint8_t *buf, size_t size); /**************************************************************************** * Write data to be send, using the cc1101_send() @@ -522,7 +595,8 @@ int cc1101_read(struct cc1101_dev_s *dev, uint8_t *buf, size_t size); * ****************************************************************************/ -int cc1101_write(struct cc1101_dev_s *dev, const uint8_t *buf, size_t size); +int cc1101_write(FAR struct cc1101_dev_s *dev, FAR const uint8_t *buf, + size_t size); /**************************************************************************** * Send data previously written using cc1101_write() @@ -535,7 +609,7 @@ int cc1101_write(struct cc1101_dev_s *dev, const uint8_t *buf, size_t size); * ****************************************************************************/ -int cc1101_send(struct cc1101_dev_s *dev); +int cc1101_send(FAR struct cc1101_dev_s *dev); /**************************************************************************** * Enter idle state (after reception and transmission completes). @@ -545,7 +619,12 @@ int cc1101_send(struct cc1101_dev_s *dev); * ****************************************************************************/ -int cc1101_idle(struct cc1101_dev_s *dev); +int cc1101_idle(FAR struct cc1101_dev_s *dev); + +int cc1101_register(FAR const char *path, FAR struct cc1101_dev_s *dev); + +void cc1101_isr_process(FAR void *arg); +int cc1101_isr(int irq, FAR void *context, FAR void *arg); #undef EXTERN #if defined(__cplusplus) @@ -553,4 +632,4 @@ int cc1101_idle(struct cc1101_dev_s *dev); #endif #endif /* __ASSEMBLY__ */ -#endif /* __INCLUDE_NUTTX_WIRELESS_CC1101_H */ +#endif /* __INCLUDE_NUTTX_WIRELESS_CC1101_H */