mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
473 lines
15 KiB
C
473 lines
15 KiB
C
/*
|
|
* Copyright (C) 2016 MUTEX NZ Ltd.
|
|
* Copyright (C) 2015 Loci Controls Inc.
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @ingroup cpu_cc2538
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Low-level radio driver for the CC2538
|
|
*
|
|
* @author Aaron Sowry <aaron@mutex.nz>
|
|
* @author Ian Martin <ian@locicontrols.com>
|
|
*/
|
|
|
|
#ifndef CC2538_RF_H
|
|
#define CC2538_RF_H
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "board.h"
|
|
#include "cc2538_rfcore.h"
|
|
|
|
#include "net/ieee802154.h"
|
|
#include "kernel_defines.h"
|
|
|
|
#include "net/ieee802154/radio.h"
|
|
|
|
#include "net/netopt.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define CC2538_AUTOCRC_LEN (2)
|
|
#define CC2538_RF_FIFO_SIZE (128)
|
|
#define CC2538_PACKET_LENGTH_SIZE (1)
|
|
#define CC2538_LENGTH_BYTE_MASK (0x7F) /**< Mask for the length byte in the packet */
|
|
|
|
#define CC2538_RF_MAX_DATA_LEN (CC2538_RF_FIFO_SIZE - CC2538_PACKET_LENGTH_SIZE)
|
|
|
|
/* TODO: Move these to sys/include/net/ieee802154.h somehow */
|
|
/* IEEE 802.15.4 defined constants (2.4 GHz logical channels) */
|
|
#define IEEE802154_MIN_FREQ (2405) /**< Min. frequency (2405 MHz) */
|
|
#define IEEE802154_MAX_FREQ (2480) /**< Max. frequency (2480 MHz) */
|
|
|
|
#define IEEE802154_CHANNEL_SPACING (5) /**< Channel spacing in MHz */
|
|
|
|
#define IEEE802154_CHAN2FREQ(chan) ( IEEE802154_MIN_FREQ + ((chan) - IEEE802154_CHANNEL_MIN) * IEEE802154_CHANNEL_SPACING )
|
|
#define IEEE802154_FREQ2CHAN(freq) ( IEEE802154_CHANNEL_MIN + ((freq) - IEEE802154_MIN_FREQ) / IEEE802154_CHANNEL_SPACING )
|
|
/* /TODO */
|
|
|
|
#define CC2538_MIN_FREQ (2394)
|
|
#define CC2538_MAX_FREQ (2507)
|
|
|
|
#define CC2538_RF_POWER_DEFAULT (CONFIG_IEEE802154_DEFAULT_TXPOWER) /**< Default output power in dBm */
|
|
#define CC2538_RF_CHANNEL_DEFAULT (CONFIG_IEEE802154_DEFAULT_CHANNEL)
|
|
|
|
#define OUTPUT_POWER_MIN (-24) /**< Min output power in dBm */
|
|
#define OUTPUT_POWER_MAX (7) /**< Max output power in dBm */
|
|
#define NUM_POWER_LEVELS ( OUTPUT_POWER_MAX - OUTPUT_POWER_MIN + 1 )
|
|
|
|
#define CC2538_CORR_VAL_MIN (50U)
|
|
#define CC2538_CORR_VAL_MAX (110U)
|
|
#define CC2538_CORR_VAL_MASK (0x7F)
|
|
|
|
#define CC2538_CRC_BIT_MASK (0x80)
|
|
|
|
#define CC2538_CCA_THR_MASK (0x000000FF) /**< CCA Threshold mask */
|
|
|
|
#define CC2538_CCA_MODE_MASK (0x18) /**< CCA Mode mask */
|
|
#define CC2538_CCA_MODE_POS (3U) /**< CCA Mode pos */
|
|
|
|
#define CC2538_CSP_SKIP_INST_MASK (0x70) /**< CSP Skip instruction mask */
|
|
#define CC2538_CSP_SKIP_INST_POS (4U) /**< CSP Skip instruction pos */
|
|
|
|
#define CC2538_CSP_SKIP_N_MASK (0x08) /**< CSP Skip condition negation mask */
|
|
|
|
#define CC2538_CSP_SKIP_COND_CCA (0x00) /**< CSP Skip condition is valid CCA */
|
|
#define CC2538_CSP_SKIP_COND_CSPZ (0x06) /**< CSP Skip condition is CSPZ is 0 */
|
|
#define CC2538_CSP_SKIP_COND_RSSI (0x07) /**< CSP Skip condition is valid RSSI */
|
|
|
|
#define CC2538_SFR_MTMSEL_MASK (0x7) /**< MAC Timer selection mask */
|
|
#define CC2538_SFR_MTMSEL_TIMER_P (0x2) /**< Selects Timer period */
|
|
#define CC2538_MCTRL_SYNC_MASK (0x2) /**< Sync MAC Timer to external clock */
|
|
#define CC2538_MCTRL_RUN_MASK (0x1) /**< Run MAC Timer */
|
|
|
|
#define CC2538_CSP_MCU_CTRL_MASK (0x1) /**< MCU Ctrl mask */
|
|
|
|
#define CC2538_CSP_INCMAXY_MAX_MASK (0x7) /**< CSP INCMAXY instruction (increment Register CSPX
|
|
without exceeding CSPY) */
|
|
|
|
#define CC2538_RXENABLE_RXON_MASK (0x80) /**< RX on mask */
|
|
|
|
#define CC2538_RSSI_OFFSET (-73) /**< Signal strength offset value */
|
|
#define CC2538_RF_SENSITIVITY (-97) /**< dBm typical, normal conditions */
|
|
|
|
#define CC2538_ACCEPT_FT_0_BEACON (1 << 3) /**< enable or disable the BEACON filter */
|
|
#define CC2538_ACCEPT_FT_1_DATA (1 << 4) /**< enable or disable the DATA filter */
|
|
#define CC2538_ACCEPT_FT_2_ACK (1 << 5) /**< enable or disable the ACK filter */
|
|
#define CC2538_ACCEPT_FT_3_CMD (1 << 6) /**< enable or disable the CMD filter */
|
|
#define CC2538_STATE_SFD_WAIT_RANGE_MIN (0x03U) /**< min range value of SFD wait state */
|
|
#define CC2538_STATE_SFD_WAIT_RANGE_MAX (0x06U) /**< max range value of SFD wait state */
|
|
#define CC2538_FRMCTRL1_PENDING_OR_MASK (0x04) /**< mask for enabling or disabling the
|
|
frame pending bit */
|
|
#define CC2538_FRMCTRL0_RX_MODE_DIS (0xC) /**< mask for disabling RX Chain during
|
|
CCA */
|
|
|
|
#define RFCORE_ASSERT(expr) (void)( (expr) || RFCORE_ASSERT_failure(#expr, __FUNCTION__, __LINE__) )
|
|
|
|
#if DEVELHELP
|
|
#define RFCORE_WAIT_UNTIL(expr) while (!(expr)) { \
|
|
DEBUG("RFCORE_WAIT_UNTIL(%s) at line %u in %s()\n", #expr, __LINE__, __FUNCTION__); \
|
|
thread_yield(); \
|
|
}
|
|
#else
|
|
#define RFCORE_WAIT_UNTIL(expr) while (!(expr)) thread_yield()
|
|
#endif
|
|
|
|
#define RFCORE_FLUSH_RECEIVE_FIFO() rfcore_strobe(ISFLUSHRX)
|
|
|
|
#define ABS_DIFF(x, y) ( ((x) < (y))? ((y) - (x)) : ((x) - (y)) )
|
|
#define BOOLEAN(x) ( (x) != 0 )
|
|
#define NOT(x) ( (x) == 0 )
|
|
#define GET_BYTE(buffer, index) ( (unsigned char*)(buffer) )[index]
|
|
|
|
#define BIT(n) ( 1 << (n) )
|
|
|
|
enum {
|
|
FSM_STATE_IDLE = 0,
|
|
FSM_STATE_RX_CALIBRATION = 2,
|
|
FSM_STATE_TX_CALIBRATION = 32,
|
|
};
|
|
|
|
/**
|
|
* @brief RFCORE_XREG_RFERRM bits
|
|
*/
|
|
enum {
|
|
STROBE_ERR = BIT(6),
|
|
TXUNDERF = BIT(5),
|
|
TXOVERF = BIT(4),
|
|
RXUNDERF = BIT(3),
|
|
RXOVERF = BIT(2),
|
|
RXABO = BIT(1),
|
|
NLOCK = BIT(0),
|
|
};
|
|
|
|
/**
|
|
* @brief RFCORE_XREG_FRMCTRL0 bits
|
|
*/
|
|
enum {
|
|
SET_RXENMASK_ON_TX = BIT(0),
|
|
IGNORE_TX_UNDERF = BIT(1),
|
|
PENDING_OR = BIT(2),
|
|
};
|
|
|
|
/**
|
|
* @brief RFCORE_XREG_FRMCTRL1 bits
|
|
*/
|
|
enum {
|
|
ENERGY_SCAN = BIT(4),
|
|
AUTOACK = BIT(5),
|
|
AUTOCRC = BIT(6),
|
|
APPEND_DATA_MODE = BIT(7),
|
|
};
|
|
|
|
/**
|
|
* @brief RFCORE_XREG_RFIRQM0 / RFCORE_XREG_RFIRQF0 bits
|
|
*/
|
|
enum {
|
|
ACT_UNUSED = BIT(0),
|
|
SFD = BIT(1), /**< Start of frame event */
|
|
FIFOP = BIT(2),
|
|
SRC_MATCH_DONE = BIT(3),
|
|
SRC_MATCH_FOUND = BIT(4),
|
|
FRAME_ACCEPTED = BIT(5),
|
|
RXPKTDONE = BIT(6), /**< End of frame event */
|
|
RXMASKZERO = BIT(7),
|
|
};
|
|
|
|
/**
|
|
* @brief RFCORE_XREG_RFIRQM1 / RFCORE_XREG_RFIRQF1 bits
|
|
*/
|
|
enum {
|
|
TXACKDONE = BIT(0),
|
|
TXDONE = BIT(1),
|
|
RF_IDLE = BIT(2),
|
|
CSP_MANINT = BIT(3),
|
|
CSP_STOP = BIT(4),
|
|
CSP_WAIT = BIT(5),
|
|
};
|
|
|
|
/**
|
|
* @brief Values for use with CCTEST_OBSSELx registers.
|
|
*/
|
|
enum {
|
|
rfc_obs_sig0 = 0,
|
|
rfc_obs_sig1 = 1,
|
|
rfc_obs_sig2 = 2,
|
|
};
|
|
|
|
/**
|
|
* @brief Values for RFCORE_XREG_RFC_OBS_CTRLx registers.
|
|
*/
|
|
enum {
|
|
constant_value_0 = 0x00, /**< Constant value 0 */
|
|
constant_value_1 = 0x01, /**< Constant value 1*/
|
|
rfc_sniff_data = 0x08, /**< Data from packet sniffer. Sample data
|
|
on rising edges of sniff_clk.*/
|
|
rfc_sniff_clk = 0x09, /**< 250kHz clock for packet sniffer data.*/
|
|
rssi_valid = 0x0c, /**< Pin is high when the RSSI value has
|
|
been updated at least once since RX was
|
|
started. Cleared when leaving RX.*/
|
|
demod_cca = 0x0d, /**< Clear channel assessment. See FSMSTAT1
|
|
register for details on how to configure
|
|
the behavior of this signal. */
|
|
sampled_cca = 0x0e, /**< A sampled version of the CCA bit from
|
|
demodulator. The value is updated whenever
|
|
a SSAMPLECCA or STXONCCA strobe is issued.*/
|
|
sfd_sync = 0x0f, /**< Pin is high when a SFD has been received
|
|
or transmitted. Cleared when leaving
|
|
RX/TX respectively. Not to be confused
|
|
with the SFD exception.*/
|
|
tx_active = 0x10, /**< Indicates that FFCTRL is in one of the TX
|
|
states. Active-high.*/
|
|
rx_active = 0x11, /**< Indicates that FFCTRL is in one of the
|
|
RX states. Active-high. */
|
|
ffctrl_fifo = 0x12, /**< Pin is high when one or more bytes are
|
|
in the RXFIFO. Low during RXFIFO overflow. */
|
|
ffctrl_fifop = 0x13, /**< Pin is high when the number of bytes
|
|
in the RXFIFO exceeds the programmable
|
|
threshold or at least one complete
|
|
frame is in the RXFIFO. Also highduring
|
|
RXFIFO overflow. Not to be confused with
|
|
the FIFOP exception.*/
|
|
packet_done = 0x14, /**< A complete frame has been received.
|
|
I.e., the number of bytes set by the
|
|
frame-length field has been received.*/
|
|
rfc_xor_rand_i_q = 0x16, /**< XOR between I and Q random outputs.
|
|
Updated at 8 MHz.*/
|
|
rfc_rand_q = 0x17, /**< Random data output from the Q channel
|
|
of the receiver. Updated at 8 MHz.*/
|
|
rfc_rand_i = 0x18, /**< Random data output from the I channel
|
|
of the receiver. Updated at 8 MHz */
|
|
lock_status = 0x19, /**< 1 when PLL is in lock, otherwise 0 */
|
|
pa_pd = 0x20, /**< Power amplifier power-down signal */
|
|
lna_pd = 0x2a, /**< LNA power-down signal*/
|
|
disabled = 0xff, /**< disabled */
|
|
};
|
|
|
|
/**
|
|
* @name RF CORE observable signals settings
|
|
*/
|
|
#ifndef CONFIG_CC2538_RF_OBS_0
|
|
#define CONFIG_CC2538_RF_OBS_0 tx_active
|
|
#endif
|
|
#ifndef CONFIG_CC2538_RF_OBS_1
|
|
#define CONFIG_CC2538_RF_OBS_1 rx_active
|
|
#endif
|
|
#ifndef CONFIG_CC2538_RF_OBS_2
|
|
#define CONFIG_CC2538_RF_OBS_2 rssi_valid
|
|
#endif
|
|
|
|
/* Default configuration for cc2538dk or similar */
|
|
#ifndef CONFIG_CC2538_RF_OBS_SIG_0_PCX
|
|
#define CONFIG_CC2538_RF_OBS_SIG_0_PCX 0 /* PC0 = LED_1 (red) */
|
|
#endif
|
|
#ifndef CONFIG_CC2538_RF_OBS_SIG_1_PCX
|
|
#define CONFIG_CC2538_RF_OBS_SIG_1_PCX 1 /* PC0 = LED_2 (red) */
|
|
#endif
|
|
#ifndef CONFIG_CC2538_RF_OBS_SIG_2_PCX
|
|
#define CONFIG_CC2538_RF_OBS_SIG_2_PCX 2 /* PC0 = LED_3 (red) */
|
|
#endif
|
|
#if ((CONFIG_CC2538_RF_OBS_SIG_2_PCX > 7) || \
|
|
(CONFIG_CC2538_RF_OBS_SIG_1_PCX > 7) || \
|
|
(CONFIG_CC2538_RF_OBS_SIG_0_PCX > 7))
|
|
#error "CONFIG_CC2538_RF_OBS_SIG_X_PCX must be between 0-7 (PC0-PC7)"
|
|
#endif
|
|
|
|
/**
|
|
* @brief Device descriptor for CC2538 transceiver
|
|
*/
|
|
typedef struct {
|
|
uint8_t state; /**< current state of the radio */
|
|
} cc2538_rf_t;
|
|
|
|
/**
|
|
* @brief Setup CC2538 in order to be used with the IEEE 802.15.4 Radio HAL
|
|
*
|
|
* @note This functions MUST be called before @ref cc2538_init.
|
|
*
|
|
* @param[in] hal pointer to the HAL descriptor associated to the device.
|
|
*/
|
|
void cc2538_rf_hal_setup(ieee802154_dev_t *hal);
|
|
|
|
/**
|
|
* @brief Enable CC2538 RF IRQs.
|
|
*/
|
|
static inline void cc2538_rf_enable_irq(void)
|
|
{
|
|
RFCORE_XREG_RFIRQM1 = TXDONE | CSP_STOP | TXACKDONE;
|
|
RFCORE_XREG_RFIRQM0 = RXPKTDONE | SFD;
|
|
}
|
|
|
|
/**
|
|
* @brief Disable CC2538 RF IRQs.
|
|
*/
|
|
static inline void cc2538_rf_disable_irq(void)
|
|
{
|
|
RFCORE_XREG_RFIRQM1 = 0;
|
|
RFCORE_XREG_RFIRQM0 = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief IRQ handler for RF events
|
|
*
|
|
*/
|
|
void cc2538_irq_handler(void);
|
|
|
|
/**
|
|
* @brief Trigger a clear channel assessment
|
|
*
|
|
* @return True if channel is clear
|
|
* @return False if channel is busy
|
|
*/
|
|
bool cc2538_channel_clear(void);
|
|
|
|
/**
|
|
* @brief Get the configured long address of the device
|
|
*
|
|
* @param[out] addr The currently set (8-byte) long address
|
|
*/
|
|
void cc2538_get_addr_long(uint8_t *addr);
|
|
|
|
/**
|
|
* @brief Get the configured short address of the device
|
|
*
|
|
* @param[out] addr The currently set (2-byte) short address
|
|
*/
|
|
void cc2538_get_addr_short(uint8_t *addr);
|
|
|
|
/**
|
|
* @brief Get the configured channel number of the device
|
|
*
|
|
* @return The currently set channel number
|
|
*/
|
|
unsigned int cc2538_get_chan(void);
|
|
|
|
/**
|
|
* @brief Check if device is in monitor (promiscuous) mode
|
|
*
|
|
* @return True if device is in monitor mode
|
|
* @return False if device is not in monitor mode
|
|
*/
|
|
bool cc2538_get_monitor(void);
|
|
|
|
/**
|
|
* @brief Get the configured PAN ID of the device
|
|
*
|
|
* @return The currently set PAN ID
|
|
*/
|
|
uint16_t cc2538_get_pan(void);
|
|
|
|
/**
|
|
* @brief Get the configured transmission power of the device
|
|
*
|
|
* @return The currently configured transmission power in dBm
|
|
*/
|
|
int cc2538_get_tx_power(void);
|
|
|
|
/**
|
|
* @brief Initialise the CC2538 radio hardware
|
|
*
|
|
*/
|
|
void cc2538_init(void);
|
|
|
|
/**
|
|
* @brief Check if device is active
|
|
*
|
|
* @return True if device is active
|
|
* @return False if device is not active
|
|
*/
|
|
bool cc2538_is_on(void);
|
|
|
|
/**
|
|
* @brief Deactivate the CC2538 radio device
|
|
*
|
|
*/
|
|
void cc2538_off(void);
|
|
|
|
/**
|
|
* @brief Activate the CC2538 radio device
|
|
*
|
|
*/
|
|
bool cc2538_on(void);
|
|
|
|
/**
|
|
* @brief Setup a CC2538 radio device
|
|
*
|
|
* @param[out] dev Device descriptor
|
|
*/
|
|
void cc2538_setup(cc2538_rf_t *dev);
|
|
|
|
/**
|
|
* @brief Set the short address of the device
|
|
*
|
|
* @param[in] addr (2-byte) short address to set
|
|
*/
|
|
void cc2538_set_addr_short(const uint8_t *addr);
|
|
|
|
/**
|
|
* @brief Set the long address of the device
|
|
*
|
|
* @param[in] addr (8-byte) short address to set
|
|
*/
|
|
void cc2538_set_addr_long(const uint8_t *addr);
|
|
|
|
/**
|
|
* @brief Set the channel number of the device
|
|
*
|
|
* @param[in] chan Channel number to set
|
|
*/
|
|
void cc2538_set_chan(unsigned int chan);
|
|
|
|
/**
|
|
* @brief Set the frequency of the device
|
|
*
|
|
* @param[in] MHz Frequency to set in MHz
|
|
*/
|
|
void cc2538_set_freq(unsigned int MHz);
|
|
|
|
/**
|
|
* @brief Enable/disable monitor (promiscuous) mode for the device
|
|
*
|
|
* @param[in] mode True for enable, false for disable
|
|
*/
|
|
void cc2538_set_monitor(bool mode);
|
|
|
|
/**
|
|
* @brief Set the PAN ID of the device
|
|
*
|
|
* @param[in] pan PAN ID to set
|
|
*/
|
|
void cc2538_set_pan(uint16_t pan);
|
|
|
|
/**
|
|
* @brief Set the state of the device
|
|
*
|
|
* @param[out] dev Device descriptor
|
|
* @param[in] state State to set device to
|
|
*/
|
|
void cc2538_set_state(cc2538_rf_t *dev, netopt_state_t state);
|
|
|
|
/**
|
|
* @brief Set the transmission power for the device
|
|
*
|
|
* @param[in] dBm Transmission power to set in dBm
|
|
*/
|
|
void cc2538_set_tx_power(int dBm);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* CC2538_RF_H */
|
|
/** @} */
|