drivers/ieee802154: Add support for Sub-GHz TI CC1200 chip

CC1200 is a sub-ghz chip supporting 6 ISM & SRD bands: 169, 433, 470,
868, 915 and 920 MHz, with features dedicated to IEEE 802.15.4(g).

Current driver enables CC1200 against actual IEEE 802.15.4 Soft-MAC. 'g'
version support in the Soft-MAC will follow later.

The chip itself is closer to a bare metal radio modem than to a usual
15.4 chip: up to the user to provide the right RF settings for the
carrier band. Such settings can be generaten through TI's SmartRF tool.

Hopefully, for channel selection, this driver will be clever enough to
compute the proper register change without any special input from the
user. This will work for all the bands supported by the chip.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-07-05 16:56:49 +02:00 committed by Jukka Rissanen
commit 8ded57d3a2
8 changed files with 2105 additions and 0 deletions

View file

@ -3,3 +3,4 @@ zephyr_sources_ifdef(CONFIG_IEEE802154_KW41Z ieee802154_kw41z.c)
zephyr_sources_ifdef(CONFIG_IEEE802154_UPIPE ieee802154_uart_pipe.c)
zephyr_sources_ifdef(CONFIG_IEEE802154_MCR20A ieee802154_mcr20a.c)
zephyr_sources_ifdef(CONFIG_IEEE802154_NRF5 ieee802154_nrf5.c)
zephyr_sources_ifdef(CONFIG_IEEE802154_CC1200 ieee802154_cc1200.c)

View file

@ -53,6 +53,8 @@ source "drivers/ieee802154/Kconfig.mcr20a"
source "drivers/ieee802154/Kconfig.nrf5"
source "drivers/ieee802154/Kconfig.cc1200"
menuconfig IEEE802154_UPIPE
bool "UART PIPE fake radio driver support for QEMU"
depends on BOARD_QEMU_X86 && NETWORKING

View file

@ -0,0 +1,187 @@
# Kconfig.cc1200 - TI CC1200 configuration options
#
menuconfig IEEE802154_CC1200
bool "TI CC1200 Driver support"
depends on NETWORKING
select NET_L2_IEEE802154_SUB_GHZ
default n
if IEEE802154_CC1200
config IEEE802154_CC1200_DRV_NAME
string "TI CC1200 Driver's name"
default "cc1200"
help
This option sets the driver name
config IEEE802154_CC1200_SPI_DRV_NAME
string "SPI driver's name to use to access CC1200"
default ""
help
This option is mandatory to set which SPI controller to use in order
to actually control the CC1200 chip.
config IEEE802154_CC1200_SPI_FREQ
int "SPI system frequency"
default 0
help
This option sets the SPI controller's frequency. Beware this value
depends on the SPI controller being used and also on the system
clock.
config IEEE802154_CC1200_SPI_SLAVE
int "SPI slave linked to CC1200"
default 0
help
This option sets the SPI slave number SPI controller has to switch
to when dealing with CC1200 chip.
config IEEE802154_CC1200_GPIO_SPI_CS
bool "Manage SPI CS through a GPIO pin"
default n
help
This option is useful if one needs to manage SPI CS through a GPIO
pin to by-pass the SPI controller's CS logic.
config IEEE802154_CC1200_GPIO_SPI_CS_DRV_NAME
string "GPIO driver's name to use to drive SPI CS through"
default ""
depends on IEEE802154_CC1200_GPIO_SPI_CS
help
This option is mandatory to set which GPIO controller to use in order
to actually emulate the SPI CS.
config IEEE802154_CC1200_GPIO_SPI_CS_PIN
int "GPIO PIN to use to drive SPI CS through"
default 0
depends on IEEE802154_CC1200_GPIO_SPI_CS
help
This option is mandatory to set which GPIO pin to use in order
to actually emulate the SPI CS.
config IEEE802154_CC1200_RX_STACK_SIZE
int "Driver's internal RX thread stack size"
default 800
help
This option sets the driver's stack size for its internal RX thread.
The default value should be sufficient, but in case it proves to be
a too little one, this option makes it easy to play with the size.
config IEEE802154_CC1200_INIT_PRIO
int "CC1200 initialization priority"
default 80
help
Set the initialization priority number. Do not mess with it unless
you know what you are doing. Beware cc1200 requires gpio and spi to
be ready first (and sometime gpio should be the very first as spi
might need it too). And of course it has to start before the net stack.
config IEEE802154_CC1200_RANDOM_MAC
bool "Random MAC address"
default y
help
Generate a random MAC address dynamically.
if ! IEEE802154_CC1200_RANDOM_MAC
config IEEE802154_CC1200_MAC4
hex "MAC Address Byte 4"
default 0
range 0 ff
help
This is the byte 4 of the MAC address.
config IEEE802154_CC1200_MAC5
hex "MAC Address Byte 5"
default 0
range 0 ff
help
This is the byte 5 of the MAC address.
config IEEE802154_CC1200_MAC6
hex "MAC Address Byte 6"
default 0
range 0 ff
help
This is the byte 6 of the MAC address.
config IEEE802154_CC1200_MAC7
hex "MAC Address Byte 7"
default 0
range 0 ff
help
This is the byte 7 of the MAC address.
endif # IEEE802154_CC1200_RANDOM_MAC
config IEEE802154_CC1200_XOSC
int "Value of the Crystal oscillator in kHz"
default 40000
help
This sets the XOSC value, it must be between 38400 and 40000.
This value should follow what has been set in the RF settings via
SmartRF tool. Do not touch this unless you know what you are doing.
config IEEE802154_CC1200_RF_PRESET
bool "Use TI CC1200 RF pre-sets"
default y
choice
prompt "TI CC1200 RF preset"
default IEEE802154_CC1200_RF_SET_0
depends on IEEE802154_CC1200_RF_PRESET
help
Set the RF preset you want to use.
config IEEE802154_CC1200_RF_SET_0
bool "868MHz - 50Kbps - 2-GFSK - IEEE 802.15.4g compliant - ETSI"
config IEEE802154_CC1200_RF_SET_1
bool "920MHz - 50Kbps - 2-GFSK - IEEE 802.15.4g compliant - ARIB"
config IEEE802154_CC1200_RF_SET_2
bool "434MHz - 50Kbjt - 2-GFSK - IEEE 802.15.4g compliant - ETSI"
endchoice
config IEEE802154_CC1200_CCA_THRESHOLD
int "Value in dbm of the CCA threshold"
default -91
help
Set the CCA threshold. See datasheet's AGC_CS_THR register for
more information. Do not touch this unless you know what you are doing.
config IEEE802154_CC1200_RSSI_OFFSET
int "Value in dbm of the RSSI offset"
default -81
help
Set the gain adjustment. See datasheet's AGC_GAIN_ADJUST register for
more information. Do not touch this unless you know what you are doing.
# Do no touch below settings unless you know what you are doing
config IEEE802154_CC1200_SETTLING_CFG
hex
default 0x03
config IEEE802154_CC1200_PKTCFG0
hex
default 0x20
config IEEE802154_CC1200_PKTCFG1
hex
default 0x03
config IEEE802154_CC1200_PKTCFG2
hex
default 0x00
config IEEE802154_CC1200_RFEND_CFG1
hex
default 0x3F
config IEEE802154_CC1200_RFEND_CFG0
hex
default 0x00
endif # IEEE802154_CC1200

View file

@ -0,0 +1,844 @@
/* ieee802154_cc1200.c - TI CC1200 driver */
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL
#define SYS_LOG_DOMAIN "dev/cc1200"
#include <logging/sys_log.h>
#include <errno.h>
#include <kernel.h>
#include <arch/cpu.h>
#include <board.h>
#include <device.h>
#include <init.h>
#include <net/net_if.h>
#include <net/net_pkt.h>
#include <misc/byteorder.h>
#include <string.h>
#include <random/rand32.h>
#include <spi.h>
#include <gpio.h>
#include <net/ieee802154_radio.h>
#include "ieee802154_cc1200.h"
#include "ieee802154_cc1200_rf.h"
#if defined(CONFIG_IEEE802154_CC1200_GPIO_SPI_CS)
static struct spi_cs_control cs_ctrl;
#endif
/* ToDo: supporting 802.15.4g will require GPIO2
* used as CC1200_GPIO_SIG_RXFIFO_THR
*
* Note: GPIO3 is unused.
*/
#define CC1200_IOCFG3 CC1200_GPIO_SIG_MARC_2PIN_STATUS_0
#define CC1200_IOCFG2 CC1200_GPIO_SIG_MARC_2PIN_STATUS_1
#define CC1200_IOCFG0 CC1200_GPIO_SIG_PKT_SYNC_RXTX
/***********************
* Debugging functions *
**********************/
#if CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL == 4
static void _cc1200_print_status(u8_t status)
{
if (status == CC1200_STATUS_IDLE) {
SYS_LOG_DBG("Idling");
} else if (status == CC1200_STATUS_RX) {
SYS_LOG_DBG("Receiving");
} else if (status == CC1200_STATUS_TX) {
SYS_LOG_DBG("Transmitting");
} else if (status == CC1200_STATUS_FSTXON) {
SYS_LOG_DBG("FS TX on");
} else if (status == CC1200_STATUS_CALIBRATE) {
SYS_LOG_DBG("Calibrating");
} else if (status == CC1200_STATUS_SETTLING) {
SYS_LOG_DBG("Settling");
} else if (status == CC1200_STATUS_RX_FIFO_ERROR) {
SYS_LOG_DBG("RX FIFO error!");
} else if (status == CC1200_STATUS_TX_FIFO_ERROR) {
SYS_LOG_DBG("TX FIFO error!");
}
}
#else
#define _cc1200_print_status(...)
#endif /* CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL */
/*********************
* Generic functions *
********************/
bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr,
void *data, size_t length, bool extended, bool burst)
{
u8_t cmd_buf[2];
struct spi_buf buf[2] = {
{
.buf = cmd_buf,
.len = extended ? 2 : 1,
},
{
.buf = data,
.len = length,
}
};
/*
SYS_LOG_DBG("%s: addr 0x%02x - Data %p Length %u - %s, %s",
read ? "Read" : "Write", addr, data, length,
extended ? "extended" : "normal",
burst ? "burst" : "single");
*/
cmd_buf[0] = 0;
if (burst) {
cmd_buf[0] |= CC1200_ACCESS_BURST;
}
if (extended) {
cmd_buf[0] |= CC1200_REG_EXTENDED_ADDRESS;
cmd_buf[1] = addr;
} else {
cmd_buf[0] |= addr;
}
if (read) {
cmd_buf[0] |= CC1200_ACCESS_RD;
return (spi_transceive(spi, buf, 1, buf, 2) == 0);
}
/* CC1200_ACCESS_WR is 0 so no need to play with it */
return (spi_write(spi, buf, data ? 2 : 1) == 0);
}
static inline u8_t *get_mac(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
#if defined(CONFIG_IEEE802154_CC1200_RANDOM_MAC)
u32_t *ptr = (u32_t *)(cc1200->mac_addr + 4);
UNALIGNED_PUT(sys_rand32_get(), ptr);
cc1200->mac_addr[7] = (cc1200->mac_addr[7] & ~0x01) | 0x02;
#else
cc1200->mac_addr[4] = CONFIG_IEEE802154_CC1200_MAC4;
cc1200->mac_addr[5] = CONFIG_IEEE802154_CC1200_MAC5;
cc1200->mac_addr[6] = CONFIG_IEEE802154_CC1200_MAC6;
cc1200->mac_addr[7] = CONFIG_IEEE802154_CC1200_MAC7;
#endif
cc1200->mac_addr[0] = 0x00;
cc1200->mac_addr[1] = 0x12;
cc1200->mac_addr[2] = 0x4b;
cc1200->mac_addr[3] = 0x00;
return cc1200->mac_addr;
}
static u8_t get_status(struct spi_config *spi)
{
u8_t val;
if (_cc1200_access_reg(spi, true, CC1200_INS_SNOP,
&val, 1, false, false)) {
/* See Section 3.1.2 */
return val & CC1200_STATUS_MASK;
}
/* We cannot get the status, so let's assume about readyness */
return CC1200_STATUS_CHIP_NOT_READY;
}
/******************
* GPIO functions *
*****************/
static inline void gpio0_int_handler(struct device *port,
struct gpio_callback *cb, u32_t pins)
{
struct cc1200_context *cc1200 =
CONTAINER_OF(cb, struct cc1200_context, rx_tx_cb);
if (atomic_get(&cc1200->tx) == 1) {
if (atomic_get(&cc1200->tx_start) == 0) {
atomic_set(&cc1200->tx_start, 1);
} else {
atomic_set(&cc1200->tx, 0);
}
k_sem_give(&cc1200->tx_sync);
} else {
if (atomic_get(&cc1200->rx) == 1) {
k_sem_give(&cc1200->rx_lock);
atomic_set(&cc1200->rx, 0);
} else {
atomic_set(&cc1200->rx, 1);
}
}
}
static void enable_gpio0_interrupt(struct cc1200_context *cc1200, bool enable)
{
if (enable) {
gpio_pin_enable_callback(
cc1200->gpios[CC1200_GPIO_IDX_GPIO0].dev,
cc1200->gpios[CC1200_GPIO_IDX_GPIO0].pin);
} else {
gpio_pin_disable_callback(
cc1200->gpios[CC1200_GPIO_IDX_GPIO0].dev,
cc1200->gpios[CC1200_GPIO_IDX_GPIO0].pin);
}
}
static void setup_gpio_callback(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
gpio_init_callback(&cc1200->rx_tx_cb, gpio0_int_handler,
BIT(cc1200->gpios[CC1200_GPIO_IDX_GPIO0].pin));
gpio_add_callback(cc1200->gpios[CC1200_GPIO_IDX_GPIO0].dev,
&cc1200->rx_tx_cb);
}
/****************
* RF functions *
***************/
static u8_t get_lo_divider(struct spi_config *spi)
{
/* See Table 34 */
return FSD_BANDSELECT(read_reg_fs_cfg(spi)) << 1;
}
static bool write_reg_freq(struct spi_config *spi, u32_t freq)
{
u8_t freq_data[3];
freq_data[0] = (u8_t)((freq & 0x00FF0000) >> 16);
freq_data[1] = (u8_t)((freq & 0x0000FF00) >> 8);
freq_data[2] = (u8_t)(freq & 0x000000FF);
return _cc1200_access_reg(spi, false, CC1200_REG_FREQ2,
freq_data, 3, true, true);
}
/* See Section 9.12 - RF programming
*
* The given formula in datasheet cannot be simply applied here, where CPU
* limits us to unsigned integers of 32 bits. Instead, "slicing" it to
* parts that fits in such limit is a solution which is applied below.
*
* The original formula being (freqoff is neglegted):
* Freq = ( RF * Lo_Div * 2^16 ) / Xtal
*
* RF and Xtal are, from here, expressed in KHz.
*
* It first calculates the targeted RF with given ChanCenterFreq0, channel
* spacing and the channel number.
*
* The calculation will slice the targeted RF by multiple of 10:
* 10^n where n is in [5, 3]. The rest, below 1000, is taken at once.
* Let's take the 434000 KHz RF for instance:
* it will be "sliced" in 3 parts: 400000, 30000, 4000.
* Or the 169406 KHz RF, 4 parts: 100000, 60000, 9000, 406.
*
* This permits also to play with Xtal to keep the result big enough to avoid
* losing precision. A factor - growing as much as Xtal decrease - is then
* applied to get to the proper result. Which one is rounded to the nearest
* integer, again to get a bit better precision.
*
* In the end, this algorithm below works for all the supported bands by CC1200.
* User does not need to pass anything extra besides the nominal settings: no
* pre-computed part or else.
*/
static u32_t rf_evaluate_freq_setting(struct cc1200_context *cc1200, u32_t chan)
{
u32_t xtal = CONFIG_IEEE802154_CC1200_XOSC;
u32_t mult_10 = 100000;
u32_t factor = 1;
u32_t freq = 0;
u32_t rf, lo_div;
rf = cc1200->rf_settings->chan_center_freq0 +
((chan * (u32_t)cc1200->rf_settings->channel_spacing) / 10);
lo_div = get_lo_divider(&cc1200->spi);
SYS_LOG_DBG("Calculating freq for %u KHz RF (%u)", rf, lo_div);
while (rf > 0) {
u32_t hz, freq_tmp, rst;
if (rf < 1000) {
hz = rf;
} else {
hz = rf / mult_10;
hz *= mult_10;
}
if (hz < 1000) {
freq_tmp = (hz * lo_div * 65536) / xtal;
} else {
freq_tmp = ((hz * lo_div) / xtal) * 65536;
}
rst = freq_tmp % factor;
freq_tmp /= factor;
if (factor > 1 && (rst/(factor/10)) > 5) {
freq_tmp++;
}
freq += freq_tmp;
factor *= 10;
mult_10 /= 10;
xtal /= 10;
rf -= hz;
}
SYS_LOG_DBG("FREQ is 0x%06X", freq);
return freq;
}
static bool
rf_install_settings(struct device *dev,
const struct cc1200_rf_registers_set *rf_settings)
{
struct cc1200_context *cc1200 = dev->driver_data;
if (!_cc1200_access_reg(&cc1200->spi, false, CC1200_REG_SYNC3,
(void *)rf_settings->registers,
CC1200_RF_NON_EXT_SPACE_REGS, false, true) ||
!_cc1200_access_reg(&cc1200->spi, false, CC1200_REG_IF_MIX_CFG,
(void *)rf_settings->registers +
CC1200_RF_NON_EXT_SPACE_REGS,
CC1200_RF_EXT_SPACE_REGS, true, true) ||
!write_reg_pkt_len(&cc1200->spi, 0xFF)) {
SYS_LOG_ERR("Could not install RF settings");
return false;
}
cc1200->rf_settings = rf_settings;
return true;
}
static int rf_calibrate(struct spi_config *spi)
{
if (!instruct_scal(spi)) {
SYS_LOG_ERR("Could not calibrate RF");
return -EIO;
}
k_busy_wait(5 * USEC_PER_MSEC);
/* We need to re-enable RX as SCAL shuts off the freq synth */
if (!instruct_sidle(spi) ||
!instruct_sfrx(spi) ||
!instruct_srx(spi)) {
SYS_LOG_ERR("Could not switch to RX");
return -EIO;
}
k_busy_wait(10 * USEC_PER_MSEC);
_cc1200_print_status(get_status(spi));
return 0;
}
/****************
* TX functions *
***************/
static inline bool write_txfifo(struct spi_config *spi,
void *data, size_t length)
{
return _cc1200_access_reg(spi, false,
CC1200_REG_TXFIFO,
data, length, false, true);
}
/****************
* RX functions *
***************/
static inline bool read_rxfifo(struct spi_config *spi,
void *data, size_t length)
{
return _cc1200_access_reg(spi, true,
CC1200_REG_RXFIFO,
data, length, false, true);
}
static inline u8_t get_packet_length(struct spi_config *spi)
{
u8_t len;
if (_cc1200_access_reg(spi, true, CC1200_REG_RXFIFO,
&len, 1, false, true)) {
return len;
}
return 0;
}
static inline bool verify_rxfifo_validity(struct spi_config *spi, u8_t pkt_len)
{
/* packet should be at least 3 bytes as a ACK */
if (pkt_len < 3 ||
read_reg_num_rxbytes(spi) > (pkt_len + CC1200_FCS_LEN)) {
return false;
}
return true;
}
static inline bool read_rxfifo_content(struct spi_config *spi,
struct net_buf *frag, u8_t len)
{
if (!read_rxfifo(spi, frag->data, len) ||
(get_status(spi) == CC1200_STATUS_RX_FIFO_ERROR)) {
return false;
}
net_buf_add(frag, len);
return true;
}
static inline bool verify_crc(struct spi_config *spi, struct net_pkt *pkt)
{
u8_t fcs[2];
if (!read_rxfifo(spi, fcs, 2)) {
return false;
}
if (!(fcs[1] & CC1200_FCS_CRC_OK)) {
return false;
}
net_pkt_set_ieee802154_rssi(pkt, fcs[0]);
net_pkt_set_ieee802154_lqi(pkt, fcs[1] & CC1200_FCS_LQI_MASK);
return true;
}
static void cc1200_rx(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
struct net_buf *pkt_frag;
struct net_pkt *pkt;
u8_t pkt_len;
while (1) {
pkt = NULL;
k_sem_take(&cc1200->rx_lock, K_FOREVER);
if (get_status(&cc1200->spi) == CC1200_STATUS_RX_FIFO_ERROR) {
SYS_LOG_ERR("Fifo error");
goto flush;
}
pkt_len = get_packet_length(&cc1200->spi);
if (!verify_rxfifo_validity(&cc1200->spi, pkt_len)) {
SYS_LOG_ERR("Invalid frame");
goto flush;
}
pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT);
if (!pkt) {
SYS_LOG_ERR("No free pkt available");
goto flush;
}
pkt_frag = net_pkt_get_frag(pkt, K_NO_WAIT);
if (!pkt_frag) {
SYS_LOG_ERR("No free frag available");
goto flush;
}
net_pkt_frag_insert(pkt, pkt_frag);
if (!read_rxfifo_content(&cc1200->spi, pkt_frag, pkt_len)) {
SYS_LOG_ERR("No content read");
goto flush;
}
if (!verify_crc(&cc1200->spi, pkt)) {
SYS_LOG_ERR("Bad packet CRC");
goto out;
}
if (ieee802154_radio_handle_ack(cc1200->iface, pkt) == NET_OK) {
SYS_LOG_DBG("ACK packet handled");
goto out;
}
SYS_LOG_DBG("Caught a packet (%u)", pkt_len);
if (net_recv_data(cc1200->iface, pkt) < 0) {
SYS_LOG_DBG("Packet dropped by NET stack");
goto out;
}
net_analyze_stack("CC1200 Rx Fiber stack",
K_THREAD_STACK_BUFFER(cc1200->rx_stack),
K_THREAD_STACK_SIZEOF(cc1200->rx_stack));
continue;
flush:
SYS_LOG_DBG("Flushing RX");
instruct_sidle(&cc1200->spi);
instruct_sfrx(&cc1200->spi);
instruct_srx(&cc1200->spi);
out:
if (pkt) {
net_pkt_unref(pkt);
}
}
}
/********************
* Radio device API *
*******************/
static enum ieee802154_hw_caps cc1200_get_capabilities(struct device *dev)
{
return IEEE802154_HW_FCS | IEEE802154_HW_SUB_GHZ;
}
static int cc1200_cca(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
if (atomic_get(&cc1200->rx) == 0) {
u8_t status = read_reg_rssi0(&cc1200->spi);
if (!(status & CARRIER_SENSE) &&
(status & CARRIER_SENSE_VALID)) {
return 0;
}
}
SYS_LOG_WRN("Busy");
return -EBUSY;
}
static int cc1200_set_channel(struct device *dev, u16_t channel)
{
struct cc1200_context *cc1200 = dev->driver_data;
/* Unlike usual 15.4 chips, cc1200 is closer to a bare metal radio modem
* and thus does not provide any means to select a channel directly, but
* requires instead that one calculates and configures the actual
* targeted frequency for the requested channel.
*
* See rf_evaluate_freq_setting() above.
*/
if (atomic_get(&cc1200->rx) == 0) {
u32_t freq = rf_evaluate_freq_setting(cc1200, channel);
if (!write_reg_freq(&cc1200->spi, freq) ||
rf_calibrate(&cc1200->spi)) {
SYS_LOG_ERR("Could not set channel %u", channel);
return -EIO;
}
}
return 0;
}
static int cc1200_set_txpower(struct device *dev, s16_t dbm)
{
struct cc1200_context *cc1200 = dev->driver_data;
u8_t pa_power_ramp;
SYS_LOG_DBG("%d dbm", dbm);
/* See Section 7.1 */
dbm = ((dbm + 18) * 2) - 1;
if ((dbm <= 3) || (dbm >= 64)) {
SYS_LOG_ERR("Unhandled value");
return -EINVAL;
}
pa_power_ramp = read_reg_pa_cfg1(&cc1200->spi) & ~PA_POWER_RAMP_MASK;
pa_power_ramp |= ((u8_t) dbm) & PA_POWER_RAMP_MASK;
if (!write_reg_pa_cfg1(&cc1200->spi, pa_power_ramp)) {
SYS_LOG_ERR("Could not proceed");
return -EIO;
}
return 0;
}
static int cc1200_tx(struct device *dev,
struct net_pkt *pkt,
struct net_buf *frag)
{
struct cc1200_context *cc1200 = dev->driver_data;
u8_t *frame = frag->data - net_pkt_ll_reserve(pkt);
u8_t len = net_pkt_ll_reserve(pkt) + frag->len;
bool status = false;
SYS_LOG_DBG("%p (%u)", frag, len);
/* ToDo:
* Supporting 802.15.4g will require to loop in pkt's frags
* depending on len value, this will also take more time.
*/
if (!instruct_sidle(&cc1200->spi) ||
!instruct_sfrx(&cc1200->spi) ||
!instruct_sftx(&cc1200->spi) ||
!instruct_sfstxon(&cc1200->spi)) {
SYS_LOG_ERR("Cannot switch to TX mode");
goto out;
}
if (!write_txfifo(&cc1200->spi, &len, CC1200_PHY_HDR_LEN) ||
!write_txfifo(&cc1200->spi, frame, len) ||
read_reg_num_txbytes(&cc1200->spi) != (len + CC1200_PHY_HDR_LEN)) {
SYS_LOG_ERR("Cannot fill-in TX fifo");
goto out;
}
atomic_set(&cc1200->tx, 1);
atomic_set(&cc1200->tx_start, 0);
if (!instruct_stx(&cc1200->spi)) {
SYS_LOG_ERR("Cannot start transmission");
goto out;
}
/* Wait for SYNC to be sent */
k_sem_take(&cc1200->tx_sync, 100);
if (atomic_get(&cc1200->tx_start) == 1) {
/* Now wait for the packet to be fully sent */
k_sem_take(&cc1200->tx_sync, 100);
}
out:
_cc1200_print_status(get_status(&cc1200->spi));
if (atomic_get(&cc1200->tx) == 1 &&
read_reg_num_txbytes(&cc1200->spi) != 0) {
SYS_LOG_ERR("TX Failed");
atomic_set(&cc1200->tx_start, 0);
instruct_sftx(&cc1200->spi);
status = false;
} else {
status = true;
}
atomic_set(&cc1200->tx, 0);
/* Get back to RX */
instruct_srx(&cc1200->spi);
return status ? 0 : -EIO;
}
static int cc1200_start(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
if (!instruct_sidle(&cc1200->spi) ||
!instruct_sftx(&cc1200->spi) ||
!instruct_sfrx(&cc1200->spi) ||
rf_calibrate(&cc1200->spi)) {
SYS_LOG_ERR("Could not proceed");
return -EIO;
}
enable_gpio0_interrupt(cc1200, true);
_cc1200_print_status(get_status(&cc1200->spi));
return 0;
}
static int cc1200_stop(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
enable_gpio0_interrupt(cc1200, false);
if (!instruct_spwd(&cc1200->spi)) {
SYS_LOG_ERR("Could not proceed");
return -EIO;
}
return 0;
}
static u16_t cc1200_get_channel_count(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
return cc1200->rf_settings->channel_limit;
}
/******************
* Initialization *
*****************/
static int power_on_and_setup(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
if (!instruct_sres(&cc1200->spi)) {
SYS_LOG_ERR("Cannot reset");
return -EIO;
}
if (!rf_install_settings(dev, &cc1200_rf_settings)) {
return -EIO;
}
if (!write_reg_iocfg3(&cc1200->spi, CC1200_IOCFG3) ||
!write_reg_iocfg2(&cc1200->spi, CC1200_IOCFG2) ||
!write_reg_iocfg0(&cc1200->spi, CC1200_IOCFG0)) {
SYS_LOG_ERR("Cannot configure GPIOs");
return -EIO;
}
setup_gpio_callback(dev);
return rf_calibrate(&cc1200->spi);
}
static int configure_spi(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
cc1200->spi.dev = device_get_binding(
CONFIG_IEEE802154_CC1200_SPI_DRV_NAME);
if (!cc1200->spi.dev) {
SYS_LOG_ERR("Unable to get SPI device");
return -ENODEV;
}
if (IS_ENABLED(CONFIG_IEEE802154_CC1200_GPIO_SPI_CS)) {
cs_ctrl.gpio_dev = device_get_binding(
CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_DRV_NAME);
if (!cs_ctrl.gpio_dev) {
SYS_LOG_ERR("Unable to get GPIO SPI CS device");
return -ENODEV;
}
cs_ctrl.gpio_pin = CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_PIN;
cs_ctrl.delay = 0;
cc1200->spi.cs = &cs_ctrl;
SYS_LOG_DBG("SPI GPIO CS configured on %s:%u",
CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_DRV_NAME,
CONFIG_IEEE802154_CC1200_GPIO_SPI_CS_PIN);
}
cc1200->spi.operation = SPI_WORD_SET(8);
cc1200->spi.frequency = CONFIG_IEEE802154_CC1200_SPI_FREQ;
cc1200->spi.slave = CONFIG_IEEE802154_CC1200_SPI_SLAVE;
return 0;
}
static int cc1200_init(struct device *dev)
{
struct cc1200_context *cc1200 = dev->driver_data;
atomic_set(&cc1200->tx, 0);
atomic_set(&cc1200->tx_start, 0);
atomic_set(&cc1200->rx, 0);
k_sem_init(&cc1200->rx_lock, 0, 1);
k_sem_init(&cc1200->tx_sync, 0, 1);
cc1200->gpios = cc1200_configure_gpios();
if (!cc1200->gpios) {
SYS_LOG_ERR("Configuring GPIOS failed");
return -EIO;
}
if (configure_spi(dev) != 0) {
SYS_LOG_ERR("Configuring SPI failed");
return -EIO;
}
SYS_LOG_DBG("GPIO and SPI configured");
if (power_on_and_setup(dev) != 0) {
SYS_LOG_ERR("Configuring CC1200 failed");
return -EIO;
}
k_thread_create(&cc1200->rx_thread, cc1200->rx_stack,
CONFIG_IEEE802154_CC1200_RX_STACK_SIZE,
(k_thread_entry_t)cc1200_rx,
dev, NULL, NULL, K_PRIO_COOP(2), 0, 0);
SYS_LOG_INF("CC1200 initialized");
return 0;
}
static void cc1200_iface_init(struct net_if *iface)
{
struct device *dev = net_if_get_device(iface);
struct cc1200_context *cc1200 = dev->driver_data;
u8_t *mac = get_mac(dev);
SYS_LOG_DBG("");
net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);
cc1200->iface = iface;
ieee802154_init(iface);
}
static struct cc1200_context cc1200_context_data;
static struct ieee802154_radio_api cc1200_radio_api = {
.iface_api.init = cc1200_iface_init,
.iface_api.send = ieee802154_radio_send,
.get_capabilities = cc1200_get_capabilities,
.cca = cc1200_cca,
.set_channel = cc1200_set_channel,
.set_txpower = cc1200_set_txpower,
.tx = cc1200_tx,
.start = cc1200_start,
.stop = cc1200_stop,
.get_subg_channel_count = cc1200_get_channel_count,
};
NET_DEVICE_INIT(cc1200, CONFIG_IEEE802154_CC1200_DRV_NAME,
cc1200_init, &cc1200_context_data, NULL,
CONFIG_IEEE802154_CC1200_INIT_PRIO,
&cc1200_radio_api, IEEE802154_L2,
NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125);

View file

@ -0,0 +1,130 @@
/* ieee802154_cc1200.h - Registers definition for TI CC1200 */
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __IEEE802154_CC1200_H__
#define __IEEE802154_CC1200_H__
#include <linker/sections.h>
#include <atomic.h>
#include <spi.h>
#include <ieee802154/cc1200.h>
/* Runtime context structure
***************************
*/
struct cc1200_context {
struct net_if *iface;
/**************************/
struct cc1200_gpio_configuration *gpios;
struct gpio_callback rx_tx_cb;
struct spi_config spi;
u8_t mac_addr[8];
/************RF************/
const struct cc1200_rf_registers_set *rf_settings;
/************TX************/
struct k_sem tx_sync;
atomic_t tx;
atomic_t tx_start;
/************RX************/
K_THREAD_STACK_MEMBER(rx_stack,
CONFIG_IEEE802154_CC1200_RX_STACK_SIZE);
struct k_thread rx_thread;
struct k_sem rx_lock;
atomic_t rx;
};
#include "ieee802154_cc1200_regs.h"
/* Registers useful routines
***************************
*/
bool _cc1200_access_reg(struct spi_config *spi, bool read, u8_t addr,
void *data, size_t length, bool extended, bool burst);
static inline u8_t _cc1200_read_single_reg(struct spi_config *spi,
u8_t addr, bool extended)
{
u8_t val;
if (_cc1200_access_reg(spi, true, addr, &val, 1, extended, false)) {
return val;
}
return 0;
}
static inline bool _cc1200_write_single_reg(struct spi_config *spi,
u8_t addr, u8_t val, bool extended)
{
return _cc1200_access_reg(spi, false, addr, &val, 1, extended, false);
}
static inline bool _cc1200_instruct(struct spi_config *spi, u8_t addr)
{
return _cc1200_access_reg(spi, false, addr, NULL, 0, false, false);
}
#define DEFINE_REG_READ(__reg_name, __reg_addr, __ext) \
static inline u8_t read_reg_##__reg_name(struct spi_config *spi) \
{ \
/*SYS_LOG_DBG("");*/ \
return _cc1200_read_single_reg(spi, __reg_addr, __ext); \
}
#define DEFINE_REG_WRITE(__reg_name, __reg_addr, __ext) \
static inline bool write_reg_##__reg_name(struct spi_config *spi, \
u8_t val) \
{ \
/*SYS_LOG_DBG("");*/ \
return _cc1200_write_single_reg(spi, __reg_addr, \
val, __ext); \
}
DEFINE_REG_WRITE(iocfg3, CC1200_REG_IOCFG3, false)
DEFINE_REG_WRITE(iocfg2, CC1200_REG_IOCFG2, false)
DEFINE_REG_WRITE(iocfg0, CC1200_REG_IOCFG0, false)
DEFINE_REG_WRITE(pa_cfg1, CC1200_REG_PA_CFG1, false)
DEFINE_REG_WRITE(pkt_len, CC1200_REG_PKT_LEN, false)
DEFINE_REG_READ(fs_cfg, CC1200_REG_FS_CFG, false)
DEFINE_REG_READ(rssi0, CC1200_REG_RSSI0, true)
DEFINE_REG_READ(pa_cfg1, CC1200_REG_PA_CFG1, false)
DEFINE_REG_READ(num_txbytes, CC1200_REG_NUM_TXBYTES, true)
DEFINE_REG_READ(num_rxbytes, CC1200_REG_NUM_RXBYTES, true)
/* Instructions useful routines
******************************
*/
#define DEFINE_STROBE_INSTRUCTION(__ins_name, __ins_addr) \
static inline bool instruct_##__ins_name(struct spi_config *spi) \
{ \
/*SYS_LOG_DBG("");*/ \
return _cc1200_instruct(spi, __ins_addr); \
}
DEFINE_STROBE_INSTRUCTION(sres, CC1200_INS_SRES)
DEFINE_STROBE_INSTRUCTION(sfstxon, CC1200_INS_SFSTXON)
DEFINE_STROBE_INSTRUCTION(sxoff, CC1200_INS_SXOFF)
DEFINE_STROBE_INSTRUCTION(scal, CC1200_INS_SCAL)
DEFINE_STROBE_INSTRUCTION(srx, CC1200_INS_SRX)
DEFINE_STROBE_INSTRUCTION(stx, CC1200_INS_STX)
DEFINE_STROBE_INSTRUCTION(sidle, CC1200_INS_SIDLE)
DEFINE_STROBE_INSTRUCTION(safc, CC1200_INS_SAFC)
DEFINE_STROBE_INSTRUCTION(swor, CC1200_INS_SWOR)
DEFINE_STROBE_INSTRUCTION(spwd, CC1200_INS_SPWD)
DEFINE_STROBE_INSTRUCTION(sfrx, CC1200_INS_SFRX)
DEFINE_STROBE_INSTRUCTION(sftx, CC1200_INS_SFTX)
DEFINE_STROBE_INSTRUCTION(sworrst, CC1200_INS_SWORRST)
DEFINE_STROBE_INSTRUCTION(snop, CC1200_INS_SNOP)
#endif /* __IEEE802154_CC1200_H__ */

View file

@ -0,0 +1,524 @@
/* ieee802154_cc1200_regs.h - Registers definition for TI CC1200 */
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __IEEE802154_CC1200_REGS_H__
#define __IEEE802154_CC1200_REGS_H__
/* Access types (see Section 3.2) */
#define CC1200_ACCESS_RD BIT(7)
#define CC1200_ACCESS_WR (0x00)
#define CC1200_ACCESS_BURST BIT(6)
/* Configuration registers (see Section 12 for the details) */
#define CC1200_REG_IOCFG3 (0x00)
#define GPIO3_ATRAN BIT(7)
#define GPIO3_INV BIT(6)
#define GPIO3_CFG(_cfg_) (_cfg_ & 0x3F)
#define CC1200_REG_IOCFG2 (0x01)
#define GPIO2_ATRAN BIT(7)
#define GPIO2_INV BIT(6)
#define GPIO2_CFG(_cfg_) (_cfg_ & 0x3F)
#define CC1200_REG_IOCFG1 (0x02)
#define GPIO1_ATRAN BIT(7)
#define GPIO1_INV BIT(6)
#define GPIO1_CFG(_cfg_) (_cfg_ & 0x3F)
#define CC1200_REG_IOCFG0 (0x03)
#define GPIO0_ATRAN BIT(7)
#define GPIO0_INV BIT(6)
#define GPIO0_CFG(_cfg_) (_cfg_ & 0x3F)
#define CC1200_REG_SYNC3 (0x04)
#define CC1200_REG_SYNC2 (0x05)
#define CC1200_REG_SYNC1 (0x06)
#define CC1200_REG_SYNC0 (0x07)
#define CC1200_REG_SYNC_CFG1 (0x08)
#define SYNC_MODE(_cfg_) (_cfg_ & 0xE0)
#define SYNC_THR(_cfg_) (_cfg_ & 0x1F)
#define CC1200_REG_SYNC_CFG0 (0x09)
#define AUTO_CLEAR BIT(5)
#define RX_CONFIG_LIMITATION BIT(4)
#define PQT_GATING_EN BIT(3)
#define EXT_SYNC_DETECT BIT(2)
#define STRICT_SYNC_CHECK(_cfg_) (_cfg_ & 0x03)
#define CC1200_REG_DEVIATION_M (0x0A)
#define CC1200_REG_MODCFG_DEV_E (0x0B)
#define MODEM_MODE(_cfg_) (_cfg_ & 0xC0)
#define MOD_FORMAT(_cfg_) (_cfg_ & 0x38)
#define DEV_E(_cfg_) (_cfg_ & 0x07)
#define CC1200_REG_DCFILT_CFG (0x0C)
#define DCFILT_FREEZE_COEFF BIT(6)
#define DCFILT_BW_SETTLE(_cfg_) (_cfg_ & 0x38)
#define DCFILT_BW(_cfg_) (_cfg_ & 0x07)
#define CC1200_REG_PREAMBLE_CFG1 (0x0D)
#define NUM_PREAMBL(_cfg_) (_cfg_ & 0x3C)
#define PREAMBLE_WORD(_cfg_) (_cfg_ & 0x03)
#define CC1200_REG_PREAMBLE_CFG0 (0x0E)
#define PQT_EN BIT(7)
#define PQT_VALID_TIMEOUT(_cfg_) (_cfg_ & 0x70)
#define PQT(_cfg_) (_cfg_ & 0x0F)
#define CC1200_REG_IQIC (0x0F)
#define IQIC_EN BIT(7)
#define IQIC_UPDATE_COEFF_EN BIT(6)
#define IQIC_BLEN_SETTLE(_cfg_) (_cfg_ & 0x30)
#define IQIC_BLEN(_cfg_) (_cfg_ & 0x0C)
#define IQIC_IMGCH_LEVEL_THR(_cfg_) (_cfg_ & 0x03)
#define CC1200_REG_CHAN_BW (0x10)
#define ADC_CIC_DECFACT(_cfg_) (_cfg_ & 0xC0)
#define BB_CIC_DECFAC(_cfg_) (_cfg_ & 0x3F)
/* Is it mentioned anywhere apart from chapter 12? No known address at least
* #define CC1200_REG_MDMCFG2 ()
* #define ASK_SHAPE(_cfg_) (_cfg_ & 0xC0)
* #define SYMBOL_MAP_CFG(_cfg_) (_cfg_ & 0x30)
* #define UPSAMPLER_P(_cfg_) (_cfg_ & 0x0E)
* #define CFM_DATA_EN BIT(0)
*/
#define CC1200_REG_MDMCFG1 (0x11)
#define CARRIER_SENSE_GATE BIT(7)
#define FIFO_EN BIT(6)
#define MANCHESTER_EN BIT(5)
#define INVERT_DATA_EN BIT(4)
#define COLLISION_DETECT_EN BIT(3)
#define DVGA_GAIN(_cfg_) (_cfg_ & 0x06)
#define SINGLE_ADC_EN BIT(0)
#define CC1200_REG_MDMCFG0 (0x12)
#define TRANSPARENT_MODE_EN BIT(6)
#define TRANSPARENT_INTFACT(_cfg_) (_cfg_ & 0x30)
#define DATA_FILTER_EN BIT(3)
#define VITERBI_EN BIT(2)
#define CC1200_REG_SYMBOL_RATE2 (0x13)
#define SRATE_E(_cfg_) (_cfg_ & 0xF0)
#define SRATE_M_19_16(_cfg_) (_cfg_ & 0x0F)
#define CC1200_REG_SYMBOL_RATE1 (0x14)
#define CC1200_REG_SYMBOL_RATE0 (0x15)
#define CC1200_REG_AGC_REF (0x16)
#define CC1200_REG_AGC_CS_THR (0x17)
#define CC1200_REG_AGC_GAIN_ADJUST (0x18)
#define CC1200_REG_AGC_CFG3 (0x19)
#define AGC_SYNC_BEHAVIOUR(_cfg_) (_cfg_ & 0xE0)
#define AGC_MIN_GAIN(_cfg_) (_cfg_ & 0x1F)
#define CC1200_REG_AGC_CFG2 (0x1A)
#define START_PREVIOUS_GAIN_EN BIT(7)
#define FE_PERFORMANCE_MODE(_cfg_) (_cfg_ & 0x60)
#define AGC_MAX_GAIN(_cfg_) (_cfg_ & 0x1F)
#define CC1200_REG_AGC_CFG1 (0x1B)
#define RSSI_STEP_THR BIT(6)
#define AGC_WIN_SIZE(_cfg_) (_cfg_ & 0x38)
#define AGC_SETTLE_WAIT(_cfg_) (_cfg_ & 0x07)
#define CC1200_REG_AGC_CFG0 (0x1C)
#define AGC_HYST_LEVEL(_cfg_) (_cfg_ & 0xC0)
#define AGC_SLEWRATE_LIMIT(_cfg_) (_cfg_ & 0x30)
#define RSSI_VALID_CNT(_cfg_) (_cfg_ & 0x0C)
#define AGC_ASK_DECAY(_cfg_) (_cfg_ & 0x03)
#define CC1200_REG_FIFO_CFG (0x1D)
#define CRC_AUTOFLUSH BIT(7)
#define FIFO_THR(_cfg_) (_cfg_ & 0x7F)
#define CC1200_REG_DEV_ADDR (0x1E)
#define CC1200_REG_SETTLING_CFG (0x1F)
#define FS_AUTOCAL(_cfg_) (_cfg_ & 0x18)
#define LOCK_TIME(_cfg_) (_cfg_ & 0x06)
#define FSREG_TIME BIT(0)
#define CC1200_REG_FS_CFG (0x20)
#define FS_LOCK_EN BIT(4)
#define FSD_BANDSELECT(_cfg_) (_cfg_ & 0x0F)
#define CC1200_REG_WOR_CFG1 (0x21)
#define WOR_RES(_cfg_) (_cfg_ & 0xC0)
#define WOR_MODE(_cfg_) (_cfg_ & 0x38)
#define EVENT1(_cfg_) (_cfg_ & 0x07)
#define CC1200_REG_WOR_CFG0 (0x22)
#define RX_DUTY_CYCLE_MODE(_cfg_) (_cfg_ & 0xC0)
#define DIV_256HZ_EN BIT(5)
#define EVENT2_CFG(_cfg_) (_cfg_ & 0x18)
#define RC_MODE(_cfg_) (_cfg_ & 0x06)
#define RC_PD BIT(0)
#define CC1200_REG_WOR_EVENT0_MSB (0x23)
#define CC1200_REG_WOR_EVENT0_LSB (0x24)
#define CC1200_REG_RXDCM_TIME (0x25)
#define CC1200_REG_PKT_CFG2 (0x26)
#define BYTE_SWAP_EN BIT(6)
#define FG_MODE_EN BIT(5)
#define CCA_MODE(_cfg_) (_cfg_ & 0x1C)
#define CCA_ALWAYS_CLEAR (0)
#define CCA_RSSI_BELOW (1 << 2)
#define CCA_NO_RX (2 << 2)
#define CCA_RSSI_BELOW_NO_RX (3 << 2)
#define CCA_RSSI_BELOW_ETSI_LBT (4 << 2)
#define PKT_FORMAT(_cfg_) (_cfg_ & 0x03)
#define PKT_FORMAT_NORMAL_MODE (0)
#define PKT_FORMAT_SYNCHRONOUS_MODE (1)
#define PKT_FORMAT_RANDOM_MODE (2)
#define PKT_FORMAT_TRANSPARENT_MODE (3)
#define CC1200_REG_PKT_CFG1 (0x27)
#define FEC_EN BIT(7)
#define WHITE_DATA BIT(6)
#define PN9_SWAP_EN BIT(5)
#define ADDR_CHECK_CFG(_cfg_) (_cfg_ & 0x18)
#define ADDR_NO_CHK (0)
#define ADDR_CHK_NO_BROADCAST (1 << 3)
#define ADDR_CHK_BROADCAST_00 (2 << 3)
#define ADDR_CHK_BROADCAST_FF (3 << 3)
#define CRC_CFG(_cfg_) (_cfg_ & 0x06)
#define CRC_NONE (0)
#define CRC_FFFF (1 << 1)
#define CRC_0000 (2 << 1)
#define CRC_1D0F (3 << 1)
#define APPEND_STATUS BIT(0)
#define CC1200_REG_PKT_CFG0 (0x28)
#define LENGTH_CONFIG(_cfg_) (_cfg_ & 0x60)
#define LENGTH_FIXED (0)
#define LENGTH_VAR_1 (1 << 5)
#define LENGTH_INFINITE (2 << 5)
#define LENGTH_VAR_2 (3 << 5)
#define PKT_BIT_LEN(_cfg_) (_cfg_ & 0x1C)
#define UART_MODE_EN BIT(1)
#define UART_SWAP_EN BIT(0)
#define CC1200_REG_RFEND_CFG1 (0x29)
#define RXOFF_MODE(_cfg_) (_cfg_ & 0x30)
#define RX_TIME(_cfg_) (_cfg_ & 0x0E)
#define RX_TIME_QUAL BIT(0)
#define CC1200_REG_RFEND_CFG0 (0x2A)
#define CAL_END_WAKE_UP_EN BIT(6)
#define TXOFF_MODE(_cfg_) (_cfg_ & 0x30)
#define TERM_ON_BAD_PACKET_EN BIT(3)
#define ANT_DIV_RX_TERM_CFG(_cfg_) (_cfg_ & 0x07)
/* Common RFEND tx/rx mode */
#define RFEND_TXRX_MODE_IDLE (0)
#define RFEND_TXRX_MODE_FSTXON (1 << 4)
#define RFEND_TXRX_MODE_TX (2 << 4)
#define RFEND_TXRX_MODE_RX (3 << 4)
#define CC1200_REG_PA_CFG1 (0x2B)
#define PA_RAMP_SHAPE_EN BIT(6)
#define PA_POWER_RAMP_MASK (0x3F)
#define CC1200_REG_PA_CFG0 (0x2C)
#define FIRST_IPL(_cfg_) (_cfg_ & 0xE0)
#define SECOND_IPL(_cfg_) (_cfg_ & 0x1C)
#define RAMP_SHAPE(_cfg_) (_cfg_ & 0x03)
#define CC1200_REG_ASK_CFG (0x2D)
#define AGC_ASK_BW(_cfg_) (_cfg_ & 0xC0)
#define ASK_DEPTH(_cfg_) (_cfg_ & 0x3F)
#define CC1200_REG_PKT_LEN (0x2E)
#define CC1200_REG_EXTENDED_ADDRESS (0x2F)
/* Command strobes */
#define CC1200_INS_SRES (0x30)
#define CC1200_INS_SFSTXON (0x31)
#define CC1200_INS_SXOFF (0x32)
#define CC1200_INS_SCAL (0x33)
#define CC1200_INS_SRX (0x34)
#define CC1200_INS_STX (0x35)
#define CC1200_INS_SIDLE (0x36)
#define CC1200_INS_SAFC (0x37)
#define CC1200_INS_SWOR (0x38)
#define CC1200_INS_SPWD (0x39)
#define CC1200_INS_SFRX (0x3A)
#define CC1200_INS_SFTX (0x3B)
#define CC1200_INS_SWORRST (0x3C)
#define CC1200_INS_SNOP (0x3D)
/* Memory access */
#define CC1200_MEM_DMA (0x3E)
#define CC1200_MEM_STD (0x3F)
/* FIFO access */
#define CC1200_REG_TXFIFO (0x3F)
#define CC1200_REG_RXFIFO (0x3F)
/* Configuration registers (Extended register space) */
#define CC1200_REG_IF_MIX_CFG (0x00)
#define CC1200_REG_FREQOFF_CFG (0x01)
#define CC1200_REG_TOC_CFG (0x02)
#define CC1200_REG_MARC_SPARE (0x03)
#define CC1200_REG_ECG_CFG (0x04)
#define CC1200_REG_MDMCFG2 (0x05)
#define CC1200_REG_EXT_CTRL (0x06)
#define CC1200_REG_RCCAL_FINE (0x07)
#define CC1200_REG_RCCAL_COARSE (0x08)
#define CC1200_REG_RCCAL_OFFSET (0x09)
#define CC1200_REG_FREQOFF1 (0x0A)
#define CC1200_REG_FREQOFF0 (0x0B)
#define CC1200_REG_FREQ2 (0x0C)
#define CC1200_REG_FREQ1 (0x0D)
#define CC1200_REG_FREQ0 (0x0E)
#define CC1200_REG_IF_ADC2 (0x0F)
#define CC1200_REG_IF_ADC1 (0x10)
#define CC1200_REG_IF_ADC0 (0x11)
#define CC1200_REG_FS_DIG1 (0x12)
#define CC1200_REG_FS_DIG0 (0x13)
#define CC1200_REG_FS_CAL3 (0x14)
#define CC1200_REG_FS_CAL2 (0x15)
#define CC1200_REG_FS_CAL1 (0x16)
#define CC1200_REG_FS_CAL0 (0x17)
#define CC1200_REG_FS_CHP (0x18)
#define CC1200_REG_FS_DIVTWO (0x19)
#define CC1200_REG_FS_DSM1 (0x1A)
#define CC1200_REG_FS_DSM0 (0x1B)
#define CC1200_REG_FS_DVC1 (0x1C)
#define CC1200_REG_FS_DVC0 (0x1D)
#define CC1200_REG_FS_LBI (0x1E)
#define CC1200_REG_FS_PFD (0x1F)
#define CC1200_REG_FS_PRE (0x20)
#define CC1200_REG_FS_REG_DIV_CML (0x21)
#define CC1200_REG_FS_SPARE (0x22)
#define CC1200_REG_FS_VCO4 (0x23)
#define CC1200_REG_FS_VCO3 (0x24)
#define CC1200_REG_FS_VCO2 (0x25)
#define CC1200_REG_FS_VCO1 (0x26)
#define CC1200_REG_FS_VCO0 (0x27)
#define CC1200_REG_GBIAS6 (0x28)
#define CC1200_REG_GBIAS5 (0x29)
#define CC1200_REG_GBIAS4 (0x2A)
#define CC1200_REG_GBIAS3 (0x2B)
#define CC1200_REG_GBIAS2 (0x2C)
#define CC1200_REG_GBIAS1 (0x2D)
#define CC1200_REG_GBIAS0 (0x2E)
#define CC1200_REG_IFAMP (0x2F)
#define CC1200_REG_LNA (0x30)
#define CC1200_REG_RXMIX (0x31)
#define CC1200_REG_XOSC5 (0x32)
#define CC1200_REG_XOSC4 (0x33)
#define CC1200_REG_XOSC3 (0x34)
#define CC1200_REG_XOSC2 (0x35)
#define CC1200_REG_XOSC1 (0x36)
#define CC1200_REG_XOSC0 (0x37)
#define CC1200_REG_ANALOG_SPARE (0x38)
#define CC1200_REG_PA_CFG3 (0x39)
/* All addresses in between are unused ones */
#define CC1200_REG_WOR_TIME1 (0x64)
#define CC1200_REG_WOR_TIME0 (0x65)
#define CC1200_REG_WOR_CAPTURE1 (0x66)
#define CC1200_REG_WOR_CAPTURE0 (0x67)
#define CC1200_REG_BIST (0x68)
#define CC1200_REG_DCFILTOFFSET_I1 (0x69)
#define CC1200_REG_DCFILTOFFSET_I0 (0x6A)
#define CC1200_REG_DCFILTOFFSET_Q1 (0x6B)
#define CC1200_REG_DCFILTOFFSET_Q0 (0x6C)
#define CC1200_REG_IQIE_I1 (0x6D)
#define CC1200_REG_IQIE_I0 (0x6E)
#define CC1200_REG_IQIE_Q1 (0x6F)
#define CC1200_REG_IQIE_Q0 (0x70)
#define CC1200_REG_RSSI1 (0x71)
#define CC1200_REG_RSSI0 (0x72)
#define RSSI(_reg_) ((_reg_ & 0x78) >> 3)
#define CARRIER_SENSE BIT(2)
#define CARRIER_SENSE_VALID BIT(1)
#define RSSI_VALID BIT(0)
#define CC1200_REG_MARCSTATE (0x73)
#define CC1200_REG_LQI_VAL (0x74)
#define CC1200_REG_PQT_SYNC_ERR (0x75)
#define CC1200_REG_DEM_STATUS (0x76)
#define CC1200_REG_FREQOFF_EST1 (0x77)
#define CC1200_REG_FREQOFF_EST0 (0x78)
#define CC1200_REG_AGC_GAIN3 (0x79)
#define CC1200_REG_AGC_GAIN2 (0x7A)
#define CC1200_REG_AGC_GAIN1 (0x7B)
#define CC1200_REG_AGC_GAIN0 (0x7C)
#define CC1200_REG_CFM_RX_DATA_OUT (0x7D)
#define CC1200_REG_CFM_RX_DATA_IN (0x7E)
#define CC1200_REG_ASK_SOFT_RX_DATA (0x7F)
#define CC1200_REG_RNDGEN (0x80)
#define CC1200_REG_MAGN2 (0x81)
#define CC1200_REG_MAGN1 (0x82)
#define CC1200_REG_MAGN0 (0x83)
#define CC1200_REG_ANG1 (0x84)
#define CC1200_REG_ANG0 (0x85)
#define CC1200_REG_CHFILT_I2 (0x86)
#define CC1200_REG_CHFILT_I1 (0x87)
#define CC1200_REG_CHFILT_I0 (0x88)
#define CC1200_REG_CHFILT_Q2 (0x89)
#define CC1200_REG_CHFILT_Q1 (0x8A)
#define CC1200_REG_CHFILT_Q0 (0x8B)
#define CC1200_REG_GPIO_STATUS (0x8C)
#define CC1200_REG_FSCAL_CTRL (0x8D)
#define CC1200_REG_PHASE_ADJUST (0x8E)
#define CC1200_REG_PARTNUMBER (0x8F)
#define CC1200_REG_PARTVERSION (0x90)
#define CC1200_REG_SERIAL_STATUS (0x91)
#define CC1200_REG_MODEM_STATUS1 (0x92)
#define CC1200_REG_MODEM_STATUS0 (0x93)
#define CC1200_REG_MARC_STATUS1 (0x94)
#define CC1200_REG_MARC_STATUS0 (0x95)
#define CC1200_REG_PA_IFAMP_TEST (0x96)
#define CC1200_REG_FSRF_TEST (0x97)
#define CC1200_REG_PRE_TEST (0x98)
#define CC1200_REG_PRE_OVR (0x99)
#define CC1200_REG_ADC_TEST (0x9A)
#define CC1200_REG_DVC_TEST (0x9B)
#define CC1200_REG_ATEST (0x9C)
#define CC1200_REG_ATEST_LVDS (0x9D)
#define CC1200_REG_ATEST_MODE (0x9E)
#define CC1200_REG_XOSC_TEST1 (0x9F)
#define CC1200_REG_XOSC_TEST0 (0xA0)
#define CC1200_REG_AES (0xA1)
#define CC1200_REG_MDM_TEST (0xA2)
/* All addresses in between are unused ones */
#define CC1200_REG_RXFIRST (0xD2)
#define CC1200_REG_TXFIRST (0xD3)
#define CC1200_REG_RXLAST (0xD4)
#define CC1200_REG_TXLAST (0xD5)
#define CC1200_REG_NUM_TXBYTES (0xD6)
#define CC1200_REG_NUM_RXBYTES (0xD7)
#define CC1200_REG_FIFO_NUM_TXBYTES (0xD8)
#define CC1200_REG_FIFO_NUM_RXBYTES (0xD9)
#define CC1200_REG_RXFIFO_PRE_BUF (0xDA)
/* All addresses in between are unused ones */
#define CC1200_REG_AES_WORKSPACE (0xE0)
/* Useful values
***************
*/
/* GPIO signals - See Section 3.4.1.1
* Note: some signals are only available on certain GPIO
* thus the number CC1200_GPIOn_(...) on some which
* tells the GPIO line where that signal is valid.
*/
#define CC1200_GPIO_SIG_RXFIFO_THR (0)
#define CC1200_GPIO_SIG_RXFIFO_THR_PKT (1)
#define CC1200_GPIO_SIG_TXFIFO_THR (2)
#define CC1200_GPIO_SIG_TXFIFO_THR_PKT (3)
#define CC1200_GPIO_SIG_RXFIFO_OVERFLOW (4)
#define CC1200_GPIO_SIG_TXFIFO_UNDERFLOW (5)
#define CC1200_GPIO_SIG_PKT_SYNC_RXTX (6)
#define CC1200_GPIO_SIG_CRC_OK (7)
#define CC1200_GPIO_SIG_SERIAL_CLK (8)
#define CC1200_GPIO_SIG_SERIAL_RX (9)
#define CC1200_GPIO_SIG_PQT_REACHED (11)
#define CC1200_GPIO_SIG_PQT_VALID (12)
#define CC1200_GPIO_SIG_RSSI_VALID (13)
#define CC1200_GPIO3_SIG_RSSI_UPDATE (14)
#define CC1200_GPIO2_SIG_RSSI_UPDATE (14)
#define CC1200_GPIO1_SIG_AGC_HOLD (14)
#define CC1200_GPIO0_SIG_AGC_UPDATE (14)
#define CC1200_GPIO3_SIG_CCA_STATUS (15)
#define CC1200_GPIO2_SIG_TXONCCA_DONE (15)
#define CC1200_GPIO1_SIG_CCA_STATUS (15)
#define CC1200_GPIO0_SIG_TXONCCA_FAILED (15)
#define CC1200_GPIO_SIG_CARRIER_SENSE_VALID (16)
#define CC1200_GPIO_SIG_CARRIER_SENSE (17)
#define CC1200_GPIO3_SIG_DSSS_CLK (18)
#define CC1200_GPIO2_SIG_DSSS_DATA0 (18)
#define CC1200_GPIO1_SIG_DSSS_CLK (18)
#define CC1200_GPIO0_SIG_DSSS_DATA1 (18)
#define CC1200_GPIO_SIG_PKT_CRC_OK (19)
#define CC1200_GPIO_SIG_MCU_WAKEUP (20)
#define CC1200_GPIO_SIG_SYNC_LOW0_HIGH1 (21)
#define CC1200_GPIO0_SIG_AES_COMMAND_ACTIVE (22)
#define CC1200_GPIO_SIG_LNA_PA_REG_PD (23)
#define CC1200_GPIO_SIG_LNA_PD (24)
#define CC1200_GPIO_SIG_PA_PD (25)
#define CC1200_GPIO_SIG_RX0TX1_CFG (26)
#define CC1200_GPIO_SIG_IMAGE_FOUND (28)
#define CC1200_GPIO_SIG_CLKEN_CFM (29)
#define CC1200_GPIO_SIG_CFM_TX_DATA_CLK (30)
#define CC1200_GPIO_SIG_RSSI_STEP_FOUND (33)
#define CC1200_GPIO3_SIG_AES_RUN (34)
#define CC1200_GPIO2_SIG_AES_RUN (34)
#define CC1200_GPIO1_SIG_RSSI_STEP_EVENT (34)
#define CC1200_GPIO0_SIG_RSSI_STEP_EVENT (34)
#define CC1200_GPIO1_SIG_LOCK (35)
#define CC1200_GPIO0_SIG_LOCK (35)
#define CC1200_GPIO_SIG_ANTENNA_SELECT (36)
#define CC1200_GPIO_SIG_MARC_2PIN_STATUS_1 (37)
#define CC1200_GPIO_SIG_MARC_2PIN_STATUS_0 (38)
#define CC1200_GPIO2_SIG_TXFIFO_OVERFLOW (39)
#define CC1200_GPIO0_SIG_RXFIFO_UNDERFLOW (39)
#define CC1200_GPIO3_SIG_MAGN_VALID (40)
#define CC1200_GPIO2_SIG_CHFILT_VALID (40)
#define CC1200_GPIO1_SIG_RCC_CAL_VALID (40)
#define CC1200_GPIO0_SIG_CHFILT_STARTUP_VALID (40)
#define CC1200_GPIO3_SIG_COLLISION_FOUND (41)
#define CC1200_GPIO2_SIG_SYNC_EVENT (41)
#define CC1200_GPIO1_SIG_COLLISION_FOUND (41)
#define CC1200_GPIO0_SIG_COLLISION_EVENT (41)
#define CC1200_GPIO_SIG_PA_RAMP_UP (42)
#define CC1200_GPIO3_SIG_CRC_FAILED (43)
#define CC1200_GPIO2_SIG_LENGTH_FAILED (43)
#define CC1200_GPIO1_SIG_ADDR_FAILED (43)
#define CC1200_GPIO0_SIG_UART_FRAMING_ERROR (43)
#define CC1200_GPIO_SIG_AGC_STABLE_GAIN (44)
#define CC1200_GPIO_SIG_AGC_UPDATE (45)
#define CC1200_GPIO3_SIG_ADC_CLOCK (46)
#define CC1200_GPIO2_SIG_ADC_Q_DATA_SAMPLE (46)
#define CC1200_GPIO1_SIG_ADC_CLOCK (46)
#define CC1200_GPIO0_SIG_ADC_I_DATA_SAMPLE (46)
#define CC1200_GPIO_SIG_HIGHZ (48)
#define CC1200_GPIO_SIG_EXT_CLOCK (49)
#define CC1200_GPIO_SIG_CHIP_RDYn (50)
#define CC1200_GPIO_SIG_HW0 (51)
#define CC1200_GPIO_SIG_CLOCK_40K (54)
#define CC1200_GPIO_SIG_WOR_EVENT0 (55)
#define CC1200_GPIO_SIG_WOR_EVENT1 (56)
#define CC1200_GPIO_SIG_WOR_EVENT2 (57)
#define CC1200_GPIO_SIG_XOSC_STABLE (59)
#define CC1200_GPIO_SIG_EXT_OSC_EN (60)
/* Chip status - See Section 3.1.2 */
#define CC1200_STATUS_CHIP_NOT_READY BIT(7)
#define CC1200_STATUS_IDLE (0x00)
#define CC1200_STATUS_RX (0x01 << 4)
#define CC1200_STATUS_TX (0x02 << 4)
#define CC1200_STATUS_FSTXON (0x03 << 4)
#define CC1200_STATUS_CALIBRATE (0x04 << 4)
#define CC1200_STATUS_SETTLING (0x05 << 4)
#define CC1200_STATUS_RX_FIFO_ERROR (0x06 << 4)
#define CC1200_STATUS_TX_FIFO_ERROR (0x07 << 4)
#define CC1200_STATUS_MASK (0x70)
/* Appended FCS - See Section 8 */
#define CC1200_FCS_LEN (2)
#define CC1200_FCS_CRC_OK BIT(7)
#define CC1200_FCS_LQI_MASK (0x7F)
/* ToDo: supporting 802.15.4g will make this header of a different size */
#define CC1200_PHY_HDR_LEN (1)
#endif /* __IEEE802154_CC1200_REGS_H__ */

View file

@ -0,0 +1,358 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __IEEE802154_CC1200_RF_H__
#define __IEEE802154_CC1200_RF_H__
#include <ieee802154/cc1200.h>
#define CC1200_RF_NON_EXT_SPACE_REGS 42
#define CC1200_RF_EXT_SPACE_REGS 58
/* About PKTCFGn from Kconfig:
* CONFIG_IEEE802154_CC1200_PKTCFG0 LENGTH_VAR_1
* CONFIG_IEEE802154_CC1200_PKTCFG1 (APPEND_STATUS | CRC_FFFF | ADDR_NO_CHK)
* We do not enable 802.15.4g mode yet:
* CONFIG_IEEE802154_CC1200_PKTCFG2 (PKT_FORMAT_NORMAL_MODE | CCA_ALWAYS_CLEAR)
**/
#ifdef CONFIG_IEEE802154_CC1200_RF_PRESET
#if defined(CONFIG_IEEE802154_CC1200_RF_SET_0)
const struct cc1200_rf_registers_set cc1200_rf_settings = {
.chan_center_freq0 = 863125,
.channel_limit = 33,
.channel_spacing = 2000, /* 200 KHz */
.registers = {
0x6F, /* SYNC3 */
0x4E,
0x90,
0x4E,
0xE5,
0x23,
0x47,
0x0B,
0x56,
0x19, /* 0x14 */
0xBA,
0xC8,
0x84,
0x42,
0x05,
0x94,
0x7A,
0xE1,
0x27,
CONFIG_IEEE802154_CC1200_CCA_THRESHOLD,
CONFIG_IEEE802154_CC1200_RSSI_OFFSET,
0xB1,
0x20,
0x11,
0x90,
0x00,
0x00,
CONFIG_IEEE802154_CC1200_SETTLING_CFG,
0x12,
0x08,
0x21,
0x00,
0x00,
0x00,
CONFIG_IEEE802154_CC1200_PKTCFG2,
CONFIG_IEEE802154_CC1200_PKTCFG1,
CONFIG_IEEE802154_CC1200_PKTCFG0,
CONFIG_IEEE802154_CC1200_RFEND_CFG1,
CONFIG_IEEE802154_CC1200_RFEND_CFG0,
0x7F,
0x56,
0x0F, /* ASK_CFG */
0x18, /* IF_MIX_CFG */
0x20,
0x03,
0x00,
0x00,
0x02,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x56,
0xCC,
0xCC,
0x02,
0xEE,
0x10,
0x04,
0x50,
0x00,
0x20,
0x40,
0x0E,
0x28,
0x03,
0x00,
0x33,
0xF7,
0x0F,
0x00,
0x00,
0x6E,
0x1C,
0xAC,
0x14,
0x00,
0x00,
0x00,
0xB5,
0x00,
0x02,
0x00,
0x00,
0x10,
0x00,
0x00,
0x05,
0x01,
0x01,
0x0E,
0xA0,
0x03,
0x04,
0x03,
0x00,
0x00,
0x00, /* PA_CFG3 */
}
};
#elif defined(CONFIG_IEEE802154_CC1200_RF_SET_1)
const struct cc1200_rf_registers_set cc1200_rf_settings = {
.chan_center_freq0 = 920600,
.channel_limit = 38,
.channel_spacing = 2000, /* 200 KHz */
.registers = {
0x6F, /* SYNC3 */
0x4E,
0x90,
0x4E,
0xE5,
0x23,
0x47,
0x0B,
0x56,
0x14,
0xBA,
0xC8,
0x84,
0x42,
0x05,
0x94,
0x7A,
0xE1,
0x27,
CONFIG_IEEE802154_CC1200_CCA_THRESHOLD,
CONFIG_IEEE802154_CC1200_RSSI_OFFSET,
0xB1,
0x20,
0x11,
0x90,
0x00,
0x00,
CONFIG_IEEE802154_CC1200_SETTLING_CFG,
0x12,
0x08,
0x21,
0x00,
0x00,
0x00,
CONFIG_IEEE802154_CC1200_PKTCFG2,
CONFIG_IEEE802154_CC1200_PKTCFG1,
CONFIG_IEEE802154_CC1200_PKTCFG0,
CONFIG_IEEE802154_CC1200_RFEND_CFG1,
CONFIG_IEEE802154_CC1200_RFEND_CFG0
0x7F,
0x56,
0x0F, /* ASK_CFG */
0x18, /* IF_MIX_CFG */
0x20,
0x03,
0x00,
0x00,
0x02,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x5C,
0x0F,
0x5C,
0x02,
0xEE,
0x10,
0x04,
0x55,
0x00,
0x20,
0x40,
0x0E,
0x28,
0x03,
0x00,
0x33,
0xFF,
0x17,
0x00,
0x00,
0x6E,
0x1C,
0xAC,
0x14,
0x00,
0x00,
0x00,
0xB5,
0x00,
0x02,
0x00,
0x00,
0x10,
0x00,
0x00,
0x05,
0x01,
0x01,
0x0E,
0xA0,
0x03,
0x04,
0x03,
0x00,
0x00,
0x00, /* PA_CFG3 */
}
};
#elif defined(CONFIG_IEEE802154_CC1200_RF_SET_2)
const struct cc1200_rf_registers_set cc1200_rf_settings = {
.chan_center_freq0 = 433164,
.channel_limit = 14,
.channel_spacing = 2000, /* 200 KHz */
.registers = {
0x6F, /* SYNC3 */
0x4E,
0x90,
0x4E,
0xE5,
0x23,
0x47,
0x0B,
0x56,
0x14,
0xBA,
0xC8,
0x84,
0x42,
0x05,
0x94,
0x7A,
0xE1,
0x27,
CONFIG_IEEE802154_CC1200_CCA_THRESHOLD,
CONFIG_IEEE802154_CC1200_RSSI_OFFSET,
0xB1,
0x20,
0x11,
0x90,
0x00,
0x00,
CONFIG_IEEE802154_CC1200_SETTLING_CFG,
0x14,
0x08,
0x21,
0x00,
0x00,
0x00,
CONFIG_IEEE802154_CC1200_PKTCFG2,
CONFIG_IEEE802154_CC1200_PKTCFG1,
CONFIG_IEEE802154_CC1200_PKTCFG0,
CONFIG_IEEE802154_CC1200_RFEND_CFG1,
CONFIG_IEEE802154_CC1200_RFEND_CFG0,
0x7F,
0x56,
0x0F, /* ASK_CFG */
0x18, /* IF_MIX_CFG */
0x20,
0x03,
0x00,
0x00,
0x02,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x56,
0xCC,
0xCC,
0x02,
0xEE,
0x10,
0x04,
0x50,
0x00,
0x20,
0x40,
0x0E,
0x28,
0x03,
0x00,
0x33,
0xF7,
0x0F,
0x00,
0x00,
0x6E,
0x1C,
0xAC,
0x14,
0x00,
0x00,
0x00,
0xB5,
0x00,
0x02,
0x00,
0x00,
0x10,
0x00,
0x00,
0x05,
0x01,
0x01,
0x0E,
0xA0,
0x03,
0x04,
0x03,
0x00,
0x00,
0x00, /* PA_CFG3 */
}
};
#endif /* CONFIG_IEEE802154_CC1200_RF_SET_n */
#endif /* CONFIG_IEEE802154_CC1200_RF_PRESET */
#endif /* __IEEE802154_CC1200_RF_H__ */

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __CC1200_H__
#define __CC1200_H__
#include <device.h>
/* RF settings
*
* First 42 entries are for the 42 first registers from
* address 0x04 to 0x2D included.
* Next, the last 58 entries are for the 58 registers from
* extended address 0x00 to 0x39 included
*
* If CONFIG_IEEE802154_CC1200_RF_PRESET is not used, one will need
* no provide 'cc1200_rf_settings' with proper settings. These can
* be generated through TI's SmartRF application.
*
*/
struct cc1200_rf_registers_set {
u32_t chan_center_freq0;
u16_t channel_limit;
/* to fit in u16_t, spacing is a multiple of 100 Hz,
* 12.5KHz for instance will be 125.
*/
u16_t channel_spacing;
u8_t registers[100];
};
#ifndef CONFIG_IEEE802154_CC1200_RF_PRESET
extern const struct cc1200_rf_registers_set cc1200_rf_settings;
#endif
/* Note for EMK & EM adapter booster pack users:
* SPI pins are easy, RESET as well, but when it comes to GPIO:
* CHIP -> EM adapter
* GPIO0 -> GPIOA
* GPIO1 -> reserved (it's SPI MISO)
* GPIO2 -> GPIOB
* GPIO3 -> GPIO3
*/
enum cc1200_gpio_index {
CC1200_GPIO_IDX_GPIO0,
CC1200_GPIO_IDX_MAX,
};
struct cc1200_gpio_configuration {
struct device *dev;
u32_t pin;
};
struct cc1200_gpio_configuration *cc1200_configure_gpios(void);
#endif /* __CC1200_H__ */