1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #12277 from benemorius/pr/kw41zrf

drivers: add kw41zrf
This commit is contained in:
benpicco 2020-03-20 00:49:56 +01:00 committed by GitHub
commit 5435792034
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 7181 additions and 5 deletions

View File

@ -2,3 +2,7 @@ ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_adc
USEMODULE += saul_gpio
endif
ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE)))
USEMODULE += kw41zrf
endif

View File

@ -3,7 +3,6 @@ ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
endif
# TODO uncomment after #12277 (add support for kw41zrf) is merged
# ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE)))
# USEMODULE += kw41zrf
# endif
ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE)))
USEMODULE += kw41zrf
endif

View File

@ -340,6 +340,16 @@ ifneq (,$(filter kw2xrf,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio_irq
endif
ifneq (,$(filter kw41zrf,$(USEMODULE)))
USEMODULE += luid
USEMODULE += netif
USEMODULE += ieee802154
USEMODULE += netdev_ieee802154
USEMODULE += core_thread_flags
USEMODULE += random
USEMODULE += mcux_xcvr_mkw41z
endif
ifneq (,$(filter l3g4200d,$(USEMODULE)))
FEATURES_REQUIRED += periph_i2c
endif

View File

@ -180,6 +180,10 @@ ifneq (,$(filter kw2xrf,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/kw2xrf/include
endif
ifneq (,$(filter kw41zrf,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/kw41zrf/include
endif
ifneq (,$(filter l3g4200d,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/l3g4200d/include
endif

170
drivers/include/kw41zrf.h Normal file
View File

@ -0,0 +1,170 @@
/*
* Copyright (C) 2017 SKF AB
*
* 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.
*/
/**
* @defgroup drivers_kw41zrf KW41Z radio-driver
* @ingroup drivers_netdev
* @brief Device driver for the NXP KW41Z, KW21Z in-cpu transceiver
* @{
*
* @file
* @brief Interface definition for the kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef KW41ZRF_H
#define KW41ZRF_H
#include <stdint.h>
#include "mutex.h"
#include "board.h"
#include "net/netdev.h"
#include "net/netdev/ieee802154.h"
#include "net/gnrc/nettype.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Maximum packet length
*/
#define KW41ZRF_MAX_PKT_LENGTH (IEEE802154_FRAME_LEN_MAX)
/**
* @brief Default channel used after initialization
*
* @{
*/
#ifndef KW41ZRF_DEFAULT_CHANNEL
#define KW41ZRF_DEFAULT_CHANNEL (IEEE802154_DEFAULT_CHANNEL)
#endif
/** @} */
/**
* @brief Default CCA threshold
*
* @{
*/
#ifndef KW41ZRF_DEFAULT_CCA_THRESHOLD
#define KW41ZRF_DEFAULT_CCA_THRESHOLD (-60)
#endif
/** @} */
/**
* @brief Default LQI compensation
*
* @{
*/
#ifndef KW41ZRF_DEFAULT_LQI_COMPENSATION
#define KW41ZRF_DEFAULT_LQI_COMPENSATION (102)
#endif
/** @} */
/**
* @brief Allowed range of channels
*
* @{
*/
#define KW41ZRF_MIN_CHANNEL (11U)
#define KW41ZRF_MAX_CHANNEL (26U)
/** @} */
/**
* @brief Default TX_POWER in dbm used after initialization
*/
#define KW41ZRF_DEFAULT_TX_POWER (IEEE802154_DEFAULT_TXPOWER)
/**
* @brief Maximum output power of the kw41z device in dBm
*/
#define KW41ZRF_OUTPUT_POWER_MAX (4)
/**
* @brief Minimum output power of the kw41z device in dBm
*/
#define KW41ZRF_OUTPUT_POWER_MIN (-19)
/**
* @brief ISR callback function type
*/
typedef void (*kw41zrf_cb_t)(void *arg);
/**
* @brief Device descriptor for KW41ZRF radio devices
*
* @extends netdev_ieee802154_t
*/
typedef struct {
netdev_ieee802154_t netdev; /**< netdev parent struct */
/**
* @name device specific fields
* @{
*/
thread_t *thread; /**< Network driver thread, for providing feedback from IRQ handler */
uint32_t tx_warmup_time; /**< TX warmup time, in event timer ticks */
uint32_t rx_warmup_time; /**< RX warmup time, in event timer ticks */
uint32_t rf_osc_en_idle; /**< RF_OSC_EN bits setting when RF module is in standby */
int16_t tx_power; /**< The current tx-power setting of the device */
uint8_t flags; /**< Internal driver option flags */
uint8_t max_retrans; /**< Maximum number of frame retransmissions
* when no Ack frame is received (macMaxFrameRetries) */
uint8_t csma_max_backoffs; /**< Maximum number of CSMA backoffs when
* waiting for channel clear (macMaxCsmaBackoffs) */
uint8_t csma_min_be; /**< Minimum backoff exponent (macMinBe) */
uint8_t csma_max_be; /**< Maximum backoff exponent (macMaxBe) */
uint8_t idle_seq; /**< state to return to after sending */
uint8_t cca_result; /**< Used for passing CCA result from ISR to user */
uint8_t csma_be; /**< Counter used internally by send implementation */
uint8_t csma_num_backoffs; /**< Counter used internally by send implementation */
uint8_t num_retrans; /**< Counter used internally by send implementation */
uint32_t backoff_delay; /**< CSMA delay for the current TX operation */
uint32_t tx_timeout; /**< Used to timeout waiting for ACK during TRX */
uint8_t pm_blocked; /**< true if we have blocked a low power mode in the CPU */
uint8_t recv_blocked; /**< blocks moving to XCVSEQ_RECEIVE to prevent
* overwriting the RX buffer before the higher
* layers have copied it to system RAM */
/** @} */
} kw41zrf_t;
/**
* @brief Setup an KW41ZRF based device state
*
* @param[out] dev device descriptor
*/
void kw41zrf_setup(kw41zrf_t *dev);
/**
* @brief Initialize the given KW41ZRF device
*
* @param[out] dev device descriptor
* @param[in] cb irq callback
*
* @return 0 on success
* @return <0 on error
*/
int kw41zrf_init(kw41zrf_t *dev, kw41zrf_cb_t cb);
/**
* @brief Reset radio hardware and restore default settings
*
* @param[in] dev device to reset
*
* @return 0 on success
* @return <0 on initialization failure
*/
int kw41zrf_reset(kw41zrf_t *dev);
#ifdef __cplusplus
}
#endif
#endif /* KW41ZRF_H */
/** @} */

4
drivers/kw41zrf/Makefile Normal file
View File

@ -0,0 +1,4 @@
# Use vendor-supplied low level XCVR hardware initialization
DIRS += vendor/XCVR/MKW41Z4
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,212 @@
/*
* Copyright (C) 2017 SKF AB
* Copyright (C) 2016 Phytec Messtechnik GmbH
*
* 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 drivers_kw41zrf
* @{
*
* @file
* @brief get/set interfaces for kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef KW41ZRF_GETSET_H
#define KW41ZRF_GETSET_H
#include "kw41zrf.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Internal device option flags
* @{
*/
#define KW41ZRF_OPT_CSMA (0x01u) /**< use CSMA/CA algorithm for sending */
#define KW41ZRF_OPT_PROMISCUOUS (0x02u) /**< promiscuous mode active */
#define KW41ZRF_OPT_PRELOADING (0x04u) /**< preloading enabled */
#define KW41ZRF_OPT_TELL_TX_START (0x08u) /**< notify MAC layer on TX start */
#define KW41ZRF_OPT_TELL_TX_END (0x10u) /**< notify MAC layer on TX finished */
#define KW41ZRF_OPT_TELL_RX_START (0x20u) /**< notify MAC layer on RX start */
#define KW41ZRF_OPT_TELL_RX_END (0x40u) /**< notify MAC layer on RX finished */
#define KW41ZRF_OPT_AUTOACK (0x80u) /**< automatic sending of ACKs */
#define KW41ZRF_OPT_ACK_PENDING (0x81u) /**< set pending bit on auto ACKs */
/** @} */
/** @brief Transceiver sequence identifiers */
enum kw41zrf_xcvseq {
XCVSEQ_IDLE = 0b000,
XCVSEQ_RECEIVE = 0b001,
XCVSEQ_TRANSMIT = 0b010,
XCVSEQ_CCA = 0b011,
XCVSEQ_TX_RX = 0b100,
XCVSEQ_CONTINUOUS_CCA = 0b101,
/* Other values are reserved */
/* Special value for idle_seq when sleeping */
XCVSEQ_DSM_IDLE = 0b1000,
};
/**
* @brief Set tx power of given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] txpower transmit power in dBm
*/
void kw41zrf_set_tx_power(kw41zrf_t *dev, int16_t txpower);
/**
* @brief Get tx power value of given device
*
* @param[in] dev kw41zrf device descriptor
*
* @return current tx power value
*/
int16_t kw41zrf_get_txpower(kw41zrf_t *dev);
/**
* @brief Set channel of given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] val channel
*/
int kw41zrf_set_channel(kw41zrf_t *dev, uint8_t val);
/**
* @brief Get channel of given device
*
* @param[in] dev kw41zrf device descriptor
*
* @return current channel
*/
uint8_t kw41zrf_get_channel(kw41zrf_t *dev);
/**
* @brief Set PAN ID of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] pan PAN ID value
*/
void kw41zrf_set_pan(kw41zrf_t *dev, uint16_t pan);
/**
* @brief Get PAN ID of given device
*
* @param[in] dev kw41zrf device descriptor
*
* @return current PAN ID
*/
uint16_t kw41zrf_get_pan(kw41zrf_t *dev);
/**
* @brief Set short address of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] addr short address
*/
void kw41zrf_set_addr_short(kw41zrf_t *dev, const network_uint16_t *addr);
/**
* @brief Set long address of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] addr long address
*/
void kw41zrf_set_addr_long(kw41zrf_t *dev, const eui64_t *addr);
/**
* @brief Get short address of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[out] addr current short address
*/
void kw41zrf_get_addr_short(kw41zrf_t *dev, network_uint16_t *addr);
/**
* @brief Get long address of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[out] addr current long address
*/
void kw41zrf_get_addr_long(kw41zrf_t *dev, eui64_t *addr);
/**
* @brief Get CCA threshold of a given device
*
* @param[in] dev kw41zrf device descriptor
* @return current CCA threshold
*/
int8_t kw41zrf_get_cca_threshold(kw41zrf_t *dev);
/**
* @brief Set CCA threshold of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] value CCA threshold
*/
void kw41zrf_set_cca_threshold(kw41zrf_t *dev, int8_t value);
/**
* @brief Set CCA mode of a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] mode CCA mode
*/
void kw41zrf_set_cca_mode(kw41zrf_t *dev, uint8_t mode);
/**
* @brief Get CCA mode of a given device
*
* @param[in] dev kw41zrf device descriptor
* @return current CCA mode
*/
uint8_t kw41zrf_get_cca_mode(kw41zrf_t *dev);
/**
* @brief Get latest ED measurement from the device
*
* @param[in] dev kw41zrf device descriptor
* @return most recent ED level
*/
int8_t kw41zrf_get_ed_level(kw41zrf_t *dev);
/**
* @brief Perform one CCA measurement and return the result
*
* @param[in] dev kw41zrf device descriptor
*
* @return 0 if channel is idle
* @return 1 if channel is busy
*/
int kw41zrf_cca(kw41zrf_t *dev);
/**
* @brief Set receive watermark to signal when the packet buffer is part full
*
* @param[in] dev kw41zrf device descriptor
* @param[in] value watermark
*/
void kw41zrf_set_rx_watermark(kw41zrf_t *dev, uint8_t value);
/**
* @brief Set netopt a given device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] option Netopt option type
* @param[in] state state
*/
void kw41zrf_set_option(kw41zrf_t *dev, uint8_t option, uint8_t state);
#ifdef __cplusplus
}
#endif
#endif /* KW41ZRF_GETSET_H */
/** @} */

View File

@ -0,0 +1,293 @@
/*
* Copyright (C) 2017 SKF AB
* Copyright (C) 2016 Phytec Messtechnik GmbH
*
* 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 drivers_kw41zrf
* @{
*
* @file
* @brief Internal function interfaces for kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef KW41ZRF_INTERN_H
#define KW41ZRF_INTERN_H
#include <stdint.h>
#include "kw41zrf.h"
/* For XCVSEQ_IDLE */
#include "kw41zrf_getset.h"
/* For ZLL CPU registers */
#include "cpu.h"
#ifdef MODULE_PM_LAYERED
#include "pm_layered.h"
#define PM_BLOCK(x) pm_block(x)
#define PM_UNBLOCK(x) pm_unblock(x)
/* When the transceiver is not in DSM, this power mode will be blocked.
* TODO: Change this to symbolic name KINETIS_PM_VLPS when Kinetis power
* management is merged (https://github.com/RIOT-OS/RIOT/pull/7897) */
#define KW41ZRF_PM_BLOCKER 1
#else
#define PM_BLOCK(x)
#define PM_UNBLOCK(x)
#endif
/* Set to 1 to use on board LEDs to show RX/TX activity */
#ifndef KW41ZRF_ENABLE_LEDS
#define KW41ZRF_ENABLE_LEDS (0)
#endif
#if KW41ZRF_ENABLE_LEDS
/* For LED macros */
#include "board.h"
#if !defined(KW41ZRF_LED_RX_ON)
#if defined(LED0_ON)
#define KW41ZRF_LED_RX_ON LED0_ON
#define KW41ZRF_LED_RX_OFF LED0_OFF
#else /* defined(LED0_ON) */
#define KW41ZRF_LED_RX_ON
#define KW41ZRF_LED_RX_OFF
#endif /* defined(LED0_ON) */
#endif /* !defined(KW41ZRF_LED_RX_ON) */
#if !defined(KW41ZRF_LED_TX_ON)
#if defined(LED1_ON)
/* Separate TX LED */
#define KW41ZRF_LED_TX_ON LED1_ON
#define KW41ZRF_LED_TX_OFF LED1_OFF
#elif defined(LED0_ON)
/* Combined RX+TX in one LED */
#define KW41ZRF_LED_TX_ON LED0_ON
#define KW41ZRF_LED_TX_OFF LED0_OFF
#else /* defined(LEDx_ON) */
#define KW41ZRF_LED_TX_ON
#define KW41ZRF_LED_TX_OFF
#endif /* defined(LEDx_ON) */
#endif /* !defined(KW41ZRF_LED_TX_ON) */
#if !defined(KW41ZRF_LED_NDSM_ON)
#if defined(LED2_ON)
#define KW41ZRF_LED_NDSM_ON LED2_ON
#define KW41ZRF_LED_NDSM_OFF LED2_OFF
#else /* defined(LEDx_ON) */
#define KW41ZRF_LED_NDSM_ON
#define KW41ZRF_LED_NDSM_OFF
#endif /* defined(LEDx_ON) */
#endif /* !defined(KW41ZRF_LED_NDSM_ON) */
#if !defined(KW41ZRF_LED_IRQ_ON)
#if defined(LED3_ON)
#define KW41ZRF_LED_IRQ_ON LED3_ON
#define KW41ZRF_LED_IRQ_OFF LED3_OFF
#else /* defined(LEDx_ON) */
#define KW41ZRF_LED_IRQ_ON
#define KW41ZRF_LED_IRQ_OFF
#endif /* defined(LEDx_ON) */
#endif /* !defined(KW41ZRF_LED_IRQ_ON) */
#else /* KW41ZRF_ENABLE_LEDS */
#define KW41ZRF_LED_NDSM_ON
#define KW41ZRF_LED_NDSM_OFF
#define KW41ZRF_LED_TX_ON
#define KW41ZRF_LED_TX_OFF
#define KW41ZRF_LED_RX_ON
#define KW41ZRF_LED_RX_OFF
#define KW41ZRF_LED_IRQ_ON
#define KW41ZRF_LED_IRQ_OFF
#endif /* KW41ZRF_ENABLE_LEDS */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief KW41Z transceiver power modes
*/
typedef enum {
KW41ZRF_POWER_IDLE = 0, /**< All parts powered */
KW41ZRF_POWER_DSM, /**< Deep sleep mode */
} kw41zrf_powermode_t;
/**
* @brief Timebase settings
*/
typedef enum kw41zrf_timer_timebase {
KW41ZRF_TIMEBASE_500000HZ = 0b010,
KW41ZRF_TIMEBASE_250000HZ = 0b011,
KW41ZRF_TIMEBASE_125000HZ = 0b100,
KW41ZRF_TIMEBASE_62500HZ = 0b101,
KW41ZRF_TIMEBASE_31250HZ = 0b110,
KW41ZRF_TIMEBASE_15625HZ = 0b111,
} kw41zrf_timer_timebase_t;
/**
* @brief Mask all transceiver interrupts
*/
static inline void kw41zrf_mask_irqs(void)
{
NVIC_DisableIRQ(Radio_1_IRQn);
NVIC_ClearPendingIRQ(Radio_1_IRQn);
}
/**
* @brief Unmask all transceiver interrupts
*/
static inline void kw41zrf_unmask_irqs(void)
{
KW41ZRF_LED_IRQ_OFF;
NVIC_EnableIRQ(Radio_1_IRQn);
}
/**
* @brief Set the callback function for the radio ISR
*
* This callback will be called from ISR context when a radio_1 interrupt occurs
*
* @param[in] cb Pointer to callback function
* @param[in] arg Argument that will be passed to the callback
*/
void kw41zrf_set_irq_callback(void (*cb)(void *arg), void *arg);
/**
* @brief Set power mode for device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] pm power mode value
*/
void kw41zrf_set_power_mode(kw41zrf_t *dev, kw41zrf_powermode_t pm);
/**
* @brief Determine if the transceiver is busy doing TX or RX
*
* @param[in] dev kw41zrf device descriptor
*
* @return 0 if transceiver is in progress transmitting a packet
* @return 1 otherwise
*/
int kw41zrf_can_switch_to_idle(kw41zrf_t *dev);
/**
* @brief Set sequence state of device
*
* @param[in] dev kw41zrf device descriptor
* @param[in] seq sequence
*/
void kw41zrf_set_sequence(kw41zrf_t *dev, uint32_t seq);
/**
* @brief Abort the current autosequence
*
* @param[in] dev kw41zrf device descriptor
*/
static inline void kw41zrf_abort_sequence(kw41zrf_t *dev)
{
(void) dev;
/* Writing IDLE to XCVSEQ aborts any ongoing sequence */
ZLL->PHY_CTRL = (ZLL->PHY_CTRL &
~(ZLL_PHY_CTRL_XCVSEQ_MASK |
ZLL_PHY_CTRL_TC3TMOUT_MASK | ZLL_PHY_CTRL_TMRTRIGEN_MASK)) |
ZLL_PHY_CTRL_XCVSEQ(XCVSEQ_IDLE) | ZLL_PHY_CTRL_SEQMSK_MASK;
/* Spin until the sequence manager has acknowledged the sequence abort, this
* should not take many cycles */
while (!(ZLL->SEQ_CTRL_STS & ZLL_SEQ_CTRL_STS_SEQ_IDLE_MASK)) {}
/* Clear interrupt flags */
uint32_t irqsts = ZLL->IRQSTS;
ZLL->IRQSTS = irqsts;
}
/**
* @brief Check if the radio is in deep sleep mode
*
* @return non-zero if radio is in deep sleep
* @return 0 if radio is not in deep sleep mode
*/
static inline uint32_t kw41zrf_is_dsm(void)
{
return (RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK);
}
/**
* @brief Set event timer counter value
*
* @param[in] dev kw41zrf device descriptor
* @param[in] value new time
*/
static inline void kw41zrf_timer_load(kw41zrf_t *dev, uint32_t value)
{
(void) dev;
ZLL->EVENT_TMR = ZLL_EVENT_TMR_EVENT_TMR(value) | ZLL_EVENT_TMR_EVENT_TMR_LD_MASK;
}
/**
* @brief Get current event timer counter value
*
* @param[in] dev kw41zrf device descriptor
*
* @return Current timer value
*/
static inline uint32_t kw41zrf_timer_get(kw41zrf_t *dev)
{
(void) dev;
return (ZLL->EVENT_TMR & ZLL_EVENT_TMR_EVENT_TMR_MASK) >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT;
}
/**
* @brief Set a timeout value for the given compare register of the Event Timer
*
* @param[in] dev kw41zrf device descriptor
* @param[out] cmp_reg pointer to timer compare register, &ZLL->TxCMP
* @param[in] timeout timer offset from current time
*/
static inline void kw41zrf_timer_set(kw41zrf_t *dev, volatile uint32_t *cmp_reg, uint32_t timeout)
{
uint32_t now = kw41zrf_timer_get(dev);
*cmp_reg = now + timeout;
}
/**
* @brief Initialize the Event Timer Block (up counter)
*
* The Event Timer Block provides:
* - Abort an RX and CCA sequence at pre-determined time
* - Latches "timestamp" value during packet reception
* - Initiates timer-triggered sequences
*
* @param[in] dev kw41zrf device descriptor
* @param[in] tb timer base value
*/
static inline void kw41zrf_timer_init(kw41zrf_t *dev, kw41zrf_timer_timebase_t tb)
{
ZLL->TMR_PRESCALE = (ZLL->TMR_PRESCALE & ~ZLL_TMR_PRESCALE_TMR_PRESCALE_MASK) |
ZLL_TMR_PRESCALE_TMR_PRESCALE(tb);
kw41zrf_timer_load(dev, 0);
}
/**
* @brief Returns timestamp of the beginning of the most recently received packet
*
* The latched timestamp corresponds to the point where the SFD detection was
* triggered for the most recent packet, i.e. right before the first byte of the
* packet.
*
* @param[in] dev kw41zrf device descriptor
*
* @return timestamp value
*/
static inline uint32_t kw41zrf_get_timestamp(kw41zrf_t *dev)
{
(void) dev;
return ZLL->TIMESTAMP;
}
#ifdef __cplusplus
}
#endif
#endif /* KW41ZRF_INTERN_H */
/** @} */

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2017 SKF AB
*
* 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 drivers_kw41zrf
* @{
*
* @file
* @brief Netdev interface for kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef KW41ZRF_NETDEV_H
#define KW41ZRF_NETDEV_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Reference to the netdev device driver struct
*/
extern const netdev_driver_t kw41zrf_driver;
#ifdef __cplusplus
}
#endif
#endif /* KW41ZRF_NETDEV_H */
/** @} */

263
drivers/kw41zrf/kw41zrf.c Normal file
View File

@ -0,0 +1,263 @@
/*
* Copyright (C) 2017 SKF AB
*
* 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 drivers_kw41zrf
* @{
* @file
* @brief Basic functionality of kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @}
*/
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "log.h"
#include "msg.h"
#include "luid.h"
#include "net/gnrc.h"
#include "net/ieee802154.h"
#include "kw41zrf.h"
#include "kw41zrf_netdev.h"
#include "kw41zrf_getset.h"
#include "kw41zrf_intern.h"
#include "vendor/XCVR/MKW41Z4/fsl_xcvr.h"
#include "vendor/XCVR/MKW41Z4/ifr_radio.h"
#include "vendor/MKW41Z4.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static void kw41zrf_set_address(kw41zrf_t *dev)
{
DEBUG("[kw41zrf] Set MAC address\n");
eui64_t addr_long;
network_uint16_t addr_short;
/* get unique IDs to use as hardware addresses */
luid_get_eui64(&addr_long);
luid_get_short(&addr_short);
/* set short and long address */
kw41zrf_set_addr_long(dev, &addr_long);
kw41zrf_set_addr_short(dev, &addr_short);
}
void kw41zrf_setup(kw41zrf_t *dev)
{
netdev_t *netdev = (netdev_t *)dev;
netdev->driver = &kw41zrf_driver;
/* initialize device descriptor */
dev->idle_seq = XCVSEQ_RECEIVE;
dev->pm_blocked = 0;
dev->recv_blocked = 0;
/* Set default parameters according to STD IEEE802.15.4-2015 */
dev->csma_max_be = 5;
dev->csma_min_be = 3;
dev->max_retrans = 3;
dev->csma_max_backoffs = 4;
DEBUG("[kw41zrf] setup finished\n");
}
/* vendor routine to initialize the radio core */
int kw41zrf_xcvr_init(kw41zrf_t *dev);
int kw41zrf_init(kw41zrf_t *dev, kw41zrf_cb_t cb)
{
if (dev == NULL) {
return -EINVAL;
}
/* Save a copy of the RF_OSC_EN setting to use when the radio is in deep sleep */
dev->rf_osc_en_idle = RSIM->CONTROL & RSIM_CONTROL_RF_OSC_EN_MASK;
kw41zrf_mask_irqs();
kw41zrf_set_irq_callback(cb, dev);
/* Perform clean reset of the radio modules. */
int res = kw41zrf_reset(dev);
if (res < 0) {
/* initialization error signaled from vendor driver */
/* Restore saved RF_OSC_EN setting */
RSIM->CONTROL = (RSIM->CONTROL & ~RSIM_CONTROL_RF_OSC_EN_MASK) | dev->rf_osc_en_idle;
return res;
}
/* Radio is now on and idle */
/* Allow radio interrupts */
kw41zrf_unmask_irqs();
DEBUG("[kw41zrf] init finished\n");
return 0;
}
int kw41zrf_reset_hardware(kw41zrf_t *dev)
{
/* Enable RSIM oscillator in RUN and WAIT modes, in order to be able to
* access the XCVR and ZLL registers when using the internal reference clock
* for the CPU core */
RSIM->CONTROL |= RSIM_CONTROL_RF_OSC_EN(1);
/* Wait for oscillator ready signal */
while ((RSIM->CONTROL & RSIM_CONTROL_RF_OSC_READY_MASK) == 0) {}
/* Assert radio software reset */
RSIM->CONTROL |= RSIM_CONTROL_RADIO_RESET_BIT_MASK;
/* De-assert radio software reset twice to follow recommendations in the
* reference manual */
RSIM->CONTROL &= ~RSIM_CONTROL_RADIO_RESET_BIT_MASK;
RSIM->CONTROL &= ~RSIM_CONTROL_RADIO_RESET_BIT_MASK;
DEBUG("[kw41zrf] start xcvr init\n");
int res = kw41zrf_xcvr_init(dev);
if (res < 0) {
return res;
}
/* Configure DSM exit oscillator stabilization delay */
uint32_t tmp = (RSIM->RF_OSC_CTRL & RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_MASK) >>
RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_SHIFT;
/* Stabilization time is 1024 * 2^x radio crystal clocks, 0 <= x <= 3 */
RSIM->DSM_OSC_OFFSET = (1024ul << tmp) / (CLOCK_RADIOXTAL / 32768u) + 1u; /* round up */
/* Clear and disable all interrupts */
/* Reset PHY_CTRL to the default values, mask all interrupts,
* enable RXACKRQD, we only use TR mode for receiving acknowledgements */
ZLL->PHY_CTRL =
ZLL_PHY_CTRL_CCATYPE(1) |
ZLL_PHY_CTRL_TSM_MSK_MASK |
ZLL_PHY_CTRL_WAKE_MSK_MASK |
ZLL_PHY_CTRL_CRC_MSK_MASK |
ZLL_PHY_CTRL_PLL_UNLOCK_MSK_MASK |
ZLL_PHY_CTRL_FILTERFAIL_MSK_MASK |
ZLL_PHY_CTRL_RX_WMRK_MSK_MASK |
ZLL_PHY_CTRL_CCAMSK_MASK |
ZLL_PHY_CTRL_RXMSK_MASK |
ZLL_PHY_CTRL_TXMSK_MASK |
ZLL_PHY_CTRL_SEQMSK_MASK |
ZLL_PHY_CTRL_RXACKRQD_MASK |
ZLL_PHY_CTRL_XCVSEQ(XCVSEQ_IDLE);
/* Mask all unused timer interrupts and clear all interrupt flags */
ZLL->IRQSTS =
ZLL_IRQSTS_TMR1MSK_MASK |
ZLL_IRQSTS_TMR4MSK_MASK |
ZLL_IRQSTS_TMR1IRQ_MASK |
ZLL_IRQSTS_TMR2IRQ_MASK |
ZLL_IRQSTS_TMR3IRQ_MASK |
ZLL_IRQSTS_TMR4IRQ_MASK |
ZLL_IRQSTS_WAKE_IRQ_MASK |
ZLL_IRQSTS_PLL_UNLOCK_IRQ_MASK |
ZLL_IRQSTS_FILTERFAIL_IRQ_MASK |
ZLL_IRQSTS_RXWTRMRKIRQ_MASK |
ZLL_IRQSTS_CCAIRQ_MASK |
ZLL_IRQSTS_RXIRQ_MASK |
ZLL_IRQSTS_TXIRQ_MASK |
ZLL_IRQSTS_SEQIRQ_MASK;
/* Clear source address cache */
ZLL->SAM_TABLE |= ZLL_SAM_TABLE_INVALIDATE_ALL_MASK;
/* Accept FrameVersion 0 and 1, data, command, and beacon frames */
ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3) |
ZLL_RX_FRAME_FILTER_BEACON_FT_MASK |
ZLL_RX_FRAME_FILTER_CMD_FT_MASK |
ZLL_RX_FRAME_FILTER_DATA_FT_MASK;
/* Set prescaler to obtain 1 symbol (16us) timebase */
kw41zrf_timer_init(dev, KW41ZRF_TIMEBASE_62500HZ);
/* Set CCA threshold to KW41ZRF_DEFAULT_CCA_THRESHOLD dBm */
/* The hardware default for this register is +75 dBm (0x4b), which is nonsense */
ZLL->CCA_LQI_CTRL = (ZLL->CCA_LQI_CTRL & ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK) |
ZLL_CCA_LQI_CTRL_CCA1_THRESH(KW41ZRF_DEFAULT_CCA_THRESHOLD);
/* Set default LQI compensation */
/* Hardware reset default is 102 */
ZLL->CCA_LQI_CTRL = (ZLL->CCA_LQI_CTRL & ~ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP_MASK) |
ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP(KW41ZRF_DEFAULT_LQI_COMPENSATION);
/* set defaults */
ZLL->SEQ_CTRL_STS = ZLL_SEQ_CTRL_STS_EVENT_TMR_DO_NOT_LATCH_MASK;
return 0;
}
int kw41zrf_reset(kw41zrf_t *dev)
{
kw41zrf_mask_irqs();
/* Sometimes (maybe 1 in 30 reboots) there is a failure in the vendor
* routines in kw41zrf_rx_bba_dcoc_dac_trim_DCest() that can be worked
* around by retrying. Clearly this is not ideal.
*/
for (int retries = 0; ; retries++) {
int res = kw41zrf_reset_hardware(dev);
if (!res) {
if (retries) {
LOG_WARNING("kw41zrf_reset_hardware() needed %i retries\n",
retries);
}
break;
}
if (retries == 9) {
LOG_ERROR("kw41zrf_reset_hardware() returned %i\n", res);
kw41zrf_unmask_irqs();
return res;
}
}
/* Compute warmup times (scaled to 16us) */
dev->rx_warmup_time =
(XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >>
XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
dev->tx_warmup_time =
(XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_MASK) >>
XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_SHIFT;
/* divide by 16 and round up */
dev->rx_warmup_time = (dev->rx_warmup_time + 15) / 16;
dev->tx_warmup_time = (dev->tx_warmup_time + 15) / 16;
/* Reset software link layer driver state */
netdev_ieee802154_reset(&dev->netdev);
dev->tx_power = KW41ZRF_DEFAULT_TX_POWER;
dev->idle_seq = XCVSEQ_RECEIVE;
kw41zrf_set_power_mode(dev, KW41ZRF_POWER_IDLE);
kw41zrf_abort_sequence(dev);
kw41zrf_set_tx_power(dev, dev->tx_power);
kw41zrf_set_channel(dev, KW41ZRF_DEFAULT_CHANNEL);
kw41zrf_set_address(dev);
kw41zrf_set_cca_mode(dev, 1);
kw41zrf_set_rx_watermark(dev, 1);
kw41zrf_set_option(dev, KW41ZRF_OPT_AUTOACK, 1);
kw41zrf_set_option(dev, KW41ZRF_OPT_CSMA, 1);
static const netopt_enable_t enable = NETOPT_ENABLE;
netdev_ieee802154_set(&dev->netdev, NETOPT_ACK_REQ,
&enable, sizeof(enable));
kw41zrf_abort_sequence(dev);
kw41zrf_set_sequence(dev, dev->idle_seq);
kw41zrf_unmask_irqs();
DEBUG("[kw41zrf] reset radio and set to channel %d.\n",
KW41ZRF_DEFAULT_CHANNEL);
return 0;
}

View File

@ -0,0 +1,304 @@
/*
* Copyright (C) 2017 SKF AB
*
* 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 drivers_kw41zrf
* @{
* @file
* @brief get/set functionality of kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @}
*/
#include <errno.h>
#include <string.h>
#include "log.h"
#include "cpu.h"
#include "byteorder.h"
#include "kw41zrf.h"
#include "kw41zrf_intern.h"
#include "kw41zrf_getset.h"
#include "vendor/MKW41Z4.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define KW41ZRF_NUM_CHANNEL (KW41ZRF_MAX_CHANNEL - KW41ZRF_MIN_CHANNEL + 1)
/* Lookup table for PA_PWR register */
/* Source: KW41Z data sheet, 5.3 Transmit and PLL Feature Summary,
* Table 8. Transmit Output Power as a function of PA_POWER[5:0] */
static const uint8_t tx_power_dbm_to_pa_pwr[29] = {
4, 4, 4, 4, /* -19:-16 dBm */
6, 6, /* -15:-14 dBm */
8, 8, /* -13:-12 dBm */
10, 10, /* -11:-10 dBm */
12, /* -9 dBm */
14, /* -8 dBm */
16, /* -7 dBm */
18, /* -6 dBm */
20, /* -5 dBm */
22, /* -4 dBm */
26, /* -3 dBm */
28, /* -2 dBm */
34, /* -1 dBm */
38, /* 0 dBm */
42, /* 1 dBm */
48, /* 2 dBm */
56, /* 3 dBm */
62, /* 4 dBm */
};
void kw41zrf_set_tx_power(kw41zrf_t *dev, int16_t txpower_dbm)
{
if (txpower_dbm < KW41ZRF_OUTPUT_POWER_MIN) {
txpower_dbm = KW41ZRF_OUTPUT_POWER_MIN;
}
else if (txpower_dbm > KW41ZRF_OUTPUT_POWER_MAX) {
txpower_dbm = KW41ZRF_OUTPUT_POWER_MAX;
}
ZLL->PA_PWR = tx_power_dbm_to_pa_pwr[txpower_dbm - KW41ZRF_OUTPUT_POWER_MIN];
DEBUG("[kw41zrf] set txpower to: %d\n", txpower_dbm);
dev->tx_power = txpower_dbm;
}
int16_t kw41zrf_get_txpower(kw41zrf_t *dev)
{
return dev->tx_power;
}
uint8_t kw41zrf_get_channel(kw41zrf_t *dev)
{
(void) dev;
return (ZLL->CHANNEL_NUM0 & ZLL_CHANNEL_NUM0_CHANNEL_NUM0_MASK)
>> ZLL_CHANNEL_NUM0_CHANNEL_NUM0_SHIFT;
}
uint16_t kw41zrf_get_pan(kw41zrf_t *dev)
{
(void) dev;
return (ZLL->MACSHORTADDRS0 & ZLL_MACSHORTADDRS0_MACPANID0_MASK)
>> ZLL_MACSHORTADDRS0_MACPANID0_SHIFT;
}
int kw41zrf_set_channel(kw41zrf_t *dev, uint8_t channel)
{
(void) dev;
if (channel < KW41ZRF_MIN_CHANNEL || channel > KW41ZRF_MAX_CHANNEL) {
LOG_ERROR("[kw41zrf] Invalid channel %u\n", channel);
return -EINVAL;
}
ZLL->CHANNEL_NUM0 = channel;
DEBUG("[kw41zrf] set channel to %u\n", channel);
return 0;
}
void kw41zrf_set_pan(kw41zrf_t *dev, uint16_t pan)
{
(void) dev;
ZLL->MACSHORTADDRS0 = (ZLL->MACSHORTADDRS0
& ~ZLL_MACSHORTADDRS0_MACPANID0_MASK) |
ZLL_MACSHORTADDRS0_MACPANID0(pan);
DEBUG("[kw41zrf] set pan to: 0x%x\n", pan);
}
void kw41zrf_set_addr_short(kw41zrf_t *dev, const network_uint16_t *addr)
{
(void) dev;
ZLL->MACSHORTADDRS0 = (ZLL->MACSHORTADDRS0
& ~ZLL_MACSHORTADDRS0_MACSHORTADDRS0_MASK) |
ZLL_MACSHORTADDRS0_MACSHORTADDRS0(addr->u16);
}
void kw41zrf_set_addr_long(kw41zrf_t *dev, const eui64_t *addr)
{
(void) dev;
ZLL->MACLONGADDRS0_LSB = addr->uint32[0].u32;
ZLL->MACLONGADDRS0_MSB = addr->uint32[1].u32;
}
void kw41zrf_get_addr_short(kw41zrf_t *dev, network_uint16_t *addr)
{
(void) dev;
addr->u16 = (ZLL->MACSHORTADDRS0 & ZLL_MACSHORTADDRS0_MACSHORTADDRS0_MASK) >>
ZLL_MACSHORTADDRS0_MACSHORTADDRS0_SHIFT;
}
void kw41zrf_get_addr_long(kw41zrf_t *dev, eui64_t *addr)
{
(void) dev;
addr->uint32[0] = (network_uint32_t)ZLL->MACLONGADDRS0_LSB;
addr->uint32[1] = (network_uint32_t)ZLL->MACLONGADDRS0_MSB;
}
int8_t kw41zrf_get_cca_threshold(kw41zrf_t *dev)
{
(void) dev;
uint8_t tmp = (ZLL->CCA_LQI_CTRL & ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK) >>
ZLL_CCA_LQI_CTRL_CCA1_THRESH_SHIFT;
return (int8_t)tmp;
}
void kw41zrf_set_cca_threshold(kw41zrf_t *dev, int8_t value)
{
(void) dev;
ZLL->CCA_LQI_CTRL = (ZLL->CCA_LQI_CTRL & ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK) |
ZLL_CCA_LQI_CTRL_CCA1_THRESH(value);
}
void kw41zrf_set_cca_mode(kw41zrf_t *dev, uint8_t mode)
{
(void) dev;
ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_CCATYPE_MASK) |
ZLL_PHY_CTRL_CCATYPE(mode);
}
uint8_t kw41zrf_get_cca_mode(kw41zrf_t *dev)
{
(void) dev;
return (ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCATYPE_MASK) >> ZLL_PHY_CTRL_CCATYPE_SHIFT;
}
int8_t kw41zrf_get_ed_level(kw41zrf_t *dev)
{
(void) dev;
return (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_CCA1_ED_FNL_MASK)
>> ZLL_LQI_AND_RSSI_CCA1_ED_FNL_SHIFT;
}
void kw41zrf_set_option(kw41zrf_t *dev, uint8_t option, uint8_t state)
{
DEBUG("[kw41zrf] set option 0x%04x to %x\n", option, state);
if (kw41zrf_is_dsm()) {
/* Transceiver is sleeping */
switch (option) {
/* Modifying these options require that the transceiver is not in
* deep sleep mode */
case KW41ZRF_OPT_CSMA:
case KW41ZRF_OPT_PROMISCUOUS:
case KW41ZRF_OPT_AUTOACK:
case KW41ZRF_OPT_ACK_PENDING:
case KW41ZRF_OPT_TELL_RX_START:
LOG_ERROR("[kw41zrf] Attempt to modify option %04x while radio is sleeping\n",
(unsigned) option);
assert(0);
return;
default:
break;
}
}
/* set option field */
if (state) {
dev->flags |= option;
/* trigger option specific actions */
switch (option) {
case KW41ZRF_OPT_CSMA:
DEBUG("[kw41zrf] enable: CSMA\n");
bit_set32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_CCABFRTX_SHIFT);
break;
case KW41ZRF_OPT_PROMISCUOUS:
DEBUG("[kw41zrf] enable: PROMISCUOUS\n");
/* enable promiscuous mode */
bit_set32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_PROMISCUOUS_SHIFT);
/* auto ACK is always disabled in promiscuous mode by the hardware */
break;
case KW41ZRF_OPT_AUTOACK:
DEBUG("[kw41zrf] enable: AUTOACK\n");
bit_set32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_AUTOACK_SHIFT);
break;
case KW41ZRF_OPT_ACK_PENDING:
DEBUG("[kw41zrf] enable: PENDING_BIT\n");
bit_set32(&ZLL->SAM_TABLE, ZLL_SAM_TABLE_ACK_FRM_PND_SHIFT);
break;
case KW41ZRF_OPT_TELL_RX_START:
DEBUG("[kw41zrf] enable: TELL_RX_START\n");
bit_clear32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_RX_WMRK_MSK_SHIFT);
break;
case KW41ZRF_OPT_TELL_RX_END:
DEBUG("[kw41zrf] enable: TELL_RX_END\n");
break;
case KW41ZRF_OPT_TELL_TX_END:
DEBUG("[kw41zrf] enable: TELL_TX_END\n");
break;
case KW41ZRF_OPT_TELL_TX_START:
DEBUG("[kw41zrf] enable: TELL_TX_START (ignored)\n");
default:
/* do nothing */
break;
}
}
else {
dev->flags &= ~(option);
/* trigger option specific actions */
switch (option) {
case KW41ZRF_OPT_CSMA:
DEBUG("[kw41zrf] disable: CSMA\n");
bit_clear32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_CCABFRTX_SHIFT);
break;
case KW41ZRF_OPT_PROMISCUOUS:
DEBUG("[kw41zrf] disable: PROMISCUOUS\n");
/* disable promiscuous mode */
bit_clear32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_PROMISCUOUS_SHIFT);
break;
case KW41ZRF_OPT_AUTOACK:
DEBUG("[kw41zrf] disable: AUTOACK\n");
bit_clear32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_AUTOACK_SHIFT);
break;
case KW41ZRF_OPT_ACK_PENDING:
DEBUG("[kw41zrf] disable: PENDING_BIT\n");
bit_clear32(&ZLL->SAM_TABLE, ZLL_SAM_TABLE_ACK_FRM_PND_SHIFT);
break;
case KW41ZRF_OPT_TELL_RX_START:
DEBUG("[kw41zrf] disable: TELL_RX_START\n");
bit_set32(&ZLL->PHY_CTRL, ZLL_PHY_CTRL_RX_WMRK_MSK_SHIFT);
break;
case KW41ZRF_OPT_TELL_RX_END:
DEBUG("[kw41zrf] disable: TELL_RX_END\n");
break;
case KW41ZRF_OPT_TELL_TX_END:
DEBUG("[kw41zrf] disable: TELL_TX_END\n");
break;
case KW41ZRF_OPT_TELL_TX_START:
DEBUG("[kw41zrf] disable: TELL_TX_START (ignored)\n");
default:
/* do nothing */
break;
}
}
}
void kw41zrf_set_rx_watermark(kw41zrf_t *dev, uint8_t value)
{
(void) dev;
ZLL->RX_WTR_MARK = ZLL_RX_WTR_MARK_RX_WTR_MARK(value);
}

View File

@ -0,0 +1,235 @@
/*
* Copyright (C) 2017 SKF AB
*
* 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 drivers_kw41zrf
* @{
* @file
* @brief Internal function of kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @}
*/
#include "log.h"
#include "irq.h"
#include "panic.h"
#include "kw41zrf.h"
#include "kw41zrf_getset.h"
#include "kw41zrf_intern.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Delay before entering deep sleep mode, in DSM_TIMER ticks (32.768 kHz)
*
* @attention must be >= 4 according to SoC ref. manual
*/
#define KW41ZRF_DSM_ENTER_DELAY 5
/**
* @brief Delay before leaving deep sleep mode, in DSM_TIMER ticks (32.768 kHz)
*
* @attention must be >= 4 according to SoC ref. manual
*/
#define KW41ZRF_DSM_EXIT_DELAY 5
struct {
void (*cb)(void *arg); /**< Callback function called from radio ISR */
void *arg; /**< Argument to callback */
} isr_config;
void kw41zrf_set_irq_callback(void (*cb)(void *arg), void *arg)
{
unsigned int mask = irq_disable();
isr_config.cb = cb;
isr_config.arg = arg;
irq_restore(mask);
}
void kw41zrf_set_power_mode(kw41zrf_t *dev, kw41zrf_powermode_t pm)
{
DEBUG("[kw41zrf] set power mode to %u\n", pm);
unsigned state = irq_disable();
switch (pm) {
case KW41ZRF_POWER_IDLE:
{
/* Disable some CPU power management if we need to be active, otherwise the
* radio will be stuck in state retention mode. */
if (!dev->pm_blocked) {
PM_BLOCK(KW41ZRF_PM_BLOCKER);
dev->pm_blocked = 1;
}
/* Restore saved RF oscillator settings, enable oscillator in RUN mode
* to allow register access */
/* This is also where the oscillator is enabled during kw41zrf_init:
* kw41zrf_init -> kw41zrf_reset_phy -> kw41zrf_set_power_mode
* => Do not return before this line during init */
RSIM->CONTROL |= RSIM_CONTROL_RF_OSC_EN(1);
/* Assume DSM timer has been running since we entered sleep mode */
/* In case it was not already running, however, we still set the
* enable flag here. */
/* RSIM_DSM_CONTROL_ZIG_SYSCLK_REQUEST_EN lets the link layer
* request the RF oscillator to remain on during STOP and VLPS, to
* allow stopping the CPU core without affecting TX or RX operations */
RSIM->DSM_CONTROL = (RSIM_DSM_CONTROL_DSM_TIMER_EN_MASK |
RSIM_DSM_CONTROL_ZIG_SYSCLK_REQUEST_EN_MASK);
/* Wait for oscillator ready signal before attempting to recover from DSM */
while ((RSIM->CONTROL & RSIM_CONTROL_RF_OSC_READY_MASK) == 0) {}
KW41ZRF_LED_NDSM_ON;
/* If we are already awake we can just return now. */
if (!(kw41zrf_is_dsm())) {
/* Already awake */
break;
}
/* The wake target must be at least (4 + RSIM_DSM_OSC_OFFSET) ticks
* into the future, to let the oscillator stabilize before switching
* on the clocks */
RSIM->ZIG_WAKE = KW41ZRF_DSM_EXIT_DELAY + RSIM->DSM_TIMER + RSIM->DSM_OSC_OFFSET;
/* Wait to come out of DSM */
while (kw41zrf_is_dsm()) {}
/* Convert DSM ticks (32.768 kHz) to event timer ticks (1 MHz) */
uint64_t tmp = (uint64_t)(RSIM->ZIG_WAKE - RSIM->ZIG_SLEEP) * 15625ul;
uint32_t usec = (tmp >> 9); /* equivalent to (usec / 512) */
/* Add the offset */
ZLL->EVENT_TMR = ZLL_EVENT_TMR_EVENT_TMR_ADD_MASK |
ZLL_EVENT_TMR_EVENT_TMR(usec);
/* Clear IRQ flags */
uint32_t irqsts = ZLL->IRQSTS;
DEBUG("[kw41zrf] wake IRQSTS=%" PRIx32 "\n", irqsts);
ZLL->IRQSTS = irqsts;
/* Disable DSM timer triggered sleep */
ZLL->DSM_CTRL = 0;
break;
}
case KW41ZRF_POWER_DSM:
{
if (kw41zrf_is_dsm()) {
/* Already asleep */
break;
}
if (dev->pm_blocked) {
PM_UNBLOCK(KW41ZRF_PM_BLOCKER);
dev->pm_blocked = 0;
}
/* Race condition: if sleep is re-triggered after wake before the
* DSM_ZIG_FINISHED flag has been switched off, then the RSIM
* becomes stuck and never enters DSM.
* The time from ZIG_WAKE until DSM_ZIG_FINISHED is turned off seem
* to be constant at 2 DSM ticks */
while (RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_DSM_ZIG_FINISHED_MASK) {}
/* Clear IRQ flags */
uint32_t irqsts = RSIM->DSM_CONTROL;
RSIM->DSM_CONTROL = irqsts;
irqsts = ZLL->IRQSTS;
DEBUG("[kw41zrf] sleep IRQSTS=%" PRIx32 "\n", irqsts);
ZLL->IRQSTS = irqsts;
NVIC_ClearPendingIRQ(Radio_1_IRQn);
/* Enable timer triggered sleep */
ZLL->DSM_CTRL = ZLL_DSM_CTRL_ZIGBEE_SLEEP_EN_MASK;
/* The device will automatically wake up 8.5 minutes from now if not
* awoken sooner by software */
/* TODO handle automatic wake in the ISR if it becomes an issue */
RSIM->ZIG_WAKE = RSIM->DSM_TIMER - KW41ZRF_DSM_EXIT_DELAY - RSIM->DSM_OSC_OFFSET;
/* Set sleep start time */
/* The target time must be at least 4 DSM_TIMER ticks into the future */
RSIM->ZIG_SLEEP = RSIM->DSM_TIMER + KW41ZRF_DSM_ENTER_DELAY;
/* Start the 32.768 kHz DSM timer in case it was not already running */
/* If ZIG_SYSCLK_REQUEST_EN is not set then the hardware will not
* enter DSM and we get stuck in the while() below */
RSIM->DSM_CONTROL = (RSIM_DSM_CONTROL_DSM_TIMER_EN_MASK |
RSIM_DSM_CONTROL_ZIG_SYSCLK_REQUEST_EN_MASK);
while (!(kw41zrf_is_dsm())) {}
KW41ZRF_LED_NDSM_OFF;
/* Restore saved RF_OSC_EN bits (from kw41zrf_init)
* This will disable the RF oscillator unless the system was
* configured to use the RF oscillator before kw41zrf_init() was
* called, for example when using the RF oscillator for the CPU core
* clock. */
RSIM->CONTROL = (RSIM->CONTROL & ~RSIM_CONTROL_RF_OSC_EN_MASK) |
dev->rf_osc_en_idle;
/* Let the DSM timer run until we exit deep sleep mode */
break;
}
default:
LOG_ERROR("[kw41zrf] Unknown power mode %u\n", pm);
break;
}
irq_restore(state);
}
void kw41zrf_set_sequence(kw41zrf_t *dev, uint32_t seq)
{
(void) dev;
DEBUG("[kw41zrf] set sequence to %x\n", (unsigned)seq);
assert(!kw41zrf_is_dsm());
unsigned back_to_sleep = 0;
if (seq == XCVSEQ_DSM_IDLE) {
back_to_sleep = 1;
seq = XCVSEQ_IDLE;
}
else if ((seq == XCVSEQ_RECEIVE) && dev->recv_blocked) {
/* Wait in standby until recv has been called to avoid corrupting the RX
* buffer before the frame has been received by the higher layers */
seq = XCVSEQ_IDLE;
}
uint32_t seq_old = ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK;
if (seq_old != XCVSEQ_IDLE && seq_old != XCVSEQ_RECEIVE) {
LOG_ERROR("[kw41zrf] seq not idle: 0x%" PRIu32 "\n", seq_old);
assert(0);
}
kw41zrf_abort_sequence(dev);
ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~(ZLL_PHY_CTRL_XCVSEQ_MASK | ZLL_PHY_CTRL_SEQMSK_MASK)) | seq;
while (((ZLL->SEQ_CTRL_STS & ZLL_SEQ_CTRL_STS_XCVSEQ_ACTUAL_MASK) >>
ZLL_SEQ_CTRL_STS_XCVSEQ_ACTUAL_SHIFT) != (ZLL_PHY_CTRL_XCVSEQ_MASK & seq)) {}
if (back_to_sleep) {
kw41zrf_set_power_mode(dev, KW41ZRF_POWER_DSM);
}
}
int kw41zrf_can_switch_to_idle(kw41zrf_t *dev)
{
(void) dev;
if (!kw41zrf_is_dsm()) {
uint8_t seq = (ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) >> ZLL_PHY_CTRL_XCVSEQ_SHIFT;
DEBUG("[kw41zrf] XCVSEQ=0x%x, SEQ_STATE=0x%" PRIx32 ", SEQ_CTRL_STS=0x%" PRIx32 "\n", seq,
ZLL->SEQ_STATE, ZLL->SEQ_CTRL_STS);
switch (seq)
{
case XCVSEQ_TRANSMIT:
case XCVSEQ_TX_RX:
case XCVSEQ_CCA:
/* We should wait until TX or CCA has finished before moving to
* another mode */
return 0;
default:
break;
}
}
return 1;
}
void isr_radio_1(void)
{
DEBUG("[kw41zrf] INT1\n");
if (isr_config.cb != NULL) {
isr_config.cb(isr_config.arg);
}
cortexm_isr_end();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,913 @@
/*
* The Clear BSD License
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @ingroup drivers_kw41zrf
* @{
* @file
* @brief NXP KW41Z XCVR module initialization and calibration of kw41zrf driver
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @}
*/
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "log.h"
#include "bit.h"
#include "kw41zrf.h"
#include "vendor/XCVR/MKW41Z4/fsl_xcvr.h"
#include "vendor/XCVR/MKW41Z4/ifr_radio.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* The implementations for these functions are taken from the vendor-provided
* XCVR driver from mcuxpresso.nxp.com (KSDK 2.2.0, framework_5.3.5)
* The code has been refactored to eliminate a lot of preprocessor
* conditionals. */
#define TsettleCal 10
#define DCOC_DAC_BBF_STEP (16)
#define RX_DC_EST_SAMPLES (64)
#define RX_DC_EST_TOTAL_SAMPLES (2 * (RX_DC_EST_SAMPLES))
/* Macros used by the calibration routine */
#define SAME_SIGN(a, b) (((a) ^ (b)) >= 0)
#define ABS(x) ((x) > 0 ? (x) : -(x))
/* dumb spin delay used in the calibration functions */
static void kw41zrf_xcvr_spin(uint32_t time)
{
time *= 32; /* Time delay is roughly in uSec. */
while (time > 0)
{
__asm__ volatile ("" ::: "memory");
--time;
}
}
/* Collect RX DC estimation samples */
static void rx_dc_est_samples(int32_t *i_sum, int32_t *q_sum, unsigned nsamples)
{
/* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase). */
uint32_t end_of_rx_wu = XCVR_CTRL_XCVR_STATUS_TSM_COUNT(
(XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >>
XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT);
while ((XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) != end_of_rx_wu) {};
int32_t sum_i = 0;
int32_t sum_q = 0;
/* Read DCOC DC EST register. */
for (unsigned k = 0; k < nsamples; k++)
{
uint32_t dc_temp = XCVR_RX_DIG->DCOC_DC_EST;
int16_t dc_meas_i = (dc_temp & XCVR_RX_DIG_DCOC_DC_EST_DC_EST_I_MASK) >> XCVR_RX_DIG_DCOC_DC_EST_DC_EST_I_SHIFT;
dc_meas_i = (int16_t)(dc_meas_i << 4) / 16; /* Sign extend from 12 to 16 bits. */
sum_i += dc_meas_i;
int16_t dc_meas_q = (dc_temp & XCVR_RX_DIG_DCOC_DC_EST_DC_EST_Q_MASK) >> XCVR_RX_DIG_DCOC_DC_EST_DC_EST_Q_SHIFT;
dc_meas_q = (int16_t)(dc_meas_q << 4) / 16; /* Sign extend from 12 to 16 bits. */
sum_q += dc_meas_q;
}
*i_sum = sum_i;
*q_sum = sum_q;
}
/* Unsigned integer division, rounded to nearest integer */
static inline uint32_t calc_div_rounded(uint32_t num, uint32_t den)
{
return (num + (den / 2)) / den;
}
int kw41zrf_rx_bba_dcoc_dac_trim_DCest(void)
{
/* Estimate the actual gain by measuring three points and approximating a line */
int status = 0;
/* Save register */
uint32_t dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore */
uint32_t dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore */
uint32_t rx_dig_ctrl_stack = XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore */
uint32_t agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore */
uint32_t dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore */
/* Register config */
/* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode */
XCVR_RX_DIG->RX_DIG_CTRL = XCVR_RX_DIG->RX_DIG_CTRL &
~(XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK | /* Turn OFF AGC */
XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK | /* Disable for SW control of DCOC */
XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN_MASK); /* Disable for SW control of DCOC */
XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | /* Enable LNA Manual Gain */
XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | /* Enable BBA Manual Gain */
XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x0) | /* Set LNA Manual Gain */
XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x0); /* Set BBA Manual Gain */
/* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode */
XCVR_RX_DIG->DCOC_CTRL_0 = XCVR_RX_DIG->DCOC_CTRL_0 |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1) | /* Enable Manual DCOC */
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1) | /* Ensure DCOC Tracking is enabled */
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_TRK_EST_OVR(1) | /* Enable DC Estimator */
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1); /* Ensure DC correction is enabled */
/* Use reset defaults */
uint8_t bbf_dacinit_i = 0x20;
uint8_t bbf_dacinit_q = 0x20;
uint8_t tza_dacinit_i = 0x80;
uint8_t tza_dacinit_q = 0x80;
/* Set default DCOC DAC INIT Value */
XCVR_RX_DIG->DCOC_DAC_INIT =
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q);
/* Store DCOC_DAC_INIT value */
uint32_t dcoc_init_reg_value_dcgain = XCVR_RX_DIG->DCOC_DAC_INIT;
kw41zrf_xcvr_spin(TsettleCal * 2);
uint32_t meas_sum = 0;
/* SWEEP I/Q CHANNEL */
/* BBF NEG STEP */
XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i - DCOC_DAC_BBF_STEP) |
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q - DCOC_DAC_BBF_STEP) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q);
kw41zrf_xcvr_spin(TsettleCal * 4);
int32_t dc_meas_im = 0;
int32_t dc_meas_qm = 0;
rx_dc_est_samples(&dc_meas_im, &dc_meas_qm, RX_DC_EST_SAMPLES);
/* BBF POS STEP */
XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i + DCOC_DAC_BBF_STEP) |
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q + DCOC_DAC_BBF_STEP) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q);
kw41zrf_xcvr_spin(TsettleCal * 4);
int32_t dc_meas_ip = 0;
int32_t dc_meas_qp = 0;
rx_dc_est_samples(&dc_meas_ip, &dc_meas_qp, RX_DC_EST_SAMPLES);
DEBUG("dc_meas_i- = %" PRId32 "\n", dc_meas_im);
DEBUG("dc_meas_q- = %" PRId32 "\n", dc_meas_qm);
DEBUG("dc_meas_i+ = %" PRId32 "\n", dc_meas_ip);
DEBUG("dc_meas_q+ = %" PRId32 "\n", dc_meas_qp);
meas_sum += dc_meas_ip - dc_meas_im;
DEBUG("meas_sum = %" PRIu32 "\n", meas_sum);
meas_sum += dc_meas_qp - dc_meas_qm;
DEBUG("meas_sum = %" PRIu32 "\n", meas_sum);
meas_sum /= 2 * DCOC_DAC_BBF_STEP;
DEBUG("meas_sum = %" PRIu32 "\n", meas_sum);
XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DAC setting to initial */
/* Compute the average sampled gain for the measured steps */
/* Calculate BBF DCOC STEPS, RECIPROCALS */
/* meas_sum here is the average gain multiplied by (4 * RX_DC_EST_SAMPLES) */
/* Compute the gain average as a Q6.3 number */
/* rounded result, Q6.3 number */
uint16_t bbf_dcoc_gain_measured = calc_div_rounded(meas_sum, (RX_DC_EST_TOTAL_SAMPLES / (1u << 3)));
DEBUG("temp_step = %f\n", (float)meas_sum / RX_DC_EST_TOTAL_SAMPLES);
DEBUG("bbf_dcoc_gain_measured = %u\n", (unsigned)bbf_dcoc_gain_measured);
/* Check the measured value for validity. Should be in the range:
* 250 < bbf_dcoc_gain_measured < 305, according to NXP wireless framework v5.4.3 (MCUXpresso KW36 SDK)
*/
if ((250 < bbf_dcoc_gain_measured) & (bbf_dcoc_gain_measured < 305))
{
/* Compute reciprocal, as Q15 number, but only the 13 lowest bits are programmable */
/* rounded result, ((2**15) / slope) */
uint32_t bbf_dcoc_gain_measured_rcp = calc_div_rounded((1u << 15) * RX_DC_EST_TOTAL_SAMPLES, meas_sum);
DEBUG("bbf_dcoc_gain_measured_rcp = %"PRIu32"\n", bbf_dcoc_gain_measured_rcp);
uint32_t bbf_dcoc_gain_default =
(xcvr_common_config.dcoc_bba_step_init &
XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP_MASK) >>
XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP_SHIFT;
/* Rescale all default TZA DCOC gains according to the measured BBF gain,
* using (bbf_dcoc_gain_measured / bbf_dcoc_gain_default) as the implicit
* scale factor, but rewrite it to use
* (meas_sum / (bbf_dcoc_gain_default * RX_DC_EST_TOTAL_SAMPLES / (1u << 3))))
* for better numeric precision */
/* rounded result, Q9.3 number */
bbf_dcoc_gain_default *= (RX_DC_EST_TOTAL_SAMPLES / (1u << 3));
DEBUG("base gain = %u\n", (unsigned)bbf_dcoc_gain_default);
/* Make the trims active */
XCVR_RX_DIG->DCOC_BBA_STEP =
XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP(bbf_dcoc_gain_measured) |
XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP_RECIP(bbf_dcoc_gain_measured_rcp);
const uint32_t *dcoc_tza_step_config_ptr = &xcvr_common_config.dcoc_tza_step_00_init;
/* All tza_step_* configuration registers use sequential memory addresses */
volatile uint32_t *xcvr_rx_dig_dcoc_tza_step_ptr = &XCVR_RX_DIG->DCOC_TZA_STEP_0;
for (unsigned k = 0; k <= 10; ++k)
{
/* Calculate TZA DCOC STEPSIZE & its RECIPROCAL */
uint16_t tza_gain_default =
(dcoc_tza_step_config_ptr[k] &
XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_GAIN_0_MASK) >>
XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_GAIN_0_SHIFT;
/* Using meas_sum for higher precision */
DEBUG("tza_gain_default[%u] = %u\n", k, (unsigned)tza_gain_default);
uint32_t dcoc_step = calc_div_rounded(tza_gain_default * meas_sum, bbf_dcoc_gain_default);
uint32_t dcoc_step_rcp = calc_div_rounded((0x8000ul << 3) * bbf_dcoc_gain_default, tza_gain_default * meas_sum);
DEBUG("tza_dcoc_step[%u].dcoc_step = %u\n", k, (unsigned)dcoc_step);
DEBUG("tza_dcoc_step[%u].dcoc_step_rcp = %u\n", k, (unsigned)dcoc_step_rcp);
xcvr_rx_dig_dcoc_tza_step_ptr[k] =
XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_GAIN_0(dcoc_step) |
XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_RCP_0(dcoc_step_rcp) ;
}
}
else
{
LOG_ERROR("!!! XCVR trim failed: bbf_dcoc_step = %u!\n", (unsigned)bbf_dcoc_gain_measured);
status = -EAGAIN; /* Failure */
}
/* Restore Registers */
XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings */
XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings */
XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings */
XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting */
XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore */
return status;
}
static void kw41zrf_dcoc_dac_init_cal(void)
{
uint8_t p_tza_dac_i = 0, p_tza_dac_q = 0;
uint8_t p_bba_dac_i = 0, p_bba_dac_q = 0;
uint8_t i = 0;
uint8_t bba_gain = 11;
uint8_t TZA_I_OK = 0, TZA_Q_OK = 0, BBA_I_OK = 0, BBA_Q_OK = 0;
uint32_t temp;
/* Save registers */
uint32_t dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore */
uint32_t dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore */
uint32_t rx_dig_ctrl_stack = XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore */
uint32_t agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore */
uint32_t dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore */
/* Register config */
/* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode */
temp = XCVR_RX_DIG->RX_DIG_CTRL;
temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK; /* Turn OFF AGC */
temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK; /* Disable for SW control of DCOC */
temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN_MASK; /* Disable for SW control of DCOC */
XCVR_RX_DIG->RX_DIG_CTRL = temp;
XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | /* Enable LNA Manual Gain */
XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | /* Enable BBA Manual Gain */
XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x0) | /* Set LNA Manual Gain */
XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x0); /* Set BBA Manual Gain */
/* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode */
temp = XCVR_RX_DIG->DCOC_CTRL_0;
temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1); /* Enable Manual DCOC */
temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1); /* Ensure DCOC Tracking is enabled */
temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_TRK_EST_OVR(1); /* Enable DC Estimator */
temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1); /* Ensure DC correction is enabled */
XCVR_RX_DIG->DCOC_CTRL_0 = temp;
kw41zrf_xcvr_spin(TsettleCal);
/* Set default DCOC DAC INIT Value */
/* LNA and BBA DAC Sweep */
uint8_t curr_bba_dac_i = 0x20;
uint8_t curr_bba_dac_q = 0x20;
uint8_t curr_tza_dac_i = 0x80;
uint8_t curr_tza_dac_q = 0x80;
/* Perform a first DC measurement to ensure that measurement is not clipping */
XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q);
int32_t dc_meas_i = 2000, dc_meas_i_p = 2000;
int32_t dc_meas_q = 2000, dc_meas_q_p = 2000;
do {
bba_gain--;
/* Set DAC user gain */
XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) |
XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0) | /* 2 */
XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) |
XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(bba_gain) ; /* 10 */
kw41zrf_xcvr_spin(TsettleCal * 2);
rx_dc_est_samples(&dc_meas_i, &dc_meas_q, RX_DC_EST_SAMPLES);
DEBUG("rx i=%d q=%d\n", (int)dc_meas_i, (int)dc_meas_q);
dc_meas_i /= RX_DC_EST_SAMPLES;
dc_meas_q /= RX_DC_EST_SAMPLES;
DEBUG("rx i=%d q=%d\n", (int)dc_meas_i, (int)dc_meas_q);
DEBUG("[kw41zrf] bba_gain=%u, meas I=%" PRId32 ", Q=%" PRId32 "\n", (unsigned)bba_gain, dc_meas_i, dc_meas_q);
} while ((ABS(dc_meas_i) > 1900) || (ABS(dc_meas_q) > 1900));
for (i = 0; i < 0x0F; i++)
{
DEBUG("rx i=%d q=%d\n", (int)dc_meas_i, (int)dc_meas_q);
/* I channel : */
if (!TZA_I_OK) {
if ((i > 0) && (!SAME_SIGN(dc_meas_i, dc_meas_i_p))) {
if (ABS(dc_meas_i) > ABS(dc_meas_i_p)) {
curr_tza_dac_i = p_tza_dac_i;
}
TZA_I_OK = 1;
}
else {
p_tza_dac_i = curr_tza_dac_i;
if (dc_meas_i > 0) {
curr_tza_dac_i--;
}
else {
curr_tza_dac_i++;
}
}
}
else if (!BBA_I_OK) {
/* Sweep BBA I */
if ((curr_bba_dac_i != 0x20) && (!SAME_SIGN(dc_meas_i, dc_meas_i_p))) {
if (ABS(dc_meas_i) > ABS(dc_meas_i_p)) {
curr_bba_dac_i = p_bba_dac_i;
}
BBA_I_OK = 1;
}
else {
p_bba_dac_i = curr_bba_dac_i;
if (dc_meas_i > 0) {
curr_bba_dac_i--;
}
else {
curr_bba_dac_i++;
}
}
}
/* Q channel : */
if (!TZA_Q_OK) {
if ((i > 0) && (!SAME_SIGN(dc_meas_q, dc_meas_q_p))) {
if (ABS(dc_meas_q) > ABS(dc_meas_q_p)) {
curr_tza_dac_q = p_tza_dac_q;
}
TZA_Q_OK = 1;
}
else {
p_tza_dac_q = curr_tza_dac_q;
if (dc_meas_q > 0) {
curr_tza_dac_q--;
}
else {
curr_tza_dac_q++;
}
}
}
else if (!BBA_Q_OK) {
/* Sweep BBA Q */
if ((curr_bba_dac_q != 0x20) && (!SAME_SIGN(dc_meas_q, dc_meas_q_p))) {
if (ABS(dc_meas_q) > ABS(dc_meas_q_p)) {
curr_bba_dac_q = p_bba_dac_q;
}
BBA_Q_OK = 1;
}
else {
p_bba_dac_q = curr_bba_dac_q;
if (dc_meas_q > 0) {
curr_bba_dac_q--;
}
else {
curr_bba_dac_q++;
}
}
}
/* DC OK break : */
if (TZA_I_OK && TZA_Q_OK && BBA_I_OK && BBA_Q_OK) {
break;
}
dc_meas_i_p = dc_meas_i; /* Store as previous value */
dc_meas_q_p = dc_meas_q; /* Store as previous value */
DEBUG("curr_bba_dac i=%d q=%d\n", (int)curr_bba_dac_i, (int)curr_bba_dac_q);
DEBUG("curr_tza_dac i=%d q=%d\n", (int)curr_tza_dac_i, (int)curr_tza_dac_q);
XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q);
kw41zrf_xcvr_spin(TsettleCal * 2);
rx_dc_est_samples(&dc_meas_i, &dc_meas_q, RX_DC_EST_SAMPLES);
dc_meas_i /= RX_DC_EST_SAMPLES;
dc_meas_q /= RX_DC_EST_SAMPLES;
}
/* Apply optimized DCOC DAC INIT : */
XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) |
XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q);
/* Restore register */
XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings */
XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings */
XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings */
XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting */
XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore */
}
static int kw41zrf_xcvr_configure(kw41zrf_t *dev,
const xcvr_common_config_t *com_config,
const xcvr_mode_config_t *mode_config,
const xcvr_mode_datarate_config_t *mode_datarate_config,
const xcvr_datarate_config_t *datarate_config)
{
(void)dev;
int config_status = 0;
uint32_t temp;
/* Turn on the module clocks before doing anything */
SIM->SCGC5 |= mode_config->scgc5_clock_ena_bits;
/* XCVR_ANA configs */
/* Configure PLL Loop Filter */
XCVR_ANA->SY_CTRL_1 &= ~com_config->ana_sy_ctrl1.mask;
XCVR_ANA->SY_CTRL_1 |= com_config->ana_sy_ctrl1.init;
/* Configure VCO KVM */
XCVR_ANA->SY_CTRL_2 &= ~mode_datarate_config->ana_sy_ctrl2.mask;
XCVR_ANA->SY_CTRL_2 |= mode_datarate_config->ana_sy_ctrl2.init;
/* Configure analog filter bandwidth */
XCVR_ANA->RX_BBA &= ~mode_datarate_config->ana_rx_bba.mask;
XCVR_ANA->RX_BBA |= mode_datarate_config->ana_rx_bba.init;
XCVR_ANA->RX_TZA &= ~mode_datarate_config->ana_rx_tza.mask;
XCVR_ANA->RX_TZA |= mode_datarate_config->ana_rx_tza.init;
temp = XCVR_ANA->TX_DAC_PA;
temp &= ~XCVR_ANALOG_TX_DAC_PA_TX_PA_BUMP_VBIAS_MASK;
temp |= XCVR_ANALOG_TX_DAC_PA_TX_PA_BUMP_VBIAS(4);
XCVR_ANA->TX_DAC_PA = temp;
temp = XCVR_ANA->BB_LDO_2;
temp &= ~XCVR_ANALOG_BB_LDO_2_BB_LDO_VCOLO_TRIM_MASK;
temp |= XCVR_ANALOG_BB_LDO_2_BB_LDO_VCOLO_TRIM(0);
XCVR_ANA->BB_LDO_2 = temp;
temp = XCVR_ANA->RX_LNA;
temp &= ~XCVR_ANALOG_RX_LNA_RX_LNA_BUMP_MASK;
temp |= XCVR_ANALOG_RX_LNA_RX_LNA_BUMP(1);
XCVR_ANA->RX_LNA = temp;
temp = XCVR_ANA->BB_LDO_1;
temp &= ~XCVR_ANALOG_BB_LDO_1_BB_LDO_FDBK_TRIM_MASK;
temp |= XCVR_ANALOG_BB_LDO_1_BB_LDO_FDBK_TRIM(1);
XCVR_ANA->BB_LDO_1 = temp;
/* XCVR_MISC configs */
temp = XCVR_MISC->XCVR_CTRL;
temp &= ~(mode_config->xcvr_ctrl.mask | XCVR_CTRL_XCVR_CTRL_REF_CLK_FREQ_MASK);
temp |= mode_config->xcvr_ctrl.init;
if (CLOCK_RADIOXTAL == 26000000ul) {
temp |= XCVR_CTRL_XCVR_CTRL_REF_CLK_FREQ(1);
}
XCVR_MISC->XCVR_CTRL = temp;
/* XCVR_PHY configs */
XCVR_PHY->PHY_PRE_REF0 = mode_config->phy_pre_ref0_init;
XCVR_PHY->PRE_REF1 = mode_config->phy_pre_ref1_init;
XCVR_PHY->PRE_REF2 = mode_config->phy_pre_ref2_init;
XCVR_PHY->CFG1 = mode_config->phy_cfg1_init;
XCVR_PHY->CFG2 = mode_datarate_config->phy_cfg2_init;
XCVR_PHY->EL_CFG = mode_config->phy_el_cfg_init | datarate_config->phy_el_cfg_init; /* EL_WIN_SIZE and EL_INTERVAL are datarate dependent, */
/* XCVR_PLL_DIG configs */
XCVR_PLL_DIG->HPM_BUMP = com_config->pll_hpm_bump;
XCVR_PLL_DIG->MOD_CTRL = com_config->pll_mod_ctrl;
XCVR_PLL_DIG->CHAN_MAP = com_config->pll_chan_map;
XCVR_PLL_DIG->LOCK_DETECT = com_config->pll_lock_detect;
XCVR_PLL_DIG->HPM_CTRL = com_config->pll_hpm_ctrl;
XCVR_PLL_DIG->HPMCAL_CTRL = com_config->pll_hpmcal_ctrl;
XCVR_PLL_DIG->HPM_SDM_RES = com_config->pll_hpm_sdm_res;
XCVR_PLL_DIG->LPM_CTRL = com_config->pll_lpm_ctrl;
XCVR_PLL_DIG->LPM_SDM_CTRL1 = com_config->pll_lpm_sdm_ctrl1;
XCVR_PLL_DIG->DELAY_MATCH = com_config->pll_delay_match;
XCVR_PLL_DIG->CTUNE_CTRL = com_config->pll_ctune_ctrl;
/* XCVR_RX_DIG configs */
/* Configure RF Aux PLL for proper operation based on external clock frequency */
temp = XCVR_ANA->RX_AUXPLL;
temp &= ~XCVR_ANALOG_RX_AUXPLL_VCO_DAC_REF_ADJUST_MASK;
if (CLOCK_RADIOXTAL == 26000000ul) {
temp |= XCVR_ANALOG_RX_AUXPLL_VCO_DAC_REF_ADJUST(4);
}
else {
temp |= XCVR_ANALOG_RX_AUXPLL_VCO_DAC_REF_ADJUST(7);
}
XCVR_ANA->RX_AUXPLL = temp;
/* Configure RX_DIG_CTRL */
if (CLOCK_RADIOXTAL == 26000000ul) {
temp = com_config->rx_dig_ctrl_init | /* Common portion of RX_DIG_CTRL init */
mode_config->rx_dig_ctrl_init_26mhz | /* Mode specific portion of RX_DIG_CTRL init */
datarate_config->rx_dig_ctrl_init_26mhz | /* Datarate specific portion of RX_DIG_CTRL init */
XCVR_RX_DIG_RX_DIG_CTRL_RX_SRC_EN_MASK; /* Always enable the sample rate converter for 26MHz */
}
else {
temp = com_config->rx_dig_ctrl_init | /* Common portion of RX_DIG_CTRL init */
mode_config->rx_dig_ctrl_init_32mhz | /* Mode specific portion of RX_DIG_CTRL init */
datarate_config->rx_dig_ctrl_init_32mhz | /* Datarate specific portion of RX_DIG_CTRL init */
0; /* Always disable the sample rate converter for 32MHz */
}
temp |= com_config->rx_dig_ctrl_init; /* Common portion of RX_DIG_CTRL init */
XCVR_RX_DIG->RX_DIG_CTRL = temp;
/* DCOC_CAL_IIR */
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_RX_DIG->DCOC_CAL_IIR = datarate_config->dcoc_cal_iir_init_26mhz;
}
else {
XCVR_RX_DIG->DCOC_CAL_IIR = datarate_config->dcoc_cal_iir_init_32mhz;
}
/* DC_RESID_CTRL */
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_RX_DIG->DC_RESID_CTRL = com_config->dc_resid_ctrl_init | datarate_config->dc_resid_ctrl_26mhz;
}
else {
XCVR_RX_DIG->DC_RESID_CTRL = com_config->dc_resid_ctrl_init | datarate_config->dc_resid_ctrl_32mhz;
}
/* DCOC_CTRL_0 & _1 */
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_RX_DIG->DCOC_CTRL_0 = com_config->dcoc_ctrl_0_init_26mhz | datarate_config->dcoc_ctrl_0_init_26mhz; /* Combine common and datarate specific settings */
XCVR_RX_DIG->DCOC_CTRL_1 = com_config->dcoc_ctrl_1_init | datarate_config->dcoc_ctrl_1_init_26mhz; /* Combine common and datarate specific settings */
/* customize DCOC_CTRL_0 settings for Gen2 GFSK BT=0.5, h=0.32 */
if ((mode_config->radio_mode == ANT_MODE) || (mode_config->radio_mode == GFSK_BT_0p5_h_0p32))
{
if (datarate_config->data_rate == DR_1MBPS) /* only apply fix to 1Mbps data rates */
{
/* apply the changes to the DCOC_CTRL_0 register XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY & XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME */
temp = XCVR_RX_DIG->DCOC_CTRL_0;
temp &= ~XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY_MASK | XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME_MASK;
temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(0x10) | XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(0x0C);
XCVR_RX_DIG->DCOC_CTRL_0 = temp;
}
}
}
else {
XCVR_RX_DIG->DCOC_CTRL_0 = com_config->dcoc_ctrl_0_init_32mhz | datarate_config->dcoc_ctrl_0_init_32mhz; /* Combine common and datarate specific settings */
XCVR_RX_DIG->DCOC_CTRL_1 = com_config->dcoc_ctrl_1_init | datarate_config->dcoc_ctrl_1_init_32mhz; /* Combine common and datarate specific settings */
}
/* DCOC_CAL_GAIN */
XCVR_RX_DIG->DCOC_CAL_GAIN = com_config->dcoc_cal_gain_init;
/* DCOC_CAL_RCP */
XCVR_RX_DIG->DCOC_CAL_RCP = com_config->dcoc_cal_rcp_init;
XCVR_RX_DIG->LNA_GAIN_VAL_3_0 = com_config->lna_gain_val_3_0;
XCVR_RX_DIG->LNA_GAIN_VAL_7_4 = com_config->lna_gain_val_7_4;
XCVR_RX_DIG->LNA_GAIN_VAL_8 = com_config->lna_gain_val_8;
XCVR_RX_DIG->BBA_RES_TUNE_VAL_7_0 = com_config->bba_res_tune_val_7_0;
XCVR_RX_DIG->BBA_RES_TUNE_VAL_10_8 = com_config->bba_res_tune_val_10_8;
/* LNA_GAIN_LIN_VAL */
XCVR_RX_DIG->LNA_GAIN_LIN_VAL_2_0 = com_config->lna_gain_lin_val_2_0_init;
XCVR_RX_DIG->LNA_GAIN_LIN_VAL_5_3 = com_config->lna_gain_lin_val_5_3_init;
XCVR_RX_DIG->LNA_GAIN_LIN_VAL_8_6 = com_config->lna_gain_lin_val_8_6_init;
XCVR_RX_DIG->LNA_GAIN_LIN_VAL_9 = com_config->lna_gain_lin_val_9_init;
/* BBA_RES_TUNE_LIN_VAL */
XCVR_RX_DIG->BBA_RES_TUNE_LIN_VAL_3_0 = com_config->bba_res_tune_lin_val_3_0_init;
XCVR_RX_DIG->BBA_RES_TUNE_LIN_VAL_7_4 = com_config->bba_res_tune_lin_val_7_4_init;
XCVR_RX_DIG->BBA_RES_TUNE_LIN_VAL_10_8 = com_config->bba_res_tune_lin_val_10_8_init;
/* BBA_STEP */
XCVR_RX_DIG->DCOC_BBA_STEP = com_config->dcoc_bba_step_init;
/* DCOC_TZA_STEP */
XCVR_RX_DIG->DCOC_TZA_STEP_0 = com_config->dcoc_tza_step_00_init;
XCVR_RX_DIG->DCOC_TZA_STEP_1 = com_config->dcoc_tza_step_01_init;
XCVR_RX_DIG->DCOC_TZA_STEP_2 = com_config->dcoc_tza_step_02_init;
XCVR_RX_DIG->DCOC_TZA_STEP_3 = com_config->dcoc_tza_step_03_init;
XCVR_RX_DIG->DCOC_TZA_STEP_4 = com_config->dcoc_tza_step_04_init;
XCVR_RX_DIG->DCOC_TZA_STEP_5 = com_config->dcoc_tza_step_05_init;
XCVR_RX_DIG->DCOC_TZA_STEP_6 = com_config->dcoc_tza_step_06_init;
XCVR_RX_DIG->DCOC_TZA_STEP_7 = com_config->dcoc_tza_step_07_init;
XCVR_RX_DIG->DCOC_TZA_STEP_8 = com_config->dcoc_tza_step_08_init;
XCVR_RX_DIG->DCOC_TZA_STEP_9 = com_config->dcoc_tza_step_09_init;
XCVR_RX_DIG->DCOC_TZA_STEP_10 = com_config->dcoc_tza_step_10_init;
/* AGC_CTRL_0 .. _3 */
XCVR_RX_DIG->AGC_CTRL_0 = com_config->agc_ctrl_0_init | mode_config->agc_ctrl_0_init;
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_RX_DIG->AGC_CTRL_1 = com_config->agc_ctrl_1_init_26mhz | datarate_config->agc_ctrl_1_init_26mhz; /* Combine common and datarate specific settings */
XCVR_RX_DIG->AGC_CTRL_2 = mode_datarate_config->agc_ctrl_2_init_26mhz;
}
else {
XCVR_RX_DIG->AGC_CTRL_1 = com_config->agc_ctrl_1_init_32mhz | datarate_config->agc_ctrl_1_init_32mhz; /* Combine common and datarate specific settings */
XCVR_RX_DIG->AGC_CTRL_2 = mode_datarate_config->agc_ctrl_2_init_32mhz;
}
XCVR_RX_DIG->AGC_CTRL_3 = com_config->agc_ctrl_3_init;
/* AGC_GAIN_TBL_** */
XCVR_RX_DIG->AGC_GAIN_TBL_03_00 = com_config->agc_gain_tbl_03_00_init;
XCVR_RX_DIG->AGC_GAIN_TBL_07_04 = com_config->agc_gain_tbl_07_04_init;
XCVR_RX_DIG->AGC_GAIN_TBL_11_08 = com_config->agc_gain_tbl_11_08_init;
XCVR_RX_DIG->AGC_GAIN_TBL_15_12 = com_config->agc_gain_tbl_15_12_init;
XCVR_RX_DIG->AGC_GAIN_TBL_19_16 = com_config->agc_gain_tbl_19_16_init;
XCVR_RX_DIG->AGC_GAIN_TBL_23_20 = com_config->agc_gain_tbl_23_20_init;
XCVR_RX_DIG->AGC_GAIN_TBL_26_24 = com_config->agc_gain_tbl_26_24_init;
/* RSSI_CTRL_0 */
XCVR_RX_DIG->RSSI_CTRL_0 = com_config->rssi_ctrl_0_init;
/* CCA_ED_LQI_0 and _1 */
XCVR_RX_DIG->CCA_ED_LQI_CTRL_0 = com_config->cca_ed_lqi_ctrl_0_init;
XCVR_RX_DIG->CCA_ED_LQI_CTRL_1 = com_config->cca_ed_lqi_ctrl_1_init;
/* Channel filter coefficients */
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_RX_DIG->RX_CHF_COEF_0 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_0;
XCVR_RX_DIG->RX_CHF_COEF_1 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_1;
XCVR_RX_DIG->RX_CHF_COEF_2 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_2;
XCVR_RX_DIG->RX_CHF_COEF_3 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_3;
XCVR_RX_DIG->RX_CHF_COEF_4 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_4;
XCVR_RX_DIG->RX_CHF_COEF_5 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_5;
XCVR_RX_DIG->RX_CHF_COEF_6 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_6;
XCVR_RX_DIG->RX_CHF_COEF_7 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_7;
XCVR_RX_DIG->RX_CHF_COEF_8 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_8;
XCVR_RX_DIG->RX_CHF_COEF_9 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_9;
XCVR_RX_DIG->RX_CHF_COEF_10 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_10;
XCVR_RX_DIG->RX_CHF_COEF_11 = mode_datarate_config->rx_chf_coeffs_26mhz.rx_chf_coef_11;
}
else {
XCVR_RX_DIG->RX_CHF_COEF_0 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_0;
XCVR_RX_DIG->RX_CHF_COEF_1 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_1;
XCVR_RX_DIG->RX_CHF_COEF_2 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_2;
XCVR_RX_DIG->RX_CHF_COEF_3 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_3;
XCVR_RX_DIG->RX_CHF_COEF_4 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_4;
XCVR_RX_DIG->RX_CHF_COEF_5 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_5;
XCVR_RX_DIG->RX_CHF_COEF_6 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_6;
XCVR_RX_DIG->RX_CHF_COEF_7 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_7;
XCVR_RX_DIG->RX_CHF_COEF_8 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_8;
XCVR_RX_DIG->RX_CHF_COEF_9 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_9;
XCVR_RX_DIG->RX_CHF_COEF_10 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_10;
XCVR_RX_DIG->RX_CHF_COEF_11 = mode_datarate_config->rx_chf_coeffs_32mhz.rx_chf_coef_11;
}
XCVR_RX_DIG->RX_RCCAL_CTRL0 = mode_datarate_config->rx_rccal_ctrl_0;
XCVR_RX_DIG->RX_RCCAL_CTRL1 = mode_datarate_config->rx_rccal_ctrl_1;
/* XCVR_TSM configs */
XCVR_TSM->CTRL = com_config->tsm_ctrl;
if ((mode_config->radio_mode != ZIGBEE_MODE) && (mode_config->radio_mode != BLE_MODE))
{
XCVR_TSM->CTRL &= ~XCVR_TSM_CTRL_DATA_PADDING_EN_MASK;
}
XCVR_MISC->LPPS_CTRL = com_config->lpps_ctrl_init; /* Register is in XCVR_MISC but grouped with TSM for initialization */
XCVR_TSM->OVRD2 = com_config->tsm_ovrd2_init;
/* TSM registers and timings - dependent upon clock frequency */
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_TSM->END_OF_SEQ = com_config->end_of_seq_init_26mhz;
XCVR_TSM->FAST_CTRL2 = com_config->tsm_fast_ctrl2_init_26mhz;
XCVR_TSM->RECYCLE_COUNT = com_config->recycle_count_init_26mhz;
XCVR_TSM->TIMING14 = com_config->tsm_timing_14_init_26mhz;
XCVR_TSM->TIMING16 = com_config->tsm_timing_16_init_26mhz;
XCVR_TSM->TIMING25 = com_config->tsm_timing_25_init_26mhz;
XCVR_TSM->TIMING27 = com_config->tsm_timing_27_init_26mhz;
XCVR_TSM->TIMING28 = com_config->tsm_timing_28_init_26mhz;
XCVR_TSM->TIMING29 = com_config->tsm_timing_29_init_26mhz;
XCVR_TSM->TIMING30 = com_config->tsm_timing_30_init_26mhz;
XCVR_TSM->TIMING31 = com_config->tsm_timing_31_init_26mhz;
XCVR_TSM->TIMING32 = com_config->tsm_timing_32_init_26mhz;
XCVR_TSM->TIMING33 = com_config->tsm_timing_33_init_26mhz;
XCVR_TSM->TIMING36 = com_config->tsm_timing_36_init_26mhz;
XCVR_TSM->TIMING37 = com_config->tsm_timing_37_init_26mhz;
XCVR_TSM->TIMING39 = com_config->tsm_timing_39_init_26mhz;
XCVR_TSM->TIMING40 = com_config->tsm_timing_40_init_26mhz;
XCVR_TSM->TIMING41 = com_config->tsm_timing_41_init_26mhz;
XCVR_TSM->TIMING52 = com_config->tsm_timing_52_init_26mhz;
XCVR_TSM->TIMING54 = com_config->tsm_timing_54_init_26mhz;
XCVR_TSM->TIMING55 = com_config->tsm_timing_55_init_26mhz;
XCVR_TSM->TIMING56 = com_config->tsm_timing_56_init_26mhz;
}
else {
XCVR_TSM->END_OF_SEQ = com_config->end_of_seq_init_32mhz;
XCVR_TSM->FAST_CTRL2 = com_config->tsm_fast_ctrl2_init_32mhz;
XCVR_TSM->RECYCLE_COUNT = com_config->recycle_count_init_32mhz;
XCVR_TSM->TIMING14 = com_config->tsm_timing_14_init_32mhz;
XCVR_TSM->TIMING16 = com_config->tsm_timing_16_init_32mhz;
XCVR_TSM->TIMING25 = com_config->tsm_timing_25_init_32mhz;
XCVR_TSM->TIMING27 = com_config->tsm_timing_27_init_32mhz;
XCVR_TSM->TIMING28 = com_config->tsm_timing_28_init_32mhz;
XCVR_TSM->TIMING29 = com_config->tsm_timing_29_init_32mhz;
XCVR_TSM->TIMING30 = com_config->tsm_timing_30_init_32mhz;
XCVR_TSM->TIMING31 = com_config->tsm_timing_31_init_32mhz;
XCVR_TSM->TIMING32 = com_config->tsm_timing_32_init_32mhz;
XCVR_TSM->TIMING33 = com_config->tsm_timing_33_init_32mhz;
XCVR_TSM->TIMING36 = com_config->tsm_timing_36_init_32mhz;
XCVR_TSM->TIMING37 = com_config->tsm_timing_37_init_32mhz;
XCVR_TSM->TIMING39 = com_config->tsm_timing_39_init_32mhz;
XCVR_TSM->TIMING40 = com_config->tsm_timing_40_init_32mhz;
XCVR_TSM->TIMING41 = com_config->tsm_timing_41_init_32mhz;
XCVR_TSM->TIMING52 = com_config->tsm_timing_52_init_32mhz;
XCVR_TSM->TIMING54 = com_config->tsm_timing_54_init_32mhz;
XCVR_TSM->TIMING55 = com_config->tsm_timing_55_init_32mhz;
XCVR_TSM->TIMING56 = com_config->tsm_timing_56_init_32mhz;
}
/* TSM timings independent of clock frequency */
XCVR_TSM->TIMING00 = com_config->tsm_timing_00_init;
XCVR_TSM->TIMING01 = com_config->tsm_timing_01_init;
XCVR_TSM->TIMING02 = com_config->tsm_timing_02_init;
XCVR_TSM->TIMING03 = com_config->tsm_timing_03_init;
XCVR_TSM->TIMING04 = com_config->tsm_timing_04_init;
XCVR_TSM->TIMING05 = com_config->tsm_timing_05_init;
XCVR_TSM->TIMING06 = com_config->tsm_timing_06_init;
XCVR_TSM->TIMING07 = com_config->tsm_timing_07_init;
XCVR_TSM->TIMING08 = com_config->tsm_timing_08_init;
XCVR_TSM->TIMING09 = com_config->tsm_timing_09_init;
XCVR_TSM->TIMING10 = com_config->tsm_timing_10_init;
XCVR_TSM->TIMING11 = com_config->tsm_timing_11_init;
XCVR_TSM->TIMING12 = com_config->tsm_timing_12_init;
XCVR_TSM->TIMING13 = com_config->tsm_timing_13_init;
XCVR_TSM->TIMING15 = com_config->tsm_timing_15_init;
XCVR_TSM->TIMING17 = com_config->tsm_timing_17_init;
XCVR_TSM->TIMING18 = com_config->tsm_timing_18_init;
XCVR_TSM->TIMING19 = com_config->tsm_timing_19_init;
XCVR_TSM->TIMING20 = com_config->tsm_timing_20_init;
XCVR_TSM->TIMING21 = com_config->tsm_timing_21_init;
XCVR_TSM->TIMING22 = com_config->tsm_timing_22_init;
XCVR_TSM->TIMING23 = com_config->tsm_timing_23_init;
XCVR_TSM->TIMING24 = com_config->tsm_timing_24_init;
XCVR_TSM->TIMING26 = com_config->tsm_timing_26_init;
XCVR_TSM->TIMING34 = com_config->tsm_timing_34_init;
XCVR_TSM->TIMING35 = com_config->tsm_timing_35_init;
XCVR_TSM->TIMING38 = com_config->tsm_timing_38_init;
XCVR_TSM->TIMING51 = com_config->tsm_timing_51_init;
XCVR_TSM->TIMING53 = com_config->tsm_timing_53_init;
XCVR_TSM->TIMING57 = com_config->tsm_timing_57_init;
XCVR_TSM->TIMING58 = com_config->tsm_timing_58_init;
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_TSM->END_OF_SEQ = XCVR_TSM_END_OF_SEQ_END_OF_TX_WU(END_OF_TX_WU) |
XCVR_TSM_END_OF_SEQ_END_OF_TX_WD(END_OF_TX_WD) |
XCVR_TSM_END_OF_SEQ_END_OF_RX_WU(END_OF_RX_WU_26MHZ) |
XCVR_TSM_END_OF_SEQ_END_OF_RX_WD(END_OF_RX_WD_26MHZ);
}
else {
XCVR_TSM->END_OF_SEQ = XCVR_TSM_END_OF_SEQ_END_OF_TX_WU(END_OF_TX_WU) |
XCVR_TSM_END_OF_SEQ_END_OF_TX_WD(END_OF_TX_WD) |
XCVR_TSM_END_OF_SEQ_END_OF_RX_WU(END_OF_RX_WU) |
XCVR_TSM_END_OF_SEQ_END_OF_RX_WD(END_OF_RX_WD);
}
XCVR_TSM->PA_RAMP_TBL0 = com_config->pa_ramp_tbl_0_init;
XCVR_TSM->PA_RAMP_TBL1 = com_config->pa_ramp_tbl_1_init;
if ((mode_datarate_config->radio_mode == MSK) && ((mode_datarate_config->data_rate == DR_500KBPS) || (mode_datarate_config->data_rate == DR_250KBPS))) {
/* Apply a specific value of TX_DIG_EN which assumes no DATA PADDING */
XCVR_TSM->TIMING35 = com_config->tsm_timing_35_init | B0(TX_DIG_EN_ASSERT_MSK500); /* LSbyte is mode specific */
}
else {
XCVR_TSM->TIMING35 = com_config->tsm_timing_35_init | mode_config->tsm_timing_35_init; /* LSbyte is mode specific, other bytes are common */
}
/* XCVR_TX_DIG configs */
if (CLOCK_RADIOXTAL == 26000000ul) {
XCVR_TX_DIG->FSK_SCALE = mode_datarate_config->tx_fsk_scale_26mhz; /* Applies only to 802.15.4 & MSK but won't harm other protocols */
XCVR_TX_DIG->GFSK_COEFF1 = mode_config->tx_gfsk_coeff1_26mhz;
XCVR_TX_DIG->GFSK_COEFF2 = mode_config->tx_gfsk_coeff2_26mhz;
}
else {
XCVR_TX_DIG->FSK_SCALE = mode_datarate_config->tx_fsk_scale_32mhz; /* Applies only to 802.15.4 & MSK but won't harm other protocols */
XCVR_TX_DIG->GFSK_COEFF1 = mode_config->tx_gfsk_coeff1_32mhz;
XCVR_TX_DIG->GFSK_COEFF2 = mode_config->tx_gfsk_coeff2_32mhz;
}
XCVR_TX_DIG->CTRL = com_config->tx_ctrl;
XCVR_TX_DIG->DATA_PADDING = com_config->tx_data_padding;
XCVR_TX_DIG->DFT_PATTERN = com_config->tx_dft_pattern;
XCVR_TX_DIG->RF_DFT_BIST_1 = com_config->rf_dft_bist_1;
XCVR_TX_DIG->RF_DFT_BIST_2 = com_config->rf_dft_bist_2;
XCVR_TX_DIG->GFSK_CTRL = mode_config->tx_gfsk_ctrl;
/* Force receiver warmup */
bit_set32(&XCVR_TSM->CTRL, XCVR_TSM_CTRL_FORCE_RX_EN_SHIFT);
/* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase) */
uint32_t end_of_rx_wu = XCVR_CTRL_XCVR_STATUS_TSM_COUNT(
(XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >>
XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT);
while ((XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) != end_of_rx_wu) {};
int res = kw41zrf_rx_bba_dcoc_dac_trim_DCest();
if (res < 0) {
config_status = res;
}
//~ DCOC_DAC_INIT_Cal(0);
kw41zrf_dcoc_dac_init_cal();
/* Force receiver warmdown */
bit_clear32(&XCVR_TSM->CTRL, XCVR_TSM_CTRL_FORCE_RX_EN_SHIFT);
return config_status;
}
int kw41zrf_xcvr_init(kw41zrf_t *dev)
{
(void) dev;
uint8_t radio_id = ((RSIM->MISC & RSIM_MISC_RADIO_VERSION_MASK) >> RSIM_MISC_RADIO_VERSION_SHIFT);
switch (radio_id) {
case 0x3: /* KW41/31/21 v1 */
case 0xb: /* KW41/31/21 v1.1 */
break;
default:
return -ENODEV;
}
RSIM->RF_OSC_CTRL = (RSIM->RF_OSC_CTRL &
~(RSIM_RF_OSC_CTRL_RADIO_EXT_OSC_OVRD_MASK)) | /* Set EXT_OSC_OVRD value to zero */
RSIM_RF_OSC_CTRL_RADIO_EXT_OSC_OVRD_EN_MASK; /* Enable over-ride with zero value */
bit_set32(&SIM->SCGC5, SIM_SCGC5_PHYDIG_SHIFT); /* Enable PHY clock gate */
/* Load IFR trim values */
IFR_SW_TRIM_TBL_ENTRY_T sw_trim_tbl[] =
{
{TRIM_STATUS, 0, 0}, /*< Fetch the trim status word if available.*/
{TRIM_VERSION, 0, 0} /*< Fetch the trim version number if available.*/
};
handle_ifr(&sw_trim_tbl[0], ARRAY_SIZE(sw_trim_tbl));
DEBUG("[kw41zrf] sw_trim_tbl:\n");
for (unsigned k = 0; k < ARRAY_SIZE(sw_trim_tbl); ++k) {
DEBUG("[kw41zrf] [%u] id=0x%04x ", k, (unsigned)sw_trim_tbl[k].trim_id);
if (sw_trim_tbl[k].trim_id == TRIM_STATUS) {
DEBUG("(TRIM_STATUS) ");
}
else if (sw_trim_tbl[k].trim_id == TRIM_VERSION) {
DEBUG("(TRIM_VERSION) ");
}
DEBUG("value=%" PRIu32 ", valid=%u\n", sw_trim_tbl[k].trim_value,
(unsigned)sw_trim_tbl[k].valid);
}
/* We only use 802.15.4 mode in this driver */
xcvrStatus_t status = kw41zrf_xcvr_configure(dev, &xcvr_common_config,
&zgbe_mode_config, &xcvr_ZIGBEE_500kbps_config, &xcvr_802_15_4_500kbps_config);
if (status != gXcvrSuccess_c) {
return -EIO;
}
return 0;
}

View File

@ -0,0 +1,616 @@
/*!
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* \file
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_OS_ABSTRACTION_H_
#define _FSL_OS_ABSTRACTION_H_
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "fsl_os_abstraction_config.h"
#ifdef __cplusplus
extern "C"
{
#endif
/*! *********************************************************************************
*************************************************************************************
* Public type definitions
*************************************************************************************
********************************************************************************** */
/*! @brief Type for the Task Priority*/
typedef uint16_t osaTaskPriority_t;
/*! @brief Type for the timer definition*/
typedef enum {
osaTimer_Once = 0, /*!< one-shot timer*/
osaTimer_Periodic = 1 /*!< repeating timer*/
} osaTimer_t;
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */
typedef void* osaTaskId_t;
/*! @brief Type for the parameter to be passed to the task at its creation */
typedef void* osaTaskParam_t;
/*! @brief Type for task pointer. Task prototype declaration */
typedef void (*osaTaskPtr_t) (osaTaskParam_t task_param);
/*! @brief Type for the semaphore handler, returned by the OSA_SemaphoreCreate function. */
typedef void* osaSemaphoreId_t;
/*! @brief Type for the mutex handler, returned by the OSA_MutexCreate function. */
typedef void* osaMutexId_t;
/*! @brief Type for the event handler, returned by the OSA_EventCreate function. */
typedef void* osaEventId_t;
/*! @brief Type for an event flags group, bit 32 is reserved. */
typedef uint32_t osaEventFlags_t;
/*! @brief Message definition. */
typedef void* osaMsg_t;
/*! @brief Type for the message queue handler, returned by the OSA_MsgQCreate function. */
typedef void* osaMsgQId_t;
/*! @brief Type for the Timer handler, returned by the OSA_TimerCreate function. */
typedef void *osaTimerId_t;
/*! @brief Type for the Timer callback function pointer. */
typedef void (*osaTimerFctPtr_t) (void const *argument);
/*! @brief Thread Definition structure contains startup information of a thread.*/
typedef struct osaThreadDef_tag {
osaTaskPtr_t pthread; /*!< start address of thread function*/
uint32_t tpriority; /*!< initial thread priority*/
uint32_t instances; /*!< maximum number of instances of that thread function*/
uint32_t stacksize; /*!< stack size requirements in bytes; 0 is default stack size*/
uint32_t *tstack;
void *tlink;
uint8_t *tname;
bool useFloat;
} osaThreadDef_t;
/*! @brief Thread Link Definition structure .*/
typedef struct osaThreadLink_tag{
uint8_t link[12];
osaTaskId_t osThreadId;
osaThreadDef_t *osThreadDefHandle;
uint32_t *osThreadStackHandle;
}osaThreadLink_t, *osaThreadLinkHandle_t;
/*! @Timer Definition structure contains timer parameters.*/
typedef struct osaTimerDef_tag {
osaTimerFctPtr_t pfCallback; /* < start address of a timer function */
void *argument;
} osaTimerDef_t;
/*! @brief Defines the return status of OSA's functions */
typedef enum osaStatus_tag
{
osaStatus_Success = 0U, /*!< Success */
osaStatus_Error = 1U, /*!< Failed */
osaStatus_Timeout = 2U, /*!< Timeout occurs while waiting */
osaStatus_Idle = 3U /*!< Used for bare metal only, the wait object is not ready
and timeout still not occur */
}osaStatus_t;
/*! *********************************************************************************
*************************************************************************************
* Public macros
*************************************************************************************
********************************************************************************** */
#if defined (FSL_RTOS_MQX)
#define USE_RTOS 1
#elif defined (FSL_RTOS_FREE_RTOS)
#define USE_RTOS 1
#elif defined (FSL_RTOS_UCOSII)
#define USE_RTOS 1
#elif defined (FSL_RTOS_UCOSIII)
#define USE_RTOS 1
#else
#define USE_RTOS 0
#endif
#define OSA_PRIORITY_IDLE (6)
#define OSA_PRIORITY_LOW (5)
#define OSA_PRIORITY_BELOW_NORMAL (4)
#define OSA_PRIORITY_NORMAL (3)
#define OSA_PRIORITY_ABOVE_NORMAL (2)
#define OSA_PRIORITY_HIGH (1)
#define OSA_PRIORITY_REAL_TIME (0)
#define OSA_TASK_PRIORITY_MAX (0)
#define OSA_TASK_PRIORITY_MIN (15)
#define SIZE_IN_UINT32_UNITS(size) (((size) + sizeof(uint32_t) - 1) / sizeof(uint32_t))
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
#define osaWaitForever_c ((uint32_t)(-1))
#define osaEventFlagsAll_c ((osaEventFlags_t)(0x00FFFFFF))
#define osThreadStackArray(name) osThread_##name##_stack
#define osThreadStackDef(name, stacksize, instances) \
uint32_t osThreadStackArray(name)[SIZE_IN_UINT32_UNITS(stacksize)*(instances)];
/* ==== Thread Management ==== */
/* Create a Thread Definition with function, priority, and stack requirements.
* \param name name of the thread function.
* \param priority initial priority of the thread function.
* \param instances number of possible thread instances.
* \param stackSz stack size (in bytes) requirements for the thread function.
* \param useFloat
*/
#if defined(FSL_RTOS_MQX)
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
osaThreadLink_t osThreadLink_##name[instances] = {0}; \
osThreadStackDef(name, stackSz, instances) \
osaThreadDef_t os_thread_def_##name = { (name), \
(priority), \
(instances), \
(stackSz), \
osThreadStackArray(name), \
osThreadLink_##name, \
(uint8_t*) #name,\
(useFloat)}
#elif defined (FSL_RTOS_UCOSII)
#if gTaskMultipleInstancesManagement_c
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
osaThreadLink_t osThreadLink_##name[instances] = {0}; \
osThreadStackDef(name, stackSz, instances) \
osaThreadDef_t os_thread_def_##name = { (name), \
(priority), \
(instances), \
(stackSz), \
osThreadStackArray(name), \
osThreadLink_##name, \
(uint8_t*) #name,\
(useFloat)}
#else
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
osThreadStackDef(name, stackSz, instances) \
osaThreadDef_t os_thread_def_##name = { (name), \
(priority), \
(instances), \
(stackSz), \
osThreadStackArray(name), \
NULL, \
(uint8_t*) #name,\
(useFloat)}
#endif
#else
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
osaThreadDef_t os_thread_def_##name = { (name), \
(priority), \
(instances), \
(stackSz), \
NULL, \
NULL, \
(uint8_t*) #name,\
(useFloat)}
#endif
/* Access a Thread defintion.
* \param name name of the thread definition object.
*/
#define OSA_TASK(name) \
&os_thread_def_##name
#define OSA_TASK_PROTO(name) \
extern osaThreadDef_t os_thread_def_##name
/* ==== Timer Management ====
* Define a Timer object.
* \param name name of the timer object.
* \param function name of the timer call back function.
*/
#define OSA_TIMER_DEF(name, function) \
osaTimerDef_t os_timer_def_##name = \
{ (function), NULL }
/* Access a Timer definition.
* \param name name of the timer object.
*/
#define OSA_TIMER(name) \
&os_timer_def_##name
/*****************************************************************************
******************************************************************************
* Public memory declarations
******************************************************************************
*****************************************************************************/
extern const uint8_t gUseRtos_c;
/*! *********************************************************************************
*************************************************************************************
* Public functions
*************************************************************************************
********************************************************************************** */
/*!
* @name Task management
* @{
*/
/*!
* @brief Creates a task.
*
* This function is used to create task based on the resources defined
* by the macro OSA_TASK_DEFINE.
*
* @param thread_def pointer to the osaThreadDef_t structure which defines the task.
* @param task_param Pointer to be passed to the task when it is created.
*
* @retval taskId The task is successfully created.
* @retval NULL The task can not be created..
*
* Example:
@code
osaTaskId_t taskId;
OSA_TASK_DEFINE( Job1, OSA_PRIORITY_HIGH, 1, 800, 0);;
taskId = OSA__TaskCreate(OSA__TASK(Job1), (osaTaskParam_t)NULL);
@endcode
*/
osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def, osaTaskParam_t task_param);
/*!
* @brief Gets the handler of active task.
*
* @return Handler to current active task.
*/
osaTaskId_t OSA_TaskGetId(void);
/*!
* @brief Puts the active task to the end of scheduler's queue.
*
* When a task calls this function, it gives up the CPU and puts itself to the
* end of a task ready list.
*
* @retval osaStatus_Success The function is called successfully.
* @retval osaStatus_Error Error occurs with this function.
*/
osaStatus_t OSA_TaskYield(void);
/*!
* @brief Gets the priority of a task.
*
* @param taskId The handler of the task whose priority is received.
*
* @return Task's priority.
*/
osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId);
/*!
* @brief Sets the priority of a task.
*
* @param taskId The handler of the task whose priority is set.
* @param taskPriority The priority to set.
*
* @retval osaStatus_Success Task's priority is set successfully.
* @retval osaStatus_Error Task's priority can not be set.
*/
osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority);
/*!
* @brief Destroys a previously created task.
*
* @param taskId The handler of the task to destroy. Returned by the OSA_TaskCreate function.
*
* @retval osaStatus_Success The task was successfully destroyed.
* @retval osaStatus_Error Task destruction failed or invalid parameter.
*/
osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId);
/*!
* @brief Creates a semaphore with a given value.
*
* This function creates a semaphore and sets the value to the parameter
* initValue.
*
* @param initValue Initial value the semaphore will be set to.
*
* @retval handler to the new semaphore if the semaphore is created successfully.
* @retval NULL if the semaphore can not be created.
*
*
*/
osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue);
/*!
* @brief Destroys a previously created semaphore.
*
* @param semId Pointer to the semaphore to destroy.
*
* @retval osaStatus_Success The semaphore is successfully destroyed.
* @retval osaStatus_Error The semaphore can not be destroyed.
*/
osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId);
/*!
* @brief Pending a semaphore with timeout.
*
* This function checks the semaphore's counting value. If it is positive,
* decreases it and returns osaStatus_Success. Otherwise, a timeout is used
* to wait.
*
* @param semId Pointer to the semaphore.
* @param millisec The maximum number of milliseconds to wait if semaphore is not
* positive. Pass osaWaitForever_c to wait indefinitely, pass 0
* will return osaStatus_Timeout immediately.
*
* @retval osaStatus_Success The semaphore is received.
* @retval osaStatus_Timeout The semaphore is not received within the specified 'timeout'.
* @retval osaStatus_Error An incorrect parameter was passed.
*/
osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec);
/*!
* @brief Signals for someone waiting on the semaphore to wake up.
*
* Wakes up one task that is waiting on the semaphore. If no task is waiting, increases
* the semaphore's counting value.
*
* @param semId Pointer to the semaphore to signal.
*
* @retval osaStatus_Success The semaphore is successfully signaled.
* @retval osaStatus_Error The object can not be signaled or invalid parameter.
*
*/
osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId);
/*!
* @brief Create an unlocked mutex.
*
* This function creates a non-recursive mutex and sets it to unlocked status.
*
* @param none.
*
* @retval handler to the new mutex if the mutex is created successfully.
* @retval NULL if the mutex can not be created.
*/
osaMutexId_t OSA_MutexCreate(void);
/*!
* @brief Waits for a mutex and locks it.
*
* This function checks the mutex's status. If it is unlocked, locks it and returns the
* osaStatus_Success. Otherwise, waits for a timeout in milliseconds to lock.
*
* @param mutexId Pointer to the Mutex.
* @param millisec The maximum number of milliseconds to wait for the mutex.
* If the mutex is locked, Pass the value osaWaitForever_c will
* wait indefinitely, pass 0 will return osaStatus_Timeout
* immediately.
*
* @retval osaStatus_Success The mutex is locked successfully.
* @retval osaStatus_Timeout Timeout occurred.
* @retval osaStatus_Error Incorrect parameter was passed.
*
* @note This is non-recursive mutex, a task can not try to lock the mutex it has locked.
*/
osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec);
/*!
* @brief Unlocks a previously locked mutex.
*
* @param mutexId Pointer to the Mutex.
*
* @retval osaStatus_Success The mutex is successfully unlocked.
* @retval osaStatus_Error The mutex can not be unlocked or invalid parameter.
*/
osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId);
/*!
* @brief Destroys a previously created mutex.
*
* @param mutexId Pointer to the Mutex.
*
* @retval osaStatus_Success The mutex is successfully destroyed.
* @retval osaStatus_Error The mutex can not be destroyed.
*
*/
osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId);
/*!
* @brief Initializes an event object with all flags cleared.
*
* This function creates an event object and set its clear mode. If autoClear
* is TRUE, when a task gets the event flags, these flags will be
* cleared automatically. Otherwise these flags must
* be cleared manually.
*
* @param autoClear TRUE The event is auto-clear.
* FALSE The event manual-clear
* @retval handler to the new event if the event is created successfully.
* @retval NULL if the event can not be created.
*/
osaEventId_t OSA_EventCreate(bool autoClear);
/*!
* @brief Sets one or more event flags.
*
* Sets specified flags of an event object.
*
* @param eventId Pointer to the event.
* @param flagsToSet Flags to be set.
*
* @retval osaStatus_Success The flags were successfully set.
* @retval osaStatus_Error An incorrect parameter was passed.
*/
osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet);
/*!
* @brief Clears one or more flags.
*
* Clears specified flags of an event object.
*
* @param eventId Pointer to the event.
* @param flagsToClear Flags to be clear.
*
* @retval osaStatus_Success The flags were successfully cleared.
* @retval osaStatus_Error An incorrect parameter was passed.
*/
osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear);
/*!
* @brief Waits for specified event flags to be set.
*
* This function waits for a combination of flags to be set in an event object.
* Applications can wait for any/all bits to be set. Also this function could
* obtain the flags who wakeup the waiting task.
*
* @param eventId Pointer to the event.
* @param flagsToWait Flags that to wait.
* @param waitAll Wait all flags or any flag to be set.
* @param millisec The maximum number of milliseconds to wait for the event.
* If the wait condition is not met, pass osaWaitForever_c will
* wait indefinitely, pass 0 will return osaStatus_Timeout
* immediately.
* @param setFlags Flags that wakeup the waiting task are obtained by this parameter.
*
* @retval osaStatus_Success The wait condition met and function returns successfully.
* @retval osaStatus_Timeout Has not met wait condition within timeout.
* @retval osaStatus_Error An incorrect parameter was passed.
*
* @note Please pay attention to the flags bit width, FreeRTOS uses the most
* significant 8 bis as control bits, so do not wait these bits while using
* FreeRTOS.
*
*/
osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags);
/*!
* @brief Destroys a previously created event object.
*
* @param eventId Pointer to the event.
*
* @retval osaStatus_Success The event is successfully destroyed.
* @retval osaStatus_Error Event destruction failed.
*/
osaStatus_t OSA_EventDestroy(osaEventId_t eventId);
/*!
* @brief Initializes a message queue.
*
* This function allocates memory for and initializes a message queue. Message queue elements are hardcoded as void*.
*
* @param msgNo :number of messages the message queue should accommodate.
* This parameter should not exceed osNumberOfMessages defined in OSAbstractionConfig.h.
*
* @return: Handler to access the queue for put and get operations. If message queue
* creation failed, return NULL.
*/
osaMsgQId_t OSA_MsgQCreate(uint32_t msgNo);
/*!
* @brief Puts a message at the end of the queue.
*
* This function puts a message to the end of the message queue. If the queue
* is full, this function returns the osaStatus_Error;
*
* @param msgQId pointer to queue returned by the OSA_MsgQCreate function.
* @param pMessage Pointer to the message to be put into the queue.
*
* @retval osaStatus_Success Message successfully put into the queue.
* @retval osaStatus_Error The queue was full or an invalid parameter was passed.
*/
osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, osaMsg_t pMessage);
/*!
* @brief Reads and remove a message at the head of the queue.
*
* This function gets a message from the head of the message queue. If the
* queue is empty, timeout is used to wait.
*
* @param msgQId Queue handler returned by the OSA_MsgQCreate function.
* @param pMessage Pointer to a memory to save the message.
* @param millisec The number of milliseconds to wait for a message. If the
* queue is empty, pass osaWaitForever_c will wait indefinitely,
* pass 0 will return osaStatus_Timeout immediately.
*
* @retval osaStatus_Success Message successfully obtained from the queue.
* @retval osaStatus_Timeout The queue remains empty after timeout.
* @retval osaStatus_Error Invalid parameter.
*/
osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, osaMsg_t pMessage, uint32_t millisec);
/*!
* @brief Destroys a previously created queue.
*
* @param msgQId queue handler returned by the OSA_MsgQCreate function.
*
* @retval osaStatus_Success The queue was successfully destroyed.
* @retval osaStatus_Error Message queue destruction failed.
*/
osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId);
/*!
* @brief Enable all interrupts.
*/
void OSA_InterruptEnable(void);
/*!
* @brief Disable all interrupts.
*/
void OSA_InterruptDisable(void);
/*!
* @brief Enable all interrupts using PRIMASK.
*/
void OSA_EnableIRQGlobal(void);
/*!
* @brief Disable all interrupts using PRIMASK.
*/
void OSA_DisableIRQGlobal(void);
/*!
* @brief Delays execution for a number of milliseconds.
*
* @param millisec The time in milliseconds to wait.
*/
void OSA_TimeDelay(uint32_t millisec);
/*!
* @brief This function gets current time in milliseconds.
*
* @retval current time in milliseconds
*/
uint32_t OSA_TimeGetMsec(void);
/*!
* @brief Installs the interrupt handler.
*
* @param IRQNumber IRQ number of the interrupt.
* @param handler The interrupt handler to install.
*/
void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void));
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,78 @@
/*!
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* \file
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_OS_ABSTRACTION_CONFIG_H_
#define _FSL_OS_ABSTRACTION_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef osNumberOfSemaphores
#define osNumberOfSemaphores 5
#endif
#ifndef osNumberOfMutexes
#define osNumberOfMutexes 5
#endif
#ifndef osNumberOfMessageQs
#define osNumberOfMessageQs 0
#endif
#ifndef osNumberOfMessages
#define osNumberOfMessages 10
#endif
#ifndef osNumberOfEvents
#define osNumberOfEvents 5
#endif
#ifndef gMainThreadStackSize_c
#define gMainThreadStackSize_c 1024
#endif
#ifndef gMainThreadPriority_c
#define gMainThreadPriority_c 7
#endif
#ifndef gTaskMultipleInstancesManagement_c
#define gTaskMultipleInstancesManagement_c 0
#endif
#ifdef __cplusplus
}
#endif
#endif /* _FSL_OS_ABSTRACTION_CONFIG_H_ */

View File

@ -0,0 +1,8 @@
MODULE = mcux_xcvr_mkw41z
# This vendor code expect all the vendor headers to also be in the include path
# These include paths are only added when building this particular directory and
# should not be available to the rest of the system.
INCLUDES += -I../../OSAbstraction/Interface
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,27 @@
#include "irq.h"
#include "fsl_os_abstraction.h"
static unsigned int irq_mask;
/*FUNCTION**********************************************************************
*
* Function Name : OSA_InterruptEnable
* Description : self explanatory.
*
*END**************************************************************************/
void OSA_InterruptEnable(void)
{
irq_restore(irq_mask);
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_InterruptDisable
* Description : self explanatory.
*
*END**************************************************************************/
void OSA_InterruptDisable(void)
{
irq_mask = irq_disable();
}

View File

@ -0,0 +1,833 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_XCVR_H_
/* clang-format off */
#define _FSL_XCVR_H_
/* clang-format on */
#include "cpu.h"
/*!
* @addtogroup xcvr
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* KW4xZ/KW3xZ/KW2xZ Radio type */
#define RADIO_IS_GEN_2P0 (1)
#if (CLOCK_RADIOXTAL == 26000000ul)
#define RF_OSC_26MHZ 1
#endif
#define TBD_ZERO (0)
#define FSL_XCVR_DRIVER_VERSION (MAKE_VERSION(0, 1, 0))
#define B0(x) (((uint32_t)(((uint32_t)(x)) << 0)) & 0xFFU)
#define B1(x) (((uint32_t)(((uint32_t)(x)) << 8)) & 0xFF00U)
#define B2(x) (((uint32_t)(((uint32_t)(x)) << 16)) & 0xFF0000U)
#define B3(x) (((uint32_t)(((uint32_t)(x)) << 24)) & 0xFF000000U)
#define USE_DEFAULT_PRE_REF (0)
#define TRIM_BBA_DCOC_DAC_AT_INIT (1)
#define PRESLOW_ENA (1)
/* GEN3 TSM defines */
#if RADIO_IS_GEN_3P0
/* TSM timings initializations for Gen3 radio */
/* NOTE: These timings are stored in 32MHz or 26MHz "baseline" settings, selected by conditional compile below */
/* The init structures for 32Mhz and 26MHz are made identical to allow the same code in fsl_xcvr.c to apply the */
/* settings for all radio generations. The Gen2 radio init value storage had a different structure so this preserves compatibility */
#if RF_OSC_26MHZ == 1
#define TSM_TIMING00init (0x6d006f00U) /* (bb_ldo_hf_en) */
#define TSM_TIMING01init (0x6d006f00U) /* (bb_ldo_adcdac_en) */
#define TSM_TIMING02init (0x6d00ffffU) /* (bb_ldo_bba_en) */
#define TSM_TIMING03init (0x6d006f00U) /* (bb_ldo_pd_en) */
#define TSM_TIMING04init (0x6d006f00U) /* (bb_ldo_fdbk_en) */
#define TSM_TIMING05init (0x6d006f00U) /* (bb_ldo_vcolo_en) */
#define TSM_TIMING06init (0x6d006f00U) /* (bb_ldo_vtref_en) */
#define TSM_TIMING07init (0x05000500U) /* (bb_ldo_fdbk_bleed_en) */
#define TSM_TIMING08init (0x03000300U) /* (bb_ldo_vcolo_bleed_en) */
#define TSM_TIMING09init (0x03000300U) /* (bb_ldo_vcolo_fastcharge_en) */
#define TSM_TIMING10init (0x6d036f03U) /* (bb_xtal_pll_ref_clk_en) */
#define TSM_TIMING11init (0xffff6f03U) /* (bb_xtal_dac_ref_clk_en) */
#define TSM_TIMING12init (0x6d03ffffU) /* (rxtx_auxpll_vco_ref_clk_en) */
#define TSM_TIMING13init (0x18004c00U) /* (sy_vco_autotune_en) */
#define TSM_TIMING14init (0x6d356863U) /* (sy_pd_cycle_slip_ld_ft_en) */
#define TSM_TIMING15init (0x6d036f03U) /* (sy_vco_en) */
#define TSM_TIMING16init (0x6d20ffffU) /* (sy_lo_rx_buf_en) */
#define TSM_TIMING17init (0xffff6f58U) /* (sy_lo_tx_buf_en) */
#define TSM_TIMING18init (0x6d056f05U) /* (sy_divn_en) */
#define TSM_TIMING19init (0x18034c03U) /* (sy_pd_filter_charge_en) */
#define TSM_TIMING20init (0x6d036f03U) /* (sy_pd_en) */
#define TSM_TIMING21init (0x6d046f04U) /* (sy_lo_divn_en) */
#define TSM_TIMING22init (0x6d04ffffU) /* (sy_lo_rx_en) */
#define TSM_TIMING23init (0xffff6f04U) /* (sy_lo_tx_en) */
#define TSM_TIMING24init (0x18004c00U) /* (sy_divn_cal_en) */
#define TSM_TIMING25init (0x6d21ffffU) /* (rx_lna_mixer_en) */
#define TSM_TIMING26init (0xffff6e58U) /* (tx_pa_en) */
#define TSM_TIMING27init (0x6d24ffffU) /* (rx_adc_i_q_en) */
#define TSM_TIMING28init (0x2524ffffU) /* (rx_adc_reset_en) */
#define TSM_TIMING29init (0x6d22ffffU) /* (rx_bba_i_q_en) */
#define TSM_TIMING30init (0x6d24ffffU) /* (rx_bba_pdet_en) */
#define TSM_TIMING31init (0x6d23ffffU) /* (rx_bba_tza_dcoc_en) */
#define TSM_TIMING32init (0x6d21ffffU) /* (rx_tza_i_q_en) */
#define TSM_TIMING33init (0x6d24ffffU) /* (rx_tza_pdet_en) */
#define TSM_TIMING34init (0x6d076f07U) /* (pll_dig_en) */
#define TSM_TIMING35init (0xffff6f5fU) /* (tx_dig_en) */
#define TSM_TIMING36init (0x6d6affffU) /* (rx_dig_en) */
#define TSM_TIMING37init (0x6b6affffU) /* (rx_init) */
#define TSM_TIMING38init (0x6d0e6f42U) /* (sigma_delta_en) */
#define TSM_TIMING39init (0x6d6affffU) /* (rx_phy_en) */
#define TSM_TIMING40init (0x6d2affffU) /* (dcoc_en) */
#define TSM_TIMING41init (0x2b2affffU) /* (dcoc_init) */
#define TSM_TIMING42init (0xffffffffU) /* (sar_adc_trig_en) */
#define TSM_TIMING43init (0xffffffffU) /* (tsm_spare0_en) */
#define TSM_TIMING44init (0xffffffffU) /* (tsm_spare1_en) */
#define TSM_TIMING45init (0xffffffffU) /* (tsm_spare2_en) */
#define TSM_TIMING46init (0xffffffffU) /* (tsm_spare3_en) */
#define TSM_TIMING47init (0xffffffffU) /* (gpio0_trig_en) */
#define TSM_TIMING48init (0xffffffffU) /* (gpio1_trig_en) */
#define TSM_TIMING49init (0xffffffffU) /* (gpio2_trig_en) */
#define TSM_TIMING50init (0xffffffffU) /* (gpio3_trig_en) */
#define TSM_TIMING51init (0x6d03ffffU) /* (rxtx_auxpll_bias_en) */
#define TSM_TIMING52init (0x1b06ffffU) /* (rxtx_auxpll_fcal_en) */
#define TSM_TIMING53init (0x6d03ffffU) /* (rxtx_auxpll_lf_pd_en) */
#define TSM_TIMING54init (0x1b03ffffU) /* (rxtx_auxpll_pd_lf_filter_charge_en) */
#define TSM_TIMING55init (0x6d24ffffU) /* (rxtx_auxpll_adc_buf_en) */
#define TSM_TIMING56init (0x6d24ffffU) /* (rxtx_auxpll_dig_buf_en) */
#define TSM_TIMING57init (0x1a03ffffU) /* (rxtx_rccal_en) */
#define TSM_TIMING58init (0xffff6f03U) /* (tx_hpm_dac_en) */
#define END_OF_SEQinit (0x6d6c6f67U) /* */
#define TX_RX_ON_DELinit (0x00008a86U) /* */
#define TX_RX_SYNTH_init (0x00002318U) /* */
#else
#define TSM_TIMING00init (0x69006f00U) /* (bb_ldo_hf_en) */
#define TSM_TIMING01init (0x69006f00U) /* (bb_ldo_adcdac_en) */
#define TSM_TIMING02init (0x6900ffffU) /* (bb_ldo_bba_en) */
#define TSM_TIMING03init (0x69006f00U) /* (bb_ldo_pd_en) */
#define TSM_TIMING04init (0x69006f00U) /* (bb_ldo_fdbk_en) */
#define TSM_TIMING05init (0x69006f00U) /* (bb_ldo_vcolo_en) */
#define TSM_TIMING06init (0x69006f00U) /* (bb_ldo_vtref_en) */
#define TSM_TIMING07init (0x05000500U) /* (bb_ldo_fdbk_bleed_en) */
#define TSM_TIMING08init (0x03000300U) /* (bb_ldo_vcolo_bleed_en) */
#define TSM_TIMING09init (0x03000300U) /* (bb_ldo_vcolo_fastcharge_en) */
#define TSM_TIMING10init (0x69036f03U) /* (bb_xtal_pll_ref_clk_en) */
#define TSM_TIMING11init (0xffff6f03U) /* (bb_xtal_dac_ref_clk_en) */
#define TSM_TIMING12init (0x6903ffffU) /* (rxtx_auxpll_vco_ref_clk_en) */
#define TSM_TIMING13init (0x18004c00U) /* (sy_vco_autotune_en) */
#define TSM_TIMING14init (0x69316863U) /* (sy_pd_cycle_slip_ld_ft_en) */
#define TSM_TIMING15init (0x69036f03U) /* (sy_vco_en) */
#define TSM_TIMING16init (0x691cffffU) /* (sy_lo_rx_buf_en) */
#define TSM_TIMING17init (0xffff6f58U) /* (sy_lo_tx_buf_en) */
#define TSM_TIMING18init (0x69056f05U) /* (sy_divn_en) */
#define TSM_TIMING19init (0x18034c03U) /* (sy_pd_filter_charge_en) */
#define TSM_TIMING20init (0x69036f03U) /* (sy_pd_en) */
#define TSM_TIMING21init (0x69046f04U) /* (sy_lo_divn_en) */
#define TSM_TIMING22init (0x6904ffffU) /* (sy_lo_rx_en) */
#define TSM_TIMING23init (0xffff6f04U) /* (sy_lo_tx_en) */
#define TSM_TIMING24init (0x18004c00U) /* (sy_divn_cal_en) */
#define TSM_TIMING25init (0x691dffffU) /* (rx_lna_mixer_en) */
#define TSM_TIMING26init (0xffff6e58U) /* (tx_pa_en) */
#define TSM_TIMING27init (0x6920ffffU) /* (rx_adc_i_q_en) */
#define TSM_TIMING28init (0x2120ffffU) /* (rx_adc_reset_en) */
#define TSM_TIMING29init (0x691effffU) /* (rx_bba_i_q_en) */
#define TSM_TIMING30init (0x6920ffffU) /* (rx_bba_pdet_en) */
#define TSM_TIMING31init (0x691fffffU) /* (rx_bba_tza_dcoc_en) */
#define TSM_TIMING32init (0x691dffffU) /* (rx_tza_i_q_en) */
#define TSM_TIMING33init (0x6920ffffU) /* (rx_tza_pdet_en) */
#define TSM_TIMING34init (0x69076f07U) /* (pll_dig_en) */
#define TSM_TIMING35init (0xffff6f5fU) /* (tx_dig_en) */
#define TSM_TIMING36init (0x6966ffffU) /* (rx_dig_en) */
#define TSM_TIMING37init (0x6766ffffU) /* (rx_init) */
#define TSM_TIMING38init (0x690e6f42U) /* (sigma_delta_en) */
#define TSM_TIMING39init (0x6966ffffU) /* (rx_phy_en) */
#define TSM_TIMING40init (0x6926ffffU) /* (dcoc_en) */
#define TSM_TIMING41init (0x2726ffffU) /* (dcoc_init) */
#define TSM_TIMING42init (0xffffffffU) /* (sar_adc_trig_en) */
#define TSM_TIMING43init (0xffffffffU) /* (tsm_spare0_en) */
#define TSM_TIMING44init (0xffffffffU) /* (tsm_spare1_en) */
#define TSM_TIMING45init (0xffffffffU) /* (tsm_spare2_en) */
#define TSM_TIMING46init (0xffffffffU) /* (tsm_spare3_en) */
#define TSM_TIMING47init (0xffffffffU) /* (gpio0_trig_en) */
#define TSM_TIMING48init (0xffffffffU) /* (gpio1_trig_en) */
#define TSM_TIMING49init (0xffffffffU) /* (gpio2_trig_en) */
#define TSM_TIMING50init (0xffffffffU) /* (gpio3_trig_en) */
#define TSM_TIMING51init (0x6903ffffU) /* (rxtx_auxpll_bias_en) */
#define TSM_TIMING52init (0x1706ffffU) /* (rxtx_auxpll_fcal_en) */
#define TSM_TIMING53init (0x6903ffffU) /* (rxtx_auxpll_lf_pd_en) */
#define TSM_TIMING54init (0x1703ffffU) /* (rxtx_auxpll_pd_lf_filter_charge_en) */
#define TSM_TIMING55init (0x6920ffffU) /* (rxtx_auxpll_adc_buf_en) */
#define TSM_TIMING56init (0x6920ffffU) /* (rxtx_auxpll_dig_buf_en) */
#define TSM_TIMING57init (0x1a03ffffU) /* (rxtx_rccal_en) */
#define TSM_TIMING58init (0xffff6f03U) /* (tx_hpm_dac_en) */
#define END_OF_SEQinit (0x69686f67U) /* */
#define TX_RX_ON_DELinit (0x00008a86U) /* */
#define TX_RX_SYNTH_init (0x00002318U) /* */
#endif /* RF_OSC_26MHZ == 1 */
#define AUX_PLL_DELAY (0)
/* TSM bitfield shift and value definitions */
#define TX_DIG_EN_ASSERT (95) /* Assertion time for TX_DIG_EN, used in mode specific settings */
#define ZGBE_TX_DIG_EN_ASSERT (TX_DIG_EN_ASSERT - 1) /* Zigbee TX_DIG_EN must assert 1 tick sooner, see adjustment below based on data padding */
/* EDIT THIS LINE TO CONTROL PA_RAMP! */
#define PA_RAMP_TIME (2) /* Only allowable values are [0, 1, 2, or 4] in Gen3 */
#define PA_RAMP_SEL_0US (0)
#define PA_RAMP_SEL_1US (1)
#define PA_RAMP_SEL_2US (2)
#define PA_RAMP_SEL_4US (3)
#if !((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 1) || (PA_RAMP_TIME == 2) || (PA_RAMP_TIME == 4))
#error "Invalid value for PA_RAMP_TIME macro"
#endif /* Error check of PA RAMP TIME */
#define ADD_FOR_26MHZ (4)
#define END_OF_TX_WU_NORAMP (103) /* NOTE: NORAMP and 2us ramp time behaviors are identical for TX WU and WD */
#define END_OF_TX_WD_NORAMP (111) /* NOTE: NORAMP and 2us ramp time behaviors are identical for TX WU and WD */
/* Redefine the values of END_OF_TX_WU and END_OF_TX_WD based on whether DATA PADDING is enabled and the selection of ramp time */
/* These two constants are then used on both common configuration and mode specific configuration files to define the TSM timing values */
#if ((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 1) || (PA_RAMP_TIME == 2))
#define END_OF_TX_WU (END_OF_TX_WU_NORAMP)
#define END_OF_TX_WD (END_OF_TX_WD_NORAMP)
#if (PA_RAMP_TIME == 0)
#define PA_RAMP_SEL PA_RAMP_SEL_0US
#define DATA_PADDING_EN (0)
#else
#define DATA_PADDING_EN (1)
#if (PA_RAMP_TIME == 1)
#define PA_RAMP_SEL PA_RAMP_SEL_1US
#else
#define PA_RAMP_SEL PA_RAMP_SEL_2US
#endif /* (PA_RAMP_TIME == 1) */
#endif /* (PA_RAMP_TIME == 0) */
#else /* ((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 1) || (PA_RAMP_TIME == 2)) */
#if (PA_RAMP_TIME == 4)
#define END_OF_TX_WU (END_OF_TX_WU_NORAMP + 2)
#define END_OF_TX_WD (END_OF_TX_WD_NORAMP + 4)
#define PA_RAMP_SEL PA_RAMP_SEL_4US
#define DATA_PADDING_EN (1)
#else /* (PA_RAMP_TIME == 4) */
#error "Invalid value for PA_RAMP_TIME macro"
#endif /* (PA_RAMP_TIME == 4) */
#endif/* (PA_RAMP_TIME == 4) */
#define END_OF_RX_WU (104 + AUX_PLL_DELAY)
#if RF_OSC_26MHZ == 1
#define END_OF_RX_WD (END_OF_RX_WU + 1 + ADD_FOR_26MHZ) /* Need to handle normal signals extending when 26MHZ warmdown is extended */
#else
#define END_OF_RX_WD (END_OF_RX_WU + 1)
#endif /* RF_OSC_26MHZ == 1 */
#define END_OF_RX_WU_26MHZ (END_OF_RX_WU + ADD_FOR_26MHZ)
#define END_OF_RX_WD_26MHZ (END_OF_RX_WU + 1 + ADD_FOR_26MHZ)
/* PA Bias Table - Gen3 version */
#define PA_RAMP_0 0x1
#define PA_RAMP_1 0x2
#define PA_RAMP_2 0x4
#define PA_RAMP_3 0x6
#define PA_RAMP_4 0x8
#define PA_RAMP_5 0xc
#define PA_RAMP_6 0x10
#define PA_RAMP_7 0x14
#define PA_RAMP_8 0x18
#define PA_RAMP_9 0x1c
#define PA_RAMP_10 0x22
#define PA_RAMP_11 0x28
#define PA_RAMP_12 0x2c
#define PA_RAMP_13 0x30
#define PA_RAMP_14 0x36
#define PA_RAMP_15 0x3c
#else /* Gen2 TSM definitions */
/* GEN2 TSM defines */
#define AUX_PLL_DELAY (0)
/* TSM bitfield shift and value definitions */
#define TX_DIG_EN_ASSERT (95) /* Assertion time for TX_DIG_EN, used in mode specific settings */
#define ZGBE_TX_DIG_EN_ASSERT (TX_DIG_EN_ASSERT - 1) /* Zigbee TX_DIG_EN must assert 1 tick sooner, see adjustment below based on data padding */
/* EDIT THIS LINE TO CONTROL PA_RAMP! */
#define PA_RAMP_TIME (2) /* Only allowable values are [0, 2, 4, or 8] for PA RAMP times in Gen2.0 */
#define PA_RAMP_SEL_0US (0)
#define PA_RAMP_SEL_2US (1)
#define PA_RAMP_SEL_4US (2)
#define PA_RAMP_SEL_8US (3)
#if !((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 2) || (PA_RAMP_TIME == 4) || (PA_RAMP_TIME == 8))
#error "Invalid value for PA_RAMP_TIME macro"
#endif /* Error check of PA RAMP TIME */
#define ADD_FOR_26MHZ (4)
#define END_OF_TX_WU_NORAMP (103) /* NOTE: NORAMP and 2us ramp time behaviors are identical for TX WU and WD */
#define END_OF_TX_WD_NORAMP (111) /* NOTE: NORAMP and 2us ramp time behaviors are identical for TX WU and WD */
/* Redefine the values of END_OF_TX_WU and END_OF_TX_WD based on whether DATA PADDING is enabled and the selection of ramp time */
/* These two constants are then used on both common configuration and mode specific configuration files to define the TSM timing values */
#if ((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 2))
#define END_OF_TX_WU (END_OF_TX_WU_NORAMP)
#define END_OF_TX_WD (END_OF_TX_WD_NORAMP)
#define TX_SYNTH_DELAY_ADJ (0)
#define PD_CYCLE_SLIP_TX_HI_ADJ (0)
#define PD_CYCLE_SLIP_TX_LO_ADJ (1)
#define ZGBE_TX_DIG_EN_TX_HI_ADJ (-5) /* Only applies to Zigbee mode */
#if (PA_RAMP_TIME == 0)
#define PA_RAMP_SEL PA_RAMP_SEL_0US
#define DATA_PADDING_EN (0)
#define TX_DIG_EN_TX_HI_ADJ (-2)
#else
#define DATA_PADDING_EN (1)
#define TX_DIG_EN_TX_HI_ADJ (0)
#define PA_RAMP_SEL PA_RAMP_SEL_2US
#endif /* (PA_RAMP_TIME == 0) */
#else /* ((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 2)) */
#if (PA_RAMP_TIME == 4)
#define END_OF_TX_WU (END_OF_TX_WU_NORAMP + 2)
#define END_OF_TX_WD (END_OF_TX_WD_NORAMP + 4)
#define TX_SYNTH_DELAY_ADJ (2)
#define PD_CYCLE_SLIP_TX_HI_ADJ (2)
#define PD_CYCLE_SLIP_TX_LO_ADJ (1)
#define TX_DIG_EN_TX_HI_ADJ (0)
#define ZGBE_TX_DIG_EN_TX_HI_ADJ (-3) /* Only applies to Zigbee mode */
#define PA_RAMP_SEL PA_RAMP_SEL_4US
#define DATA_PADDING_EN (1)
#else /* (PA_RAMP_TIME==4) */
#if ((PA_RAMP_TIME == 8) && (!RADIO_IS_GEN_3P0))
#define END_OF_TX_WU (END_OF_TX_WU_NORAMP + 6)
#define END_OF_TX_WD (END_OF_TX_WD_NORAMP + 12)
#define TX_SYNTH_DELAY_ADJ (6)
#define PD_CYCLE_SLIP_TX_HI_ADJ (6)
#define PD_CYCLE_SLIP_TX_LO_ADJ (1)
#define TX_DIG_EN_TX_HI_ADJ (4)
#define ZGBE_TX_DIG_EN_TX_HI_ADJ (1) /* Only applies to Zigbee mode */
#define PA_RAMP_SEL PA_RAMP_SEL_8US
#define DATA_PADDING_EN (1)
#else /* (PA_RAMP_TIME == 8) */
#error "Invalid value for PA_RAMP_TIME macro"
#endif /* (PA_RAMP_TIME == 8) */
#endif/* (PA_RAMP_TIME == 4) */
#endif /* ((PA_RAMP_TIME == 0) || (PA_RAMP_TIME == 2)) */
#define TX_DIG_EN_ASSERT_MSK500 (END_OF_TX_WU - 3)
#define END_OF_RX_WU (104 + AUX_PLL_DELAY)
#if RF_OSC_26MHZ == 1
#define END_OF_RX_WD (END_OF_RX_WU + 1 + ADD_FOR_26MHZ) /* Need to handle normal signals extending when 26MHZ warmdown is extended */
#else
#define END_OF_RX_WD (END_OF_RX_WU + 1)
#endif /* RF_OSC_26MHZ == 1 */
#define END_OF_RX_WU_26MHZ (END_OF_RX_WU + ADD_FOR_26MHZ)
#define END_OF_RX_WD_26MHZ (END_OF_RX_WU + 1 + ADD_FOR_26MHZ)
/* PA Bias Table */
#define PA_RAMP_0 0x1
#define PA_RAMP_1 0x2
#define PA_RAMP_2 0x4
#define PA_RAMP_3 0x8
#define PA_RAMP_4 0xe
#define PA_RAMP_5 0x16
#define PA_RAMP_6 0x22
#define PA_RAMP_7 0x2e
/* BLE LL timing definitions */
#define TX_ON_DELAY (0x85) /* Adjusted TX_ON_DELAY to make turnaround time 150usec */
#define RX_ON_DELAY (29 + END_OF_RX_WU+4)
#define RX_ON_DELAY_26MHZ (29 + END_OF_RX_WU_26MHZ+4)
#define TX_RX_ON_DELAY_VAL (TX_ON_DELAY << 8 | RX_ON_DELAY)
#define TX_RX_ON_DELAY_VAL_26MHZ (TX_ON_DELAY << 8 | RX_ON_DELAY_26MHZ)
#define TX_SYNTH_DELAY (TX_ON_DELAY - END_OF_TX_WU - TX_SYNTH_DELAY_ADJ) /* Adjustment to TX_SYNTH_DELAY due to DATA_PADDING */
#define RX_SYNTH_DELAY (0x18)
#define TX_RX_SYNTH_DELAY_VAL (TX_SYNTH_DELAY << 8 | RX_SYNTH_DELAY)
/* PHY reference waveform assembly */
#define RW0PS(loc, val) (((val) & 0x1F) << ((loc) * 5)) /* Ref Word 0 - loc is the phase info symbol number, val is the value of the phase info */
#define RW1PS(loc, val) (((val) & 0x1F) << (((loc) * 5) - 32)) /* Ref Word 1 - loc is the phase info symbol number, val is the value of the phase info */
#define RW2PS(loc, val) (((val) & 0x1F) << (((loc) * 5) - 64)) /* Ref Word 2 - loc is the phase info symbol number, val is the value of the phase info */
#endif /* RADIO_IS_GEN_3P0 */
/*! @brief Error codes for the XCVR driver. */
typedef enum _xcvrStatus
{
gXcvrSuccess_c = 0,
gXcvrInvalidParameters_c,
gXcvrUnsupportedOperation_c,
gXcvrTrimFailure_c
} xcvrStatus_t;
/*! @brief Health status returned from PHY upon status check function return. */
typedef enum _healthStatus
{
NO_ERRORS = 0,
PLL_CTUNE_FAIL = 1,
PLL_CYCLE_SLIP_FAIL = 2,
PLL_FREQ_TARG_FAIL = 4,
PLL_TSM_ABORT_FAIL = 8,
} healthStatus_t;
/*! @brief Health status returned from PHY upon status check function return. */
typedef enum _ext_clock_config
{
EXT_CLK_32_MHZ = 0,
EXT_CLK_26_MHZ = 1,
} ext_clock_config_t;
/*! @brief Radio operating mode setting types. */
typedef enum
{
BLE_MODE = 0,
ZIGBEE_MODE = 1,
ANT_MODE = 2,
/* BT=0.5, h=** */
GFSK_BT_0p5_h_0p5 = 3, /* < BT=0.5, h=0.5 [BLE at 1MBPS data rate; CS4 at 250KBPS data rate] */
GFSK_BT_0p5_h_0p32 = 4, /* < BT=0.5, h=0.32*/
GFSK_BT_0p5_h_0p7 = 5, /* < BT=0.5, h=0.7 [ CS1 at 500KBPS data rate] */
GFSK_BT_0p5_h_1p0 = 6, /* < BT=0.5, h=1.0 [ CS4 at 250KBPS data rate] */
/* BT=** h=0.5 */
GFSK_BT_0p3_h_0p5 = 7, /* < BT=0.3, h=0.5 [ CS2 at 1MBPS data rate] */
GFSK_BT_0p7_h_0p5 = 8, /* < BT=0.7, h=0.5 */
MSK = 9,
NUM_RADIO_MODES = 10,
} radio_mode_t;
/*! @brief Link layer types. */
typedef enum
{
BLE_LL = 0, /* Must match bit assignment in RADIO1_IRQ_SEL */
ZIGBEE_LL = 1, /* Must match bit assignment in RADIO1_IRQ_SEL */
ANT_LL = 2, /* Must match bit assignment in RADIO1_IRQ_SEL */
GENFSK_LL = 3, /* Must match bit assignment in RADIO1_IRQ_SEL */
UNASSIGNED_LL = 4, /* Must match bit assignment in RADIO1_IRQ_SEL */
} link_layer_t;
/*! @brief Data rate selections. */
typedef enum
{
DR_1MBPS = 0, /* Must match bit assignment in BITRATE field */
DR_500KBPS = 1, /* Must match bit assignment in BITRATE field */
DR_250KBPS = 2, /* Must match bit assignment in BITRATE field */
#if RADIO_IS_GEN_3P0
DR_2MBPS = 3, /* Must match bit assignment in BITRATE field */
#endif /* RADIO_IS_GEN_3P0 */
DR_UNASSIGNED = 4, /* Must match bit assignment in BITRATE field */
} data_rate_t;
/*!
* @brief XCVR RX_DIG channel filter coefficient storage
* Storage of the coefficients varies from 6 bits to 10 bits so all use int16_t for storage.
*/
typedef struct
{
uint16_t rx_chf_coef_0; /* < 6 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_1; /* < 6 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_2; /* < 7 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_3; /* < 7 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_4; /* < 7 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_5; /* < 7 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_6; /* < 8 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_7; /* < 8 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_8; /* < 9 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_9; /* < 9 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_10; /* < 10 bit two's complement stored in a uint16_t */
uint16_t rx_chf_coef_11; /* < 10 bit two's complement stored in a uint16_t */
} xcvr_rx_chf_coeffs_t;
/*!
* @brief XCVR masked init type for 32 bit registers
* Initialization uses the mask to clear selected fields of the register and then OR's in the init value. All init values must be in their proper field position.
*/
typedef struct
{
uint32_t mask;
uint32_t init;
} xcvr_masked_init_32_t;
/*!
* @brief XCVR common configure structure
*/
typedef struct
{
/* XCVR_ANA configs */
xcvr_masked_init_32_t ana_sy_ctrl1;
/* XCVR_PLL_DIG configs */
uint32_t pll_hpm_bump;
uint32_t pll_mod_ctrl;
uint32_t pll_chan_map;
uint32_t pll_lock_detect;
uint32_t pll_hpm_ctrl;
#if !RADIO_IS_GEN_2P1
uint32_t pll_hpmcal_ctrl;
#endif /* !RADIO_IS_GEN_2P1 */
uint32_t pll_hpm_sdm_res;
uint32_t pll_lpm_ctrl;
uint32_t pll_lpm_sdm_ctrl1;
uint32_t pll_delay_match;
uint32_t pll_ctune_ctrl;
/* XCVR_RX_DIG configs */
uint32_t rx_dig_ctrl_init; /* NOTE: Common init, mode init, and datarate init will be OR'd together for RX_DIG_CTRL to form complete register initialization */
uint32_t dcoc_ctrl_0_init_26mhz; /* NOTE: This will be OR'd with mode specific init for DCOC_CTRL_0 to form complete register initialization */
uint32_t dcoc_ctrl_0_init_32mhz; /* NOTE: This will be OR'd with mode specific init for DCOC_CTRL_0 to form complete register initialization */
uint32_t dcoc_ctrl_1_init;
uint32_t dcoc_cal_gain_init;
uint32_t dc_resid_ctrl_init; /* NOTE: This will be OR'd with datarate specific init for DCOC_RESID_CTRL to form complete register initialization */
uint32_t dcoc_cal_rcp_init;
uint32_t lna_gain_val_3_0;
uint32_t lna_gain_val_7_4;
uint32_t lna_gain_val_8;
uint32_t bba_res_tune_val_7_0;
uint32_t bba_res_tune_val_10_8;
uint32_t lna_gain_lin_val_2_0_init;
uint32_t lna_gain_lin_val_5_3_init;
uint32_t lna_gain_lin_val_8_6_init;
uint32_t lna_gain_lin_val_9_init;
uint32_t bba_res_tune_lin_val_3_0_init;
uint32_t bba_res_tune_lin_val_7_4_init;
uint32_t bba_res_tune_lin_val_10_8_init;
uint32_t dcoc_bba_step_init;
uint32_t dcoc_tza_step_00_init;
uint32_t dcoc_tza_step_01_init;
uint32_t dcoc_tza_step_02_init;
uint32_t dcoc_tza_step_03_init;
uint32_t dcoc_tza_step_04_init;
uint32_t dcoc_tza_step_05_init;
uint32_t dcoc_tza_step_06_init;
uint32_t dcoc_tza_step_07_init;
uint32_t dcoc_tza_step_08_init;
uint32_t dcoc_tza_step_09_init;
uint32_t dcoc_tza_step_10_init;
#if (RADIO_IS_GEN_3P0 || RADIO_IS_GEN_2P1)
uint32_t dcoc_cal_fail_th_init;
uint32_t dcoc_cal_pass_th_init;
#endif /* (RADIO_IS_GEN_3P0 || RADIO_IS_GEN_2P1) */
uint32_t agc_ctrl_0_init; /* NOTE: Common init and mode init will be OR'd together for AGC_CTRL_0 to form complete register initialization */
uint32_t agc_ctrl_1_init_26mhz; /* NOTE: This will be OR'd with datarate specific init to form complete register initialization */
uint32_t agc_ctrl_1_init_32mhz; /* NOTE: This will be OR'd with datarate specific init to form complete register initialization */
uint32_t agc_ctrl_3_init;
/* Other agc config inits are in the modeXdatarate config table */
uint32_t agc_gain_tbl_03_00_init;
uint32_t agc_gain_tbl_07_04_init;
uint32_t agc_gain_tbl_11_08_init;
uint32_t agc_gain_tbl_15_12_init;
uint32_t agc_gain_tbl_19_16_init;
uint32_t agc_gain_tbl_23_20_init;
uint32_t agc_gain_tbl_26_24_init;
uint32_t rssi_ctrl_0_init;
#if RADIO_IS_GEN_3P0
uint32_t rssi_ctrl_1_init;
#endif /* RADIO_IS_GEN_3P0 */
uint32_t cca_ed_lqi_ctrl_0_init;
uint32_t cca_ed_lqi_ctrl_1_init;
/* XCVR_TSM configs */
uint32_t tsm_ctrl;
uint32_t tsm_ovrd2_init;
uint32_t end_of_seq_init_26mhz;
uint32_t end_of_seq_init_32mhz;
#if !RADIO_IS_GEN_2P1
uint32_t lpps_ctrl_init;
#endif /* !RADIO_IS_GEN_2P1 */
uint32_t tsm_fast_ctrl2_init_26mhz;
uint32_t tsm_fast_ctrl2_init_32mhz;
uint32_t recycle_count_init_26mhz;
uint32_t recycle_count_init_32mhz;
uint32_t pa_ramp_tbl_0_init;
uint32_t pa_ramp_tbl_1_init;
#if RADIO_IS_GEN_3P0
uint32_t pa_ramp_tbl_2_init;
uint32_t pa_ramp_tbl_3_init;
#endif /* RADIO_IS_GEN_3P0 */
uint32_t tsm_timing_00_init;
uint32_t tsm_timing_01_init;
uint32_t tsm_timing_02_init;
uint32_t tsm_timing_03_init;
uint32_t tsm_timing_04_init;
uint32_t tsm_timing_05_init;
uint32_t tsm_timing_06_init;
uint32_t tsm_timing_07_init;
uint32_t tsm_timing_08_init;
uint32_t tsm_timing_09_init;
uint32_t tsm_timing_10_init;
uint32_t tsm_timing_11_init;
uint32_t tsm_timing_12_init;
uint32_t tsm_timing_13_init;
uint32_t tsm_timing_14_init_26mhz; /* tsm_timing_14 has mode specific LSbyte (both LS bytes) */
uint32_t tsm_timing_14_init_32mhz; /* tsm_timing_14 has mode specific LSbyte (both LS bytes) */
uint32_t tsm_timing_15_init;
uint32_t tsm_timing_16_init_26mhz;
uint32_t tsm_timing_16_init_32mhz;
uint32_t tsm_timing_17_init;
uint32_t tsm_timing_18_init;
uint32_t tsm_timing_19_init;
uint32_t tsm_timing_20_init;
uint32_t tsm_timing_21_init;
uint32_t tsm_timing_22_init;
uint32_t tsm_timing_23_init;
uint32_t tsm_timing_24_init;
uint32_t tsm_timing_25_init_26mhz;
uint32_t tsm_timing_25_init_32mhz;
uint32_t tsm_timing_26_init;
uint32_t tsm_timing_27_init_26mhz;
uint32_t tsm_timing_27_init_32mhz;
uint32_t tsm_timing_28_init_26mhz;
uint32_t tsm_timing_28_init_32mhz;
uint32_t tsm_timing_29_init_26mhz;
uint32_t tsm_timing_29_init_32mhz;
uint32_t tsm_timing_30_init_26mhz;
uint32_t tsm_timing_30_init_32mhz;
uint32_t tsm_timing_31_init_26mhz;
uint32_t tsm_timing_31_init_32mhz;
uint32_t tsm_timing_32_init_26mhz;
uint32_t tsm_timing_32_init_32mhz;
uint32_t tsm_timing_33_init_26mhz;
uint32_t tsm_timing_33_init_32mhz;
uint32_t tsm_timing_34_init;
uint32_t tsm_timing_35_init; /* tsm_timing_35 has a mode specific LSbyte*/
uint32_t tsm_timing_36_init_26mhz;
uint32_t tsm_timing_36_init_32mhz;
uint32_t tsm_timing_37_init_26mhz;
uint32_t tsm_timing_37_init_32mhz;
uint32_t tsm_timing_38_init;
uint32_t tsm_timing_39_init_26mhz;
uint32_t tsm_timing_39_init_32mhz;
uint32_t tsm_timing_40_init_26mhz;
uint32_t tsm_timing_40_init_32mhz;
uint32_t tsm_timing_41_init_26mhz;
uint32_t tsm_timing_41_init_32mhz;
uint32_t tsm_timing_51_init;
uint32_t tsm_timing_52_init_26mhz;
uint32_t tsm_timing_52_init_32mhz;
uint32_t tsm_timing_53_init;
uint32_t tsm_timing_54_init_26mhz;
uint32_t tsm_timing_54_init_32mhz;
uint32_t tsm_timing_55_init_26mhz;
uint32_t tsm_timing_55_init_32mhz;
uint32_t tsm_timing_56_init_26mhz;
uint32_t tsm_timing_56_init_32mhz;
uint32_t tsm_timing_57_init;
uint32_t tsm_timing_58_init;
/* XCVR_TX_DIG configs */
uint32_t tx_ctrl;
uint32_t tx_data_padding;
uint32_t tx_dft_pattern;
#if !RADIO_IS_GEN_2P1
uint32_t rf_dft_bist_1;
uint32_t rf_dft_bist_2;
#endif /* !RADIO_IS_GEN_2P1 */
} xcvr_common_config_t;
/*! @brief XCVR mode specific configure structure (varies by radio mode) */
typedef struct
{
radio_mode_t radio_mode;
uint32_t scgc5_clock_ena_bits;
/* XCVR_MISC configs */
xcvr_masked_init_32_t xcvr_ctrl;
/* XCVR_PHY configs */
#if RADIO_IS_GEN_3P0
uint32_t phy_fsk_pd_cfg0;
uint32_t phy_fsk_pd_cfg1;
uint32_t phy_fsk_cfg;
uint32_t phy_fsk_misc;
uint32_t phy_fad_ctrl;
#else
uint32_t phy_pre_ref0_init;
uint32_t phy_pre_ref1_init;
uint32_t phy_pre_ref2_init;
uint32_t phy_cfg1_init;
uint32_t phy_el_cfg_init; /* EL_WIN_SIZE and EL_INTERVAL are in the data_rate specific configuration */
#endif /* RADIO_IS_GEN_3P0 */
/* XCVR_RX_DIG configs */
uint32_t rx_dig_ctrl_init_26mhz; /* NOTE: Common init, mode init, and datarate init will be OR'd together for RX_DIG_CTRL to form complete register initialization */
uint32_t rx_dig_ctrl_init_32mhz; /* NOTE: Common init, mode init, and datarate init will be OR'd together for RX_DIG_CTRL to form complete register initialization */
uint32_t agc_ctrl_0_init; /* NOTE: Common init and mode init will be OR'd together for AGC_CTRL_0 to form complete register initialization */
/* XCVR_TSM configs */
#if (RADIO_IS_GEN_2P0 || RADIO_IS_GEN_2P1)
uint32_t tsm_timing_35_init; /* Only the LSbyte is mode specific */
#endif /* (RADIO_IS_GEN_2P0 || RADIO_IS_GEN_2P1) */
/* XCVR_TX_DIG configs */
uint32_t tx_gfsk_ctrl;
uint32_t tx_gfsk_coeff1_26mhz;
uint32_t tx_gfsk_coeff2_26mhz;
uint32_t tx_gfsk_coeff1_32mhz;
uint32_t tx_gfsk_coeff2_32mhz;
} xcvr_mode_config_t;
/*!
* @brief XCVR modeXdatarate specific configure structure (varies by radio mode AND data rate)
* This structure is used to store all of the XCVR settings which are dependent upon both radio mode and data rate. It is used as an overlay
* on top of the xcvr_mode_config_t structure to supply definitions which are either not in that table or which must be overridden for data rate.
*/
typedef struct
{
radio_mode_t radio_mode;
data_rate_t data_rate;
/* XCVR_ANA configs */
xcvr_masked_init_32_t ana_sy_ctrl2;
xcvr_masked_init_32_t ana_rx_bba;
xcvr_masked_init_32_t ana_rx_tza;
/* XCVR_PHY configs */
#if RADIO_IS_GEN_3P0
uint32_t phy_fsk_misc_mode_datarate;
#else
uint32_t phy_cfg2_init;
#endif /* RADIO_IS_GEN_3P0 */
uint32_t agc_ctrl_2_init_26mhz;
uint32_t agc_ctrl_2_init_32mhz;
xcvr_rx_chf_coeffs_t rx_chf_coeffs_26mhz; /* 26MHz ext clk */
xcvr_rx_chf_coeffs_t rx_chf_coeffs_32mhz; /* 32MHz ext clk */
uint32_t rx_rccal_ctrl_0;
uint32_t rx_rccal_ctrl_1;
/* XCVR_TX_DIG configs */
uint32_t tx_fsk_scale_26mhz; /* Only used by MSK mode, but dependent on datarate */
uint32_t tx_fsk_scale_32mhz; /* Only used by MSK mode, but dependent on datarate */
} xcvr_mode_datarate_config_t;
/*!
* @brief XCVR datarate specific configure structure (varies by data rate)
* This structure is used to store all of the XCVR settings which are dependent upon data rate. It is used as an overlay
* on top of the xcvr_mode_config_t structure to supply definitions which are either not in that table or which must be overridden for data rate.
*/
typedef struct
{
data_rate_t data_rate;
/* XCVR_PHY configs */
uint32_t phy_el_cfg_init; /* Note: EL_ENABLE is set in xcvr_mode_config_t settings */
/* XCVR_RX_DIG configs */
uint32_t rx_dig_ctrl_init_26mhz; /* NOTE: Common init, mode init, and datarate init will be OR'd together for RX_DIG_CTRL to form complete register initialization */
uint32_t rx_dig_ctrl_init_32mhz; /* NOTE: Common init, mode init, and datarate init will be OR'd together for RX_DIG_CTRL to form complete register initialization */
uint32_t agc_ctrl_1_init_26mhz;
uint32_t agc_ctrl_1_init_32mhz;
uint32_t dcoc_ctrl_0_init_26mhz; /* NOTE: This will be OR'd with common init for DCOC_CTRL_0 to form complete register initialization */
uint32_t dcoc_ctrl_0_init_32mhz; /* NOTE: This will be OR'd with common init for DCOC_CTRL_0 to form complete register initialization */
uint32_t dcoc_ctrl_1_init_26mhz; /* NOTE: This will be OR'd with common init for DCOC_CTRL_1 to form complete register initialization */
uint32_t dcoc_ctrl_1_init_32mhz; /* NOTE: This will be OR'd with common init for DCOC_CTRL_1 to form complete register initialization */
uint32_t dcoc_ctrl_2_init_26mhz;
uint32_t dcoc_ctrl_2_init_32mhz;
uint32_t dcoc_cal_iir_init_26mhz;
uint32_t dcoc_cal_iir_init_32mhz;
uint32_t dc_resid_ctrl_26mhz;/* NOTE: This will be OR'd with common init for DCOC_RESID_CTRL to form complete register initialization */
uint32_t dc_resid_ctrl_32mhz;/* NOTE: This will be OR'd with common init for DCOC_RESID_CTRL to form complete register initialization */
} xcvr_datarate_config_t;
/*!
* @brief LPUART callback function type
*
* The panic callback function is defined by system if system need to be informed of XCVR fatal errors.
* refer to #XCVR_RegisterPanicCb
*/
typedef void (*panic_fptr)(uint32_t panic_id, uint32_t location, uint32_t extra1, uint32_t extra2);
/* Make available const structures from config files */
extern const xcvr_common_config_t xcvr_common_config;
extern const xcvr_mode_config_t zgbe_mode_config;
extern const xcvr_mode_config_t ble_mode_config;
extern const xcvr_mode_config_t ant_mode_config;
extern const xcvr_mode_config_t gfsk_bt_0p5_h_0p5_mode_config;
extern const xcvr_mode_config_t gfsk_bt_0p5_h_0p7_mode_config;
extern const xcvr_mode_config_t gfsk_bt_0p5_h_0p32_mode_config;
extern const xcvr_mode_config_t gfsk_bt_0p5_h_1p0_mode_config;
extern const xcvr_mode_config_t gfsk_bt_0p3_h_0p5_mode_config;
extern const xcvr_mode_config_t gfsk_bt_0p7_h_0p5_mode_config;
extern const xcvr_mode_config_t msk_mode_config;
#if RADIO_IS_GEN_3P0
extern const xcvr_datarate_config_t xcvr_2mbps_config;
#endif /* RADIO_IS_GEN_3P0 */
extern const xcvr_datarate_config_t xcvr_1mbps_config;
extern const xcvr_datarate_config_t xcvr_500kbps_config;
extern const xcvr_datarate_config_t xcvr_250kbps_config;
extern const xcvr_datarate_config_t xcvr_802_15_4_500kbps_config; /* Custom datarate settings for 802.15.4 since it is 2MChips/sec */
#if RADIO_IS_GEN_3P0
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p5_2mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p32_2mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p3_h_0p5_2mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p7_h_0p5_2mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_MSK_2mbps_config;
#endif /* RADIO_IS_GEN_3P0 */
extern const xcvr_mode_datarate_config_t xcvr_BLE_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_ZIGBEE_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_ANT_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p5_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p5_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p5_250kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p32_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p32_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p32_250kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p7_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p7_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_0p7_250kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_1p0_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_1p0_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p5_h_1p0_250kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p3_h_0p5_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p3_h_0p5_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p3_h_0p5_250kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p7_h_0p5_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p7_h_0p5_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_GFSK_BT_0p7_h_0p5_250kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_MSK_1mbps_config;
extern const xcvr_mode_datarate_config_t xcvr_MSK_500kbps_config;
extern const xcvr_mode_datarate_config_t xcvr_MSK_250kbps_config;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*! @}*/
#endif /* _FSL_XCVR_H_ */

View File

@ -0,0 +1,628 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_xcvr.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
const xcvr_common_config_t xcvr_common_config =
{
/* XCVR_ANA configs */
.ana_sy_ctrl1.mask = XCVR_ANALOG_SY_CTRL_1_SY_LPF_FILT_CTRL_MASK,
.ana_sy_ctrl1.init = XCVR_ANALOG_SY_CTRL_1_SY_LPF_FILT_CTRL(3), /* PLL Analog Loop Filter */
#define hpm_vcm_tx 0
#define hpm_vcm_cal 1
#define hpm_fdb_res_tx 0
#define hpm_fdb_res_cal 1
#define modulation_word_manual 0
#define mod_disable 0
#define hpm_mod_manual 0
#define hpm_mod_disable 0
#define hpm_sdm_out_manual 0
#define hpm_sdm_out_disable 0
#define channel_num 0
#define boc 0
#define bmr 1
#define zoc 0
#define ctune_ldf_lev 8
#define ftf_rx_thrsh 33
#define ftw_rx 0
#define ftf_tx_thrsh 6
#define ftw_tx 0
#define freq_count_go 0
#define freq_count_time 0
#define hpm_sdm_in_manual 0
#define hpm_sdm_out_invert 0
#define hpm_sdm_in_disable 0
#define hpm_lfsr_size 4
#define hpm_dth_scl 0
#define hpm_dth_en 1
#define hpm_integer_scale 0
#define hpm_integer_invert 0
#define hpm_cal_invert 1
#define hpm_mod_in_invert 1
#define hpm_cal_not_bumped 0
#define hpm_cal_count_scale 0
#define hp_cal_disable 0
#define hpm_cal_factor_manual 0
#define hpm_cal_array_size 1
#define hpm_cal_time 0
#define hpm_sdm_denom 256
#define hpm_count_adjust 0
#define pll_ld_manual 0
#define pll_ld_disable 0
#define lpm_sdm_inv 0
#define lpm_disable 0
#define lpm_dth_scl 8
#define lpm_d_ctrl 1
#define lpm_d_ovrd 1
#define lpm_scale 8
#define lpm_sdm_use_neg 0
#define hpm_array_bias 0
#define lpm_intg 38
#define sdm_map_disable 0
#define lpm_sdm_delay 4
#define hpm_sdm_delay 0
#define hpm_integer_delay 0
#define ctune_target_manual 0
#define ctune_target_disable 0
#define ctune_adjust 0
#define ctune_manual 0
#define ctune_disable 0
/*-------------------------------------------------------------------------------------------------*/
.pll_hpm_bump = XCVR_PLL_DIG_HPM_BUMP_HPM_FDB_RES_CAL(hpm_fdb_res_cal) |
XCVR_PLL_DIG_HPM_BUMP_HPM_FDB_RES_TX(hpm_fdb_res_tx) |
XCVR_PLL_DIG_HPM_BUMP_HPM_VCM_CAL(hpm_vcm_cal) |
XCVR_PLL_DIG_HPM_BUMP_HPM_VCM_TX(hpm_vcm_tx),
/*-------------------------------------------------------------------------------------------------*/
.pll_mod_ctrl = XCVR_PLL_DIG_MOD_CTRL_HPM_MOD_DISABLE(hpm_mod_disable) |
XCVR_PLL_DIG_MOD_CTRL_HPM_MOD_MANUAL(hpm_mod_manual) |
XCVR_PLL_DIG_MOD_CTRL_HPM_SDM_OUT_DISABLE(hpm_sdm_out_disable) |
XCVR_PLL_DIG_MOD_CTRL_HPM_SDM_OUT_MANUAL(hpm_sdm_out_manual) |
XCVR_PLL_DIG_MOD_CTRL_MOD_DISABLE(mod_disable) |
XCVR_PLL_DIG_MOD_CTRL_MODULATION_WORD_MANUAL(modulation_word_manual),
/*-------------------------------------------------------------------------------------------------*/
.pll_chan_map = XCVR_PLL_DIG_CHAN_MAP_BMR(bmr) |
XCVR_PLL_DIG_CHAN_MAP_BOC(boc) |
XCVR_PLL_DIG_CHAN_MAP_CHANNEL_NUM(channel_num)
#if !RADIO_IS_GEN_2P1
| XCVR_PLL_DIG_CHAN_MAP_ZOC(zoc)
#endif /* !RADIO_IS_GEN_2P1 */
,
/*-------------------------------------------------------------------------------------------------*/
.pll_lock_detect = XCVR_PLL_DIG_LOCK_DETECT_CTUNE_LDF_LEV(ctune_ldf_lev) |
XCVR_PLL_DIG_LOCK_DETECT_FREQ_COUNT_GO(freq_count_go) |
XCVR_PLL_DIG_LOCK_DETECT_FREQ_COUNT_TIME(freq_count_time) |
XCVR_PLL_DIG_LOCK_DETECT_FTF_RX_THRSH(ftf_rx_thrsh) |
XCVR_PLL_DIG_LOCK_DETECT_FTF_TX_THRSH(ftf_tx_thrsh) |
XCVR_PLL_DIG_LOCK_DETECT_FTW_RX(ftw_rx) |
XCVR_PLL_DIG_LOCK_DETECT_FTW_TX(ftw_tx),
/*-------------------------------------------------------------------------------------------------*/
.pll_hpm_ctrl = XCVR_PLL_DIG_HPM_CTRL_HPM_CAL_INVERT(hpm_cal_invert) |
XCVR_PLL_DIG_HPM_CTRL_HPM_DTH_EN(hpm_dth_en) |
XCVR_PLL_DIG_HPM_CTRL_HPM_DTH_SCL(hpm_dth_scl) |
XCVR_PLL_DIG_HPM_CTRL_HPM_INTEGER_INVERT(hpm_integer_invert) |
XCVR_PLL_DIG_HPM_CTRL_HPM_INTEGER_SCALE(hpm_integer_scale) |
XCVR_PLL_DIG_HPM_CTRL_HPM_LFSR_SIZE(hpm_lfsr_size) |
XCVR_PLL_DIG_HPM_CTRL_HPM_MOD_IN_INVERT(hpm_mod_in_invert) |
XCVR_PLL_DIG_HPM_CTRL_HPM_SDM_IN_DISABLE(hpm_sdm_in_disable) |
XCVR_PLL_DIG_HPM_CTRL_HPM_SDM_IN_MANUAL(hpm_sdm_in_manual) |
XCVR_PLL_DIG_HPM_CTRL_HPM_SDM_OUT_INVERT(hpm_sdm_out_invert),
/*-------------------------------------------------------------------------------------------------*/
#if !RADIO_IS_GEN_2P1
.pll_hpmcal_ctrl = XCVR_PLL_DIG_HPMCAL_CTRL_HP_CAL_DISABLE(hp_cal_disable) |
XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_ARRAY_SIZE(hpm_cal_array_size) |
XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_COUNT_SCALE(hpm_cal_count_scale) |
XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MANUAL(hpm_cal_factor_manual) |
XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_NOT_BUMPED(hpm_cal_not_bumped) |
XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_TIME(hpm_cal_time),
#endif /* !RADIO_IS_GEN_2P1 */
/*-------------------------------------------------------------------------------------------------*/
.pll_hpm_sdm_res = XCVR_PLL_DIG_HPM_SDM_RES_HPM_COUNT_ADJUST(hpm_count_adjust) |
XCVR_PLL_DIG_HPM_SDM_RES_HPM_DENOM(hpm_sdm_denom),
/*-------------------------------------------------------------------------------------------------*/
.pll_lpm_ctrl = XCVR_PLL_DIG_LPM_CTRL_LPM_D_CTRL(lpm_d_ctrl) |
XCVR_PLL_DIG_LPM_CTRL_LPM_D_OVRD(lpm_d_ovrd) |
XCVR_PLL_DIG_LPM_CTRL_LPM_DISABLE(lpm_disable) |
XCVR_PLL_DIG_LPM_CTRL_LPM_DTH_SCL(lpm_dth_scl) |
XCVR_PLL_DIG_LPM_CTRL_LPM_SCALE(lpm_scale) |
XCVR_PLL_DIG_LPM_CTRL_LPM_SDM_INV(lpm_sdm_inv) |
XCVR_PLL_DIG_LPM_CTRL_LPM_SDM_USE_NEG(lpm_sdm_use_neg) |
XCVR_PLL_DIG_LPM_CTRL_PLL_LD_DISABLE(pll_ld_disable) |
XCVR_PLL_DIG_LPM_CTRL_PLL_LD_MANUAL(pll_ld_manual),
/*-------------------------------------------------------------------------------------------------*/
.pll_lpm_sdm_ctrl1 = XCVR_PLL_DIG_LPM_SDM_CTRL1_HPM_ARRAY_BIAS(hpm_array_bias) |
XCVR_PLL_DIG_LPM_SDM_CTRL1_LPM_INTG(lpm_intg) |
XCVR_PLL_DIG_LPM_SDM_CTRL1_SDM_MAP_DISABLE(sdm_map_disable),
/*-------------------------------------------------------------------------------------------------*/
.pll_delay_match = XCVR_PLL_DIG_DELAY_MATCH_HPM_INTEGER_DELAY(hpm_integer_delay) |
XCVR_PLL_DIG_DELAY_MATCH_HPM_SDM_DELAY(hpm_sdm_delay) |
XCVR_PLL_DIG_DELAY_MATCH_LPM_SDM_DELAY(lpm_sdm_delay),
/*-------------------------------------------------------------------------------------------------*/
.pll_ctune_ctrl = XCVR_PLL_DIG_CTUNE_CTRL_CTUNE_ADJUST(ctune_adjust) |
XCVR_PLL_DIG_CTUNE_CTRL_CTUNE_DISABLE(ctune_disable) |
XCVR_PLL_DIG_CTUNE_CTRL_CTUNE_MANUAL(ctune_manual) |
XCVR_PLL_DIG_CTUNE_CTRL_CTUNE_TARGET_DISABLE(ctune_target_disable) |
XCVR_PLL_DIG_CTUNE_CTRL_CTUNE_TARGET_MANUAL(ctune_target_manual),
/*-------------------------------------------------------------------------------------------------*/
/* XCVR_RX_DIG configs */
/* NOTE: Clock specific settings are embedded in the mode dependent configs */
.rx_dig_ctrl_init = XCVR_RX_DIG_RX_DIG_CTRL_RX_ADC_NEGEDGE(0) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_CH_FILT_BYPASS(0) |
#if !RADIO_IS_GEN_2P1
XCVR_RX_DIG_RX_DIG_CTRL_RX_ADC_RAW_EN(0) |
#endif /* !RADIO_IS_GEN_2P1 */
XCVR_RX_DIG_RX_DIG_CTRL_RX_ADC_POL(0) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_NORM_EN(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_RSSI_EN(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_EN(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_IQ_SWAP(0) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DMA_DTEST_EN(0) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_HZD_CORR_DIS(1),
.agc_ctrl_0_init = XCVR_RX_DIG_AGC_CTRL_0_SLOW_AGC_EN(1) |
XCVR_RX_DIG_AGC_CTRL_0_SLOW_AGC_SRC(2) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_FREEZE_EN(1) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_FREEZE_PRE_OR_AA(0) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_UP_EN(1) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_UP_SRC(0) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_DOWN_BBA_STEP_SZ(2) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_DOWN_LNA_STEP_SZ(2) |
XCVR_RX_DIG_AGC_CTRL_0_AGC_UP_RSSI_THRESH(0xe7),
.agc_ctrl_3_init = XCVR_RX_DIG_AGC_CTRL_3_AGC_UNFREEZE_TIME(21) |
XCVR_RX_DIG_AGC_CTRL_3_AGC_PDET_LO_DLY(2) |
XCVR_RX_DIG_AGC_CTRL_3_AGC_RSSI_DELT_H2S(20) |
XCVR_RX_DIG_AGC_CTRL_3_AGC_H2S_STEP_SZ(6) |
XCVR_RX_DIG_AGC_CTRL_3_AGC_UP_STEP_SZ(2),
/* DCOC configs */
.dcoc_ctrl_0_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CAL_DURATION(16) | /* Only the duration changes between 26MHz and 32MHz ref osc settings */
#if (RADIO_IS_GEN_2P1)
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CAL_CHECK_EN(0) |
#endif /* (RADIO_IS_GEN_2P1) */
XCVR_RX_DIG_DCOC_CTRL_0_TRACK_FROM_ZERO(0) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1) |
XCVR_RX_DIG_DCOC_CTRL_0_TZA_CORR_POL(0) |
XCVR_RX_DIG_DCOC_CTRL_0_BBA_CORR_POL(0) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1),
.dcoc_ctrl_0_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CAL_DURATION(20) | /* Only the duration changes between 26MHz and 32MHz ref osc settings */
#if (RADIO_IS_GEN_2P1)
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CAL_CHECK_EN(0) |
#endif /* (RADIO_IS_GEN_2P1) */
XCVR_RX_DIG_DCOC_CTRL_0_TRACK_FROM_ZERO(0) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1) |
XCVR_RX_DIG_DCOC_CTRL_0_TZA_CORR_POL(0) |
XCVR_RX_DIG_DCOC_CTRL_0_BBA_CORR_POL(0) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1),
.dcoc_ctrl_1_init = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_MIN_AGC_IDX(26),
.dc_resid_ctrl_init = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_ITER_FREEZE(5) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_ALPHA(1) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_EXT_DC_EN(1) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_MIN_AGC_IDX(26),
.dcoc_cal_gain_init = XCVR_RX_DIG_DCOC_CAL_GAIN_DCOC_BBA_CAL_GAIN1(1) |
XCVR_RX_DIG_DCOC_CAL_GAIN_DCOC_LNA_CAL_GAIN1(1) |
XCVR_RX_DIG_DCOC_CAL_GAIN_DCOC_BBA_CAL_GAIN2(1) |
XCVR_RX_DIG_DCOC_CAL_GAIN_DCOC_LNA_CAL_GAIN2(2) |
XCVR_RX_DIG_DCOC_CAL_GAIN_DCOC_BBA_CAL_GAIN3(3) |
XCVR_RX_DIG_DCOC_CAL_GAIN_DCOC_LNA_CAL_GAIN3(1) ,
.dcoc_cal_rcp_init = XCVR_RX_DIG_DCOC_CAL_RCP_ALPHA_CALC_RECIP(1) |
XCVR_RX_DIG_DCOC_CAL_RCP_DCOC_TMP_CALC_RECIP(711),
.lna_gain_val_3_0 = XCVR_RX_DIG_LNA_GAIN_VAL_3_0_LNA_GAIN_VAL_0(0x1DU) |
XCVR_RX_DIG_LNA_GAIN_VAL_3_0_LNA_GAIN_VAL_1(0x32U) |
XCVR_RX_DIG_LNA_GAIN_VAL_3_0_LNA_GAIN_VAL_2(0x09U) |
XCVR_RX_DIG_LNA_GAIN_VAL_3_0_LNA_GAIN_VAL_3(0x38U),
.lna_gain_val_7_4 = XCVR_RX_DIG_LNA_GAIN_VAL_7_4_LNA_GAIN_VAL_4(0x4FU) |
XCVR_RX_DIG_LNA_GAIN_VAL_7_4_LNA_GAIN_VAL_5(0x5BU) |
XCVR_RX_DIG_LNA_GAIN_VAL_7_4_LNA_GAIN_VAL_6(0x72U) |
XCVR_RX_DIG_LNA_GAIN_VAL_7_4_LNA_GAIN_VAL_7(0x8AU),
.lna_gain_val_8 = XCVR_RX_DIG_LNA_GAIN_VAL_8_LNA_GAIN_VAL_8(0xA0U) |
XCVR_RX_DIG_LNA_GAIN_VAL_8_LNA_GAIN_VAL_9(0xB6U),
.bba_res_tune_val_7_0 = XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_0(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_1(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_2(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_3(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_4(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_5(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_6(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_7_0_BBA_RES_TUNE_VAL_7(0xF),
.bba_res_tune_val_10_8 = XCVR_RX_DIG_BBA_RES_TUNE_VAL_10_8_BBA_RES_TUNE_VAL_8(0x0) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_10_8_BBA_RES_TUNE_VAL_9(0x1) |
XCVR_RX_DIG_BBA_RES_TUNE_VAL_10_8_BBA_RES_TUNE_VAL_10(0x2),
.lna_gain_lin_val_2_0_init = XCVR_RX_DIG_LNA_GAIN_LIN_VAL_2_0_LNA_GAIN_LIN_VAL_0(0) |
XCVR_RX_DIG_LNA_GAIN_LIN_VAL_2_0_LNA_GAIN_LIN_VAL_1(0) |
XCVR_RX_DIG_LNA_GAIN_LIN_VAL_2_0_LNA_GAIN_LIN_VAL_2(1),
.lna_gain_lin_val_5_3_init = XCVR_RX_DIG_LNA_GAIN_LIN_VAL_5_3_LNA_GAIN_LIN_VAL_3(3) |
XCVR_RX_DIG_LNA_GAIN_LIN_VAL_5_3_LNA_GAIN_LIN_VAL_4(5) |
XCVR_RX_DIG_LNA_GAIN_LIN_VAL_5_3_LNA_GAIN_LIN_VAL_5(7),
.lna_gain_lin_val_8_6_init = XCVR_RX_DIG_LNA_GAIN_LIN_VAL_8_6_LNA_GAIN_LIN_VAL_6(14) |
XCVR_RX_DIG_LNA_GAIN_LIN_VAL_8_6_LNA_GAIN_LIN_VAL_7(27) |
XCVR_RX_DIG_LNA_GAIN_LIN_VAL_8_6_LNA_GAIN_LIN_VAL_8(50),
.lna_gain_lin_val_9_init = XCVR_RX_DIG_LNA_GAIN_LIN_VAL_9_LNA_GAIN_LIN_VAL_9(91),
.bba_res_tune_lin_val_3_0_init = XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_3_0_BBA_RES_TUNE_LIN_VAL_0(8) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_3_0_BBA_RES_TUNE_LIN_VAL_1(11) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_3_0_BBA_RES_TUNE_LIN_VAL_2(16) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_3_0_BBA_RES_TUNE_LIN_VAL_3(22),
.bba_res_tune_lin_val_7_4_init = XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_7_4_BBA_RES_TUNE_LIN_VAL_4(31) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_7_4_BBA_RES_TUNE_LIN_VAL_5(44) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_7_4_BBA_RES_TUNE_LIN_VAL_6(62) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_7_4_BBA_RES_TUNE_LIN_VAL_7(42), /* Has 2 fractional bits unlike other BBA_RES_TUNE_LIN_VALs */
.bba_res_tune_lin_val_10_8_init = XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_10_8_BBA_RES_TUNE_LIN_VAL_8(128) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_10_8_BBA_RES_TUNE_LIN_VAL_9(188) |
XCVR_RX_DIG_BBA_RES_TUNE_LIN_VAL_10_8_BBA_RES_TUNE_LIN_VAL_10(288),
.dcoc_bba_step_init = XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP_RECIP(939) |
XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP(279),
.dcoc_tza_step_00_init = XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_GAIN_0(77) |
XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_RCP_0(3404),
.dcoc_tza_step_01_init = XCVR_RX_DIG_DCOC_TZA_STEP_1_DCOC_TZA_STEP_GAIN_1(108) |
XCVR_RX_DIG_DCOC_TZA_STEP_1_DCOC_TZA_STEP_RCP_1(2439),
.dcoc_tza_step_02_init = XCVR_RX_DIG_DCOC_TZA_STEP_2_DCOC_TZA_STEP_GAIN_2(155) |
XCVR_RX_DIG_DCOC_TZA_STEP_2_DCOC_TZA_STEP_RCP_2(1691),
.dcoc_tza_step_03_init = XCVR_RX_DIG_DCOC_TZA_STEP_3_DCOC_TZA_STEP_GAIN_3(220) |
XCVR_RX_DIG_DCOC_TZA_STEP_3_DCOC_TZA_STEP_RCP_3(1192),
.dcoc_tza_step_04_init = XCVR_RX_DIG_DCOC_TZA_STEP_4_DCOC_TZA_STEP_GAIN_4(314) |
XCVR_RX_DIG_DCOC_TZA_STEP_4_DCOC_TZA_STEP_RCP_4(835),
.dcoc_tza_step_05_init = XCVR_RX_DIG_DCOC_TZA_STEP_5_DCOC_TZA_STEP_GAIN_5(436) |
XCVR_RX_DIG_DCOC_TZA_STEP_5_DCOC_TZA_STEP_RCP_5(601),
.dcoc_tza_step_06_init = XCVR_RX_DIG_DCOC_TZA_STEP_6_DCOC_TZA_STEP_GAIN_6(614) |
XCVR_RX_DIG_DCOC_TZA_STEP_6_DCOC_TZA_STEP_RCP_6(427),
.dcoc_tza_step_07_init = XCVR_RX_DIG_DCOC_TZA_STEP_7_DCOC_TZA_STEP_GAIN_7(845) |
XCVR_RX_DIG_DCOC_TZA_STEP_7_DCOC_TZA_STEP_RCP_7(310),
.dcoc_tza_step_08_init = XCVR_RX_DIG_DCOC_TZA_STEP_8_DCOC_TZA_STEP_GAIN_8(1256) |
XCVR_RX_DIG_DCOC_TZA_STEP_8_DCOC_TZA_STEP_RCP_8(209),
.dcoc_tza_step_09_init = XCVR_RX_DIG_DCOC_TZA_STEP_9_DCOC_TZA_STEP_GAIN_9(1805) |
XCVR_RX_DIG_DCOC_TZA_STEP_9_DCOC_TZA_STEP_RCP_9(145),
.dcoc_tza_step_10_init = XCVR_RX_DIG_DCOC_TZA_STEP_10_DCOC_TZA_STEP_GAIN_10(2653) |
XCVR_RX_DIG_DCOC_TZA_STEP_10_DCOC_TZA_STEP_RCP_10(99),
#if (RADIO_IS_GEN_2P1)
.dcoc_cal_fail_th_init = XCVR_RX_DIG_DCOC_CAL_FAIL_TH_DCOC_CAL_BETA_F_TH(20) |
XCVR_RX_DIG_DCOC_CAL_FAIL_TH_DCOC_CAL_ALPHA_F_TH(10),
.dcoc_cal_pass_th_init = XCVR_RX_DIG_DCOC_CAL_PASS_TH_DCOC_CAL_BETA_P_TH(16) |
XCVR_RX_DIG_DCOC_CAL_PASS_TH_DCOC_CAL_ALPHA_P_TH(2),
#endif /* (RADIO_IS_GEN_2P1) */
/* AGC Configs */
.agc_gain_tbl_03_00_init = XCVR_RX_DIG_AGC_GAIN_TBL_03_00_LNA_GAIN_00(0) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_BBA_GAIN_00(0) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_LNA_GAIN_01(1) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_BBA_GAIN_01(1) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_LNA_GAIN_02(2) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_BBA_GAIN_02(1) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_LNA_GAIN_03(2) |
XCVR_RX_DIG_AGC_GAIN_TBL_03_00_BBA_GAIN_03(2),
.agc_gain_tbl_07_04_init = XCVR_RX_DIG_AGC_GAIN_TBL_07_04_LNA_GAIN_04(2) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_BBA_GAIN_04(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_LNA_GAIN_05(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_BBA_GAIN_05(0) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_LNA_GAIN_06(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_BBA_GAIN_06(1) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_LNA_GAIN_07(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_07_04_BBA_GAIN_07(2),
.agc_gain_tbl_11_08_init = XCVR_RX_DIG_AGC_GAIN_TBL_11_08_LNA_GAIN_08(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_BBA_GAIN_08(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_LNA_GAIN_09(4) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_BBA_GAIN_09(2) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_LNA_GAIN_10(4) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_BBA_GAIN_10(3) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_LNA_GAIN_11(4) |
XCVR_RX_DIG_AGC_GAIN_TBL_11_08_BBA_GAIN_11(4),
.agc_gain_tbl_15_12_init = XCVR_RX_DIG_AGC_GAIN_TBL_15_12_LNA_GAIN_12(5) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_BBA_GAIN_12(4) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_LNA_GAIN_13(5) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_BBA_GAIN_13(5) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_LNA_GAIN_14(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_BBA_GAIN_14(4) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_LNA_GAIN_15(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_15_12_BBA_GAIN_15(5),
.agc_gain_tbl_19_16_init = XCVR_RX_DIG_AGC_GAIN_TBL_19_16_LNA_GAIN_16(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_BBA_GAIN_16(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_LNA_GAIN_17(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_BBA_GAIN_17(7) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_LNA_GAIN_18(7) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_BBA_GAIN_18(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_LNA_GAIN_19(7) |
XCVR_RX_DIG_AGC_GAIN_TBL_19_16_BBA_GAIN_19(7),
.agc_gain_tbl_23_20_init = XCVR_RX_DIG_AGC_GAIN_TBL_23_20_LNA_GAIN_20(8) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_BBA_GAIN_20(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_LNA_GAIN_21(8) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_BBA_GAIN_21(7) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_LNA_GAIN_22(9) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_BBA_GAIN_22(6) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_LNA_GAIN_23(9) |
XCVR_RX_DIG_AGC_GAIN_TBL_23_20_BBA_GAIN_23(7),
.agc_gain_tbl_26_24_init = XCVR_RX_DIG_AGC_GAIN_TBL_26_24_LNA_GAIN_24(9) |
XCVR_RX_DIG_AGC_GAIN_TBL_26_24_BBA_GAIN_24(8) |
XCVR_RX_DIG_AGC_GAIN_TBL_26_24_LNA_GAIN_25(9) |
XCVR_RX_DIG_AGC_GAIN_TBL_26_24_BBA_GAIN_25(9) |
XCVR_RX_DIG_AGC_GAIN_TBL_26_24_LNA_GAIN_26(9) |
XCVR_RX_DIG_AGC_GAIN_TBL_26_24_BBA_GAIN_26(10),
.rssi_ctrl_0_init = XCVR_RX_DIG_RSSI_CTRL_0_RSSI_USE_VALS(1) |
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_HOLD_SRC(0) |
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_HOLD_EN(1) |
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_IIR_CW_WEIGHT(0) |
#if !RADIO_IS_GEN_2P1
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_N_WINDOW_AVG(1) |
#else
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_N_WINDOW_NB(1) |
#endif /* !RADIO_IS_GEN_2P1 */
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_HOLD_DELAY(4) |
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_IIR_WEIGHT(3) |
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_VLD_SETTLE(3) |
XCVR_RX_DIG_RSSI_CTRL_0_RSSI_ADJ(0xE8) ,
.cca_ed_lqi_ctrl_0_init = XCVR_RX_DIG_CCA_ED_LQI_CTRL_0_LQI_CORR_THRESH(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_0_CORR_CNTR_THRESH(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_0_LQI_CNTR(0x1A) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_0_SNR_ADJ(0),
.cca_ed_lqi_ctrl_1_init = XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_RSSI_NOISE_AVG_DELAY(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_RSSI_NOISE_AVG_FACTOR(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_LQI_RSSI_WEIGHT(0x4) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_LQI_RSSI_SENS(0x7) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_SNR_LQI_DIS(0) |
#if !RADIO_IS_GEN_2P1
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_SEL_SNR_MODE(0) |
#endif /* !RADIO_IS_GEN_2P1 */
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_MEAS_TRANS_TO_IDLE(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_CCA1_ED_EN_DIS(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_MAN_MEAS_COMPLETE(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_MAN_AA_MATCH(0) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_SNR_LQI_WEIGHT(0x5) |
XCVR_RX_DIG_CCA_ED_LQI_CTRL_1_LQI_BIAS(0x2),
/* XCVR_TSM configs */
.tsm_ctrl = XCVR_TSM_CTRL_PA_RAMP_SEL(PA_RAMP_SEL) |
XCVR_TSM_CTRL_DATA_PADDING_EN(DATA_PADDING_EN) |
XCVR_TSM_CTRL_TSM_IRQ0_EN(0) |
XCVR_TSM_CTRL_TSM_IRQ1_EN(0) |
XCVR_TSM_CTRL_RAMP_DN_DELAY(0x4) |
XCVR_TSM_CTRL_TX_ABORT_DIS(0) |
XCVR_TSM_CTRL_RX_ABORT_DIS(0) |
XCVR_TSM_CTRL_ABORT_ON_CTUNE(0) |
XCVR_TSM_CTRL_ABORT_ON_CYCLE_SLIP(0) |
XCVR_TSM_CTRL_ABORT_ON_FREQ_TARG(0) |
XCVR_TSM_CTRL_BKPT(0xFF) ,
.tsm_ovrd2_init = XCVR_TSM_OVRD2_FREQ_TARG_LD_EN_OVRD(0) | XCVR_TSM_OVRD2_FREQ_TARG_LD_EN_OVRD_EN_MASK,
.end_of_seq_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(END_OF_RX_WU_26MHZ) | B1(END_OF_TX_WD) | B0(END_OF_TX_WU),
.end_of_seq_init_32mhz = B3(END_OF_RX_WD) | B2(END_OF_RX_WU) | B1(END_OF_TX_WD) | B0(END_OF_TX_WU),
#if !RADIO_IS_GEN_2P1
.lpps_ctrl_init = B3(102) | B2(40) | B1(0) | B0(0),
#endif /* !RADIO_IS_GEN_2P1 */
.tsm_fast_ctrl2_init_26mhz = B3(102 + ADD_FOR_26MHZ) | B2(40 + ADD_FOR_26MHZ) | B1(66) | B0(8),
.tsm_fast_ctrl2_init_32mhz = B3(102) | B2(40) | B1(66) | B0(8),
.pa_ramp_tbl_0_init = XCVR_TSM_PA_RAMP_TBL0_PA_RAMP0(PA_RAMP_0) | XCVR_TSM_PA_RAMP_TBL0_PA_RAMP1(PA_RAMP_1) |
XCVR_TSM_PA_RAMP_TBL0_PA_RAMP2(PA_RAMP_2) | XCVR_TSM_PA_RAMP_TBL0_PA_RAMP3(PA_RAMP_3),
.pa_ramp_tbl_1_init = XCVR_TSM_PA_RAMP_TBL1_PA_RAMP4(PA_RAMP_4) | XCVR_TSM_PA_RAMP_TBL1_PA_RAMP5(PA_RAMP_5) |
XCVR_TSM_PA_RAMP_TBL1_PA_RAMP6(PA_RAMP_6) | XCVR_TSM_PA_RAMP_TBL1_PA_RAMP7(PA_RAMP_7),
.recycle_count_init_26mhz = B3(0) | B2(0x1C + ADD_FOR_26MHZ) | B1(0x06) | B0(0x66 + ADD_FOR_26MHZ),
.recycle_count_init_32mhz = B3(0) | B2(0x1C) | B1(0x06) | B0(0x66),
.tsm_timing_00_init = B3(END_OF_RX_WD) | B2(0x00) | B1(END_OF_TX_WD) | B0(0x00), /* bb_ldo_hf_en */
.tsm_timing_01_init = B3(END_OF_RX_WD) | B2(0x00) | B1(END_OF_TX_WD) | B0(0x00), /* bb_ldo_adcdac_en */
.tsm_timing_02_init = B3(END_OF_RX_WD) | B2(0x00) | B1(0xFF) | B0(0xFF), /* bb_ldo_bba_en */
.tsm_timing_03_init = B3(END_OF_RX_WD) | B2(0x00) | B1(END_OF_TX_WD) | B0(0x00), /* bb_ldo_pd_en */
.tsm_timing_04_init = B3(END_OF_RX_WD) | B2(0x00) | B1(END_OF_TX_WD) | B0(0x00), /* bb_ldo_fdbk_en */
.tsm_timing_05_init = B3(END_OF_RX_WD) | B2(0x00) | B1(END_OF_TX_WD) | B0(0x00), /* bb_ldo_vcolo_en */
.tsm_timing_06_init = B3(END_OF_RX_WD) | B2(0x00) | B1(END_OF_TX_WD) | B0(0x00), /* bb_ldo_vtref_en */
.tsm_timing_07_init = B3(0x05) | B2(0x00) | B1(0x05) | B0(0x00), /* bb_ldo_fdbk_bleed_en */
.tsm_timing_08_init = B3(0x03) | B2(0x00) | B1(0x03) | B0(0x00), /* bb_ldo_vcolo_bleed_en */
.tsm_timing_09_init = B3(0x03) | B2(0x00) | B1(0x03) | B0(0x00), /* bb_ldo_vcolo_fastcharge_en */
.tsm_timing_10_init = B3(END_OF_RX_WD) | B2(0x03 + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x03), /* bb_xtal_pll_ref_clk_en */
.tsm_timing_11_init = B3(0xFF) | B2(0xFF) | B1(END_OF_TX_WD) | B0(0x03), /* bb_xtal_dac_ref_clk_en */
.tsm_timing_12_init = B3(END_OF_RX_WD) | B2(0x03 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_vco_ref_clk_en */
.tsm_timing_13_init = B3(0x18) | B2(0x00) | B1(0x4C) | B0(0x00), /* sy_vco_autotune_en */
.tsm_timing_14_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x31+ADD_FOR_26MHZ) | B1(END_OF_TX_WU + PD_CYCLE_SLIP_TX_LO_ADJ) | B0(0x63 + PD_CYCLE_SLIP_TX_HI_ADJ), /* sy_pd_cycle_slip_ld_ft_en */
.tsm_timing_14_init_32mhz = B3(END_OF_RX_WD) | B2(0x31 + AUX_PLL_DELAY) | B1(END_OF_TX_WU + PD_CYCLE_SLIP_TX_LO_ADJ) | B0(0x63 + PD_CYCLE_SLIP_TX_HI_ADJ),
.tsm_timing_15_init = B3(END_OF_RX_WD) | B2(0x03 + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x03), /* sy_vco_en */
.tsm_timing_16_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x1C + ADD_FOR_26MHZ) | B1(0xFF) | B0(0xFF), /* sy_lo_rx_buf_en */
.tsm_timing_16_init_32mhz = B3(END_OF_RX_WD) | B2(0x1C + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_17_init = B3(0xFF) | B2(0xFF) | B1(END_OF_TX_WD) | B0(0x55), /* sy_lo_tx_buf_en */
.tsm_timing_18_init = B3(END_OF_RX_WD) | B2(0x05 + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x05), /* sy_divn_en */
.tsm_timing_19_init = B3(0x18+AUX_PLL_DELAY) | B2(0x03 + AUX_PLL_DELAY) | B1(0x4C) | B0(0x03), /* sy_pd_filter_charge_en */
.tsm_timing_20_init = B3(END_OF_RX_WD) | B2(0x03 + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x03), /* sy_pd_en */
.tsm_timing_21_init = B3(END_OF_RX_WD) | B2(0x04 + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x04), /* sy_lo_divn_en */
.tsm_timing_22_init = B3(END_OF_RX_WD) | B2(0x04 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* sy_lo_rx_en */
.tsm_timing_23_init = B3(0xFF) | B2(0xFF) | B1(END_OF_TX_WD) | B0(0x04), /*sy_lo_tx_en */
.tsm_timing_24_init = B3(0x18) | B2(0x00) | B1(0x4C) | B0(0x00), /* sy_divn_cal_en */
.tsm_timing_25_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x1D + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_lna_mixer_en */
.tsm_timing_25_init_32mhz = B3(END_OF_RX_WD) | B2(0x1D + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_26_init = B3(0xFF) | B2(0xFF) | B1(END_OF_TX_WD) | B0(0x58), /* tx_pa_en */
.tsm_timing_27_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x20 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_adc_i_q_en */
.tsm_timing_27_init_32mhz = B3(END_OF_RX_WD) | B2(0x20 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_28_init_26mhz = B3(0x21 + ADD_FOR_26MHZ) | B2(0x20 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_adc_reset_en */
.tsm_timing_28_init_32mhz = B3(0x21 + AUX_PLL_DELAY) | B2(0x20 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_29_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x1E + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_bba_i_q_en */
.tsm_timing_29_init_32mhz = B3(END_OF_RX_WD) | B2(0x1E + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_30_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x20 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_bba_pdet_en */
.tsm_timing_30_init_32mhz = B3(END_OF_RX_WD) | B2(0x20 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_31_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x1F + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_bba_tza_dcoc_en */
.tsm_timing_31_init_32mhz = B3(END_OF_RX_WD) | B2(0x1F + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_32_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x1D + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_tza_i_q_en */
.tsm_timing_32_init_32mhz = B3(END_OF_RX_WD) | B2(0x1D + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_33_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x20 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_tza_pdet_en */
.tsm_timing_33_init_32mhz = B3(END_OF_RX_WD) | B2(0x20 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_34_init = B3(END_OF_RX_WD) | B2(0x07 + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x07), /* pll_dig_en */
.tsm_timing_35_init = B3(0xFF) | B2(0xFF) | B1(END_OF_TX_WD), /* tx_dig_en - Byte 0 comes from mode specific settings */
.tsm_timing_36_init_26mhz = B3(END_OF_RX_WD) | B2(0x66 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_dig_en */
.tsm_timing_36_init_32mhz = B3(END_OF_RX_WD) | B2(0x66 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_37_init_26mhz = B3(0x67 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B2(0x66 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_init */
.tsm_timing_37_init_32mhz = B3(0x67 + AUX_PLL_DELAY) | B2(0x66 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_38_init = B3(END_OF_RX_WD) | B2(0x0E + AUX_PLL_DELAY) | B1(END_OF_TX_WD) | B0(0x42), /* sigma_delta_en */
.tsm_timing_39_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x66 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rx_phy_en */
.tsm_timing_39_init_32mhz = B3(END_OF_RX_WD) | B2(0x66 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_40_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x26 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* dcoc_en */
.tsm_timing_40_init_32mhz = B3(END_OF_RX_WD) | B2(0x26 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_41_init_26mhz = B3(0x27 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B2(0x26 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* dcoc_init */
.tsm_timing_41_init_32mhz = B3(0x27 + AUX_PLL_DELAY) | B2(0x26 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_51_init = B3(END_OF_RX_WD) | B2(0x03 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_bias_en */
.tsm_timing_52_init_26mhz = B3(0x17 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B2(0x06 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_fcal_en */
.tsm_timing_52_init_32mhz = B3(0x17 + AUX_PLL_DELAY) | B2(0x06 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_53_init = B3(END_OF_RX_WD) | B2(0x03 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_lf_pd_en */
.tsm_timing_54_init_26mhz = B3(0x17 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B2(0x03 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_pd_lf_filter_charge_en */
.tsm_timing_54_init_32mhz = B3(0x17 + AUX_PLL_DELAY) | B2(0x03 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_55_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x20 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_adc_buf_en */
.tsm_timing_55_init_32mhz = B3(END_OF_RX_WD) | B2(0x20 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_56_init_26mhz = B3(END_OF_RX_WD_26MHZ) | B2(0x20 + ADD_FOR_26MHZ + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /* rxtx_auxpll_dig_buf_en */
.tsm_timing_56_init_32mhz = B3(END_OF_RX_WD) | B2(0x20 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF),
.tsm_timing_57_init = B3(0x1A + AUX_PLL_DELAY) | B2(0x03 + AUX_PLL_DELAY) | B1(0xFF) | B0(0xFF), /*rxtx_rccal_en */
.tsm_timing_58_init = B3(0xFF) | B2(0xFF) | B1(END_OF_TX_WD) | B0(0x03), /* tx_hpm_dac_en */
/* XCVR_TX_DIG configs */
#define radio_dft_mode 0
#define lfsr_length 4
#define lfsr_en 0
#define dft_clk_sel 4
#define tx_dft_en 0
#define soc_test_sel 0
#define tx_capture_pol 0
#define freq_word_adj 0
#define lrm 0
#define data_padding_pat_1 0x55
#define data_padding_pat_0 0xAA
#define gfsk_multiply_table_manual 0
#define gfsk_mi 1
#define gfsk_mld 0
#define gfsk_fld 0
#define gfsk_mod_index_scaling 0
#define tx_image_filter_ovrd_en 0
#define tx_image_filter_0_ovrd 0
#define tx_image_filter_1_ovrd 0
#define tx_image_filter_2_ovrd 0
#define gfsk_filter_coeff_manual2 0xC0630401
#define gfsk_filter_coeff_manual1 0xBB29960D
#define fsk_modulation_scale_0 0x1800
#define fsk_modulation_scale_1 0x0800
#define dft_mod_patternval 0
#define ctune_bist_go 0
#define ctune_bist_thrshld 0
#define pa_am_mod_freq 0
#define pa_am_mod_entries 0
#define pa_am_mod_en 0
#define syn_bist_go 0
#define syn_bist_all_channels 0
#define freq_count_threshold 0
#define hpm_inl_bist_go 0
#define hpm_dnl_bist_go 0
#define dft_max_ram_size 0
.tx_ctrl = XCVR_TX_DIG_CTRL_RADIO_DFT_MODE(radio_dft_mode) |
XCVR_TX_DIG_CTRL_LFSR_LENGTH(lfsr_length) |
XCVR_TX_DIG_CTRL_LFSR_EN(lfsr_en) |
XCVR_TX_DIG_CTRL_DFT_CLK_SEL(dft_clk_sel) |
XCVR_TX_DIG_CTRL_TX_DFT_EN(tx_dft_en) |
XCVR_TX_DIG_CTRL_SOC_TEST_SEL(soc_test_sel) |
XCVR_TX_DIG_CTRL_TX_CAPTURE_POL(tx_capture_pol) |
XCVR_TX_DIG_CTRL_FREQ_WORD_ADJ(freq_word_adj),
/*-------------------------------------------------------------------------------------------------*/
.tx_data_padding = XCVR_TX_DIG_DATA_PADDING_LRM(lrm) |
XCVR_TX_DIG_DATA_PADDING_DATA_PADDING_PAT_1(data_padding_pat_1) |
XCVR_TX_DIG_DATA_PADDING_DATA_PADDING_PAT_0(data_padding_pat_0),
/*-------------------------------------------------------------------------------------------------*/
.tx_dft_pattern = XCVR_TX_DIG_DFT_PATTERN_DFT_MOD_PATTERN(dft_mod_patternval),
#if !RADIO_IS_GEN_2P1
/*-------------------------------------------------------------------------------------------------*/
.rf_dft_bist_1 = XCVR_TX_DIG_RF_DFT_BIST_1_CTUNE_BIST_GO(ctune_bist_go) |
XCVR_TX_DIG_RF_DFT_BIST_1_CTUNE_BIST_THRSHLD(ctune_bist_thrshld) |
XCVR_TX_DIG_RF_DFT_BIST_1_PA_AM_MOD_FREQ(pa_am_mod_freq) |
XCVR_TX_DIG_RF_DFT_BIST_1_PA_AM_MOD_ENTRIES(pa_am_mod_entries) |
XCVR_TX_DIG_RF_DFT_BIST_1_PA_AM_MOD_EN(pa_am_mod_en),
/*-------------------------------------------------------------------------------------------------*/
.rf_dft_bist_2 = XCVR_TX_DIG_RF_DFT_BIST_2_SYN_BIST_GO(syn_bist_go) |
XCVR_TX_DIG_RF_DFT_BIST_2_SYN_BIST_ALL_CHANNELS(syn_bist_all_channels) |
XCVR_TX_DIG_RF_DFT_BIST_2_FREQ_COUNT_THRESHOLD(freq_count_threshold) |
XCVR_TX_DIG_RF_DFT_BIST_2_HPM_INL_BIST_GO(hpm_inl_bist_go) |
XCVR_TX_DIG_RF_DFT_BIST_2_HPM_DNL_BIST_GO(hpm_dnl_bist_go) |
XCVR_TX_DIG_RF_DFT_BIST_2_DFT_MAX_RAM_SIZE(dft_max_ram_size),
#endif /* !RADIO_IS_GEN_2P1 */
};

View File

@ -0,0 +1,217 @@
/*
* The Clear BSD License
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_xcvr.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
/* ========================= DATA RATE ONLY settings ===============*/
/*!
* @brief XCVR 1Mbps DATA RATE specific configure structure
*/
const xcvr_datarate_config_t xcvr_1mbps_config =
{
.data_rate = DR_1MBPS,
.phy_el_cfg_init = XCVR_PHY_EL_CFG_EL_WIN_SIZE(0xF) |
#if !RADIO_IS_GEN_2P1
XCVR_PHY_EL_CFG_EL_ZB_WIN_SIZE(0) |
#endif /* !RADIO_IS_GEN_2P1 */
XCVR_PHY_EL_CFG_EL_INTERVAL(0x20) ,
.rx_dig_ctrl_init_26mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(0) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.rx_dig_ctrl_init_32mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.agc_ctrl_1_init_26mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(10) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.agc_ctrl_1_init_32mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(12) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.dcoc_ctrl_0_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(10) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(3),
.dcoc_ctrl_0_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(12) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(4),
.dcoc_ctrl_1_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(3),
.dcoc_ctrl_1_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(3),
.dcoc_cal_iir_init_26mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(2),
.dcoc_cal_iir_init_32mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(3) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(2),
.dc_resid_ctrl_26mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(48) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(5),
.dc_resid_ctrl_32mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(48) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(6),
};
/*!
* @brief XCVR 500K bps DATA RATE specific configure structure
*/
const xcvr_datarate_config_t xcvr_500kbps_config =
{
.data_rate = DR_500KBPS,
.phy_el_cfg_init = XCVR_PHY_EL_CFG_EL_WIN_SIZE(0x8) |
#if !RADIO_IS_GEN_2P1
XCVR_PHY_EL_CFG_EL_ZB_WIN_SIZE(0) |
#endif /* !RADIO_IS_GEN_2P1 */
XCVR_PHY_EL_CFG_EL_INTERVAL(0x10),
.rx_dig_ctrl_init_26mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.rx_dig_ctrl_init_32mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(2) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.agc_ctrl_1_init_26mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(15) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.agc_ctrl_1_init_32mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(18) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.dcoc_ctrl_0_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(13) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(29),
.dcoc_ctrl_0_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(16) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(36),
.dcoc_ctrl_1_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(2) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(2),
.dcoc_ctrl_1_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(2) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(2),
.dcoc_cal_iir_init_26mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(2),
.dcoc_cal_iir_init_32mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(2),
.dc_resid_ctrl_26mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(32) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(4),
.dc_resid_ctrl_32mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(32) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(4),
};
/*!
* @brief XCVR 250K bps DATA RATE specific configure structure
*/
const xcvr_datarate_config_t xcvr_250kbps_config =
{
.data_rate = DR_250KBPS,
.phy_el_cfg_init = XCVR_PHY_EL_CFG_EL_WIN_SIZE(0x4) |
#if !RADIO_IS_GEN_2P1
XCVR_PHY_EL_CFG_EL_ZB_WIN_SIZE(0) |
#endif /* !RADIO_IS_GEN_2P1 */
XCVR_PHY_EL_CFG_EL_INTERVAL(0x8) ,
.rx_dig_ctrl_init_26mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(2) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.rx_dig_ctrl_init_32mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(4) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.agc_ctrl_1_init_26mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(18) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.agc_ctrl_1_init_32mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(22) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.dcoc_ctrl_0_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(16) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(34),
.dcoc_ctrl_0_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(20) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(42),
.dcoc_ctrl_1_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(2),
.dcoc_ctrl_1_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(2),
.dcoc_cal_iir_init_26mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(0) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(1) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(1),
.dcoc_cal_iir_init_32mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(0) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(1) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(1),
.dc_resid_ctrl_26mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(16) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(4),
.dc_resid_ctrl_32mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(16) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(4),
};

View File

@ -0,0 +1,249 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fsl_xcvr.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
const xcvr_mode_config_t zgbe_mode_config =
{
.radio_mode = ZIGBEE_MODE,
.scgc5_clock_ena_bits = SIM_SCGC5_PHYDIG_MASK | SIM_SCGC5_ZigBee_MASK,
/* XCVR_MISC configs */
.xcvr_ctrl.mask = XCVR_CTRL_XCVR_CTRL_PROTOCOL_MASK |
XCVR_CTRL_XCVR_CTRL_TGT_PWR_SRC_MASK |
XCVR_CTRL_XCVR_CTRL_DEMOD_SEL_MASK,
.xcvr_ctrl.init = XCVR_CTRL_XCVR_CTRL_PROTOCOL(4) |
XCVR_CTRL_XCVR_CTRL_TGT_PWR_SRC(7) |
XCVR_CTRL_XCVR_CTRL_DEMOD_SEL(2),
/* XCVR_PHY configs */
.phy_pre_ref0_init = 0x0, /* Not used in Zigbee */
.phy_pre_ref1_init = 0x0, /* Not used in Zigbee */
.phy_pre_ref2_init = 0x0, /* Not used in Zigbee */
.phy_cfg1_init = XCVR_PHY_CFG1_AA_PLAYBACK(0) |
XCVR_PHY_CFG1_AA_OUTPUT_SEL(1) |
XCVR_PHY_CFG1_FSK_BIT_INVERT(0) |
XCVR_PHY_CFG1_BSM_EN_BLE(0) |
XCVR_PHY_CFG1_DEMOD_CLK_MODE(0) |
XCVR_PHY_CFG1_CTS_THRESH(0xC0) |
XCVR_PHY_CFG1_FSK_FTS_TIMEOUT(2),
.phy_el_cfg_init = XCVR_PHY_EL_CFG_EL_ENABLE(1)
#if !RADIO_IS_GEN_2P1
| XCVR_PHY_EL_CFG_EL_ZB_ENABLE(0)
#endif /* !RADIO_IS_GEN_2P1 */
,
/* XCVR_PLL_DIG configs */
/* XCVR_RX_DIG configs */
.rx_dig_ctrl_init_26mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_FSK_ZB_SEL(1) | /* Depends on protocol */
XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN(1) | /* Depends on protocol */
XCVR_RX_DIG_RX_DIG_CTRL_RX_SRC_RATE(0),
.rx_dig_ctrl_init_32mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_FSK_ZB_SEL(1) | /* Depends on protocol */
XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN(1), /* Depends on protocol */
.agc_ctrl_0_init = XCVR_RX_DIG_AGC_CTRL_0_AGC_DOWN_RSSI_THRESH(0xFF),
/* XCVR_TSM configs */
#if (DATA_PADDING_EN)
.tsm_timing_35_init = B0(TX_DIG_EN_ASSERT+ZGBE_TX_DIG_EN_TX_HI_ADJ), /* DATA_PADDING adjustments are specified relative to the non-Zigbee base timing */
#else
.tsm_timing_35_init = B0(ZGBE_TX_DIG_EN_ASSERT),
#endif /* (DATA_PADDING_EN) */
/* XCVR_TX_DIG configs */
.tx_gfsk_ctrl = XCVR_TX_DIG_GFSK_CTRL_GFSK_MULTIPLY_TABLE_MANUAL(0x4000) |
XCVR_TX_DIG_GFSK_CTRL_GFSK_MI(1) |
XCVR_TX_DIG_GFSK_CTRL_GFSK_MLD(0) |
XCVR_TX_DIG_GFSK_CTRL_GFSK_FLD(0) |
XCVR_TX_DIG_GFSK_CTRL_GFSK_MOD_INDEX_SCALING(0) |
XCVR_TX_DIG_GFSK_CTRL_TX_IMAGE_FILTER_OVRD_EN(0) |
XCVR_TX_DIG_GFSK_CTRL_TX_IMAGE_FILTER_0_OVRD(0) |
XCVR_TX_DIG_GFSK_CTRL_TX_IMAGE_FILTER_1_OVRD(0) |
XCVR_TX_DIG_GFSK_CTRL_TX_IMAGE_FILTER_2_OVRD(0) ,
.tx_gfsk_coeff1_26mhz = 0,
.tx_gfsk_coeff2_26mhz = 0,
.tx_gfsk_coeff1_32mhz = 0,
.tx_gfsk_coeff2_32mhz = 0,
};
const xcvr_mode_datarate_config_t xcvr_ZIGBEE_500kbps_config =
{
.radio_mode = ZIGBEE_MODE,
.data_rate = DR_500KBPS,
.ana_sy_ctrl2.mask = XCVR_ANALOG_SY_CTRL_2_SY_VCO_KVM_MASK,
.ana_sy_ctrl2.init = XCVR_ANALOG_SY_CTRL_2_SY_VCO_KVM(1), /* VCO KVM */
.ana_rx_bba.mask = XCVR_ANALOG_RX_BBA_RX_BBA_BW_SEL_MASK | XCVR_ANALOG_RX_BBA_RX_BBA2_BW_SEL_MASK,
.ana_rx_bba.init = XCVR_ANALOG_RX_BBA_RX_BBA_BW_SEL(1) | XCVR_ANALOG_RX_BBA_RX_BBA2_BW_SEL(1), /* BBA_BW_SEL and BBA2_BW_SEL */
.ana_rx_tza.mask = XCVR_ANALOG_RX_TZA_RX_TZA_BW_SEL_MASK,
.ana_rx_tza.init = XCVR_ANALOG_RX_TZA_RX_TZA_BW_SEL(1), /*TZA_BW_SEL */
.phy_cfg2_init = XCVR_PHY_CFG2_PHY_FIFO_PRECHG(8) |
XCVR_PHY_CFG2_X2_DEMOD_GAIN(0xA) ,
/* AGC configs */
.agc_ctrl_2_init_26mhz = XCVR_RX_DIG_AGC_CTRL_2_BBA_GAIN_SETTLE_TIME(8) |
XCVR_RX_DIG_AGC_CTRL_2_BBA_PDET_SEL_LO(5) |
XCVR_RX_DIG_AGC_CTRL_2_BBA_PDET_SEL_HI(6) |
XCVR_RX_DIG_AGC_CTRL_2_TZA_PDET_SEL_LO(3) |
XCVR_RX_DIG_AGC_CTRL_2_TZA_PDET_SEL_HI(5) |
XCVR_RX_DIG_AGC_CTRL_2_AGC_FAST_EXPIRE(5),
.agc_ctrl_2_init_32mhz = XCVR_RX_DIG_AGC_CTRL_2_BBA_GAIN_SETTLE_TIME(10) |
XCVR_RX_DIG_AGC_CTRL_2_BBA_PDET_SEL_LO(5) |
XCVR_RX_DIG_AGC_CTRL_2_BBA_PDET_SEL_HI(6) |
XCVR_RX_DIG_AGC_CTRL_2_TZA_PDET_SEL_LO(3) |
XCVR_RX_DIG_AGC_CTRL_2_TZA_PDET_SEL_HI(5) |
XCVR_RX_DIG_AGC_CTRL_2_AGC_FAST_EXPIRE(5),
/* All constant values are represented as 16 bits, register writes will remove unused bits */
.rx_chf_coeffs_26mhz.rx_chf_coef_0 = 0xFFFF,
.rx_chf_coeffs_26mhz.rx_chf_coef_1 = 0xFFFF,
.rx_chf_coeffs_26mhz.rx_chf_coef_2 = 0x0002,
.rx_chf_coeffs_26mhz.rx_chf_coef_3 = 0x0008,
.rx_chf_coeffs_26mhz.rx_chf_coef_4 = 0x000A,
.rx_chf_coeffs_26mhz.rx_chf_coef_5 = 0x0000,
.rx_chf_coeffs_26mhz.rx_chf_coef_6 = 0xFFE8,
.rx_chf_coeffs_26mhz.rx_chf_coef_7 = 0xFFD7,
.rx_chf_coeffs_26mhz.rx_chf_coef_8 = 0xFFE6,
.rx_chf_coeffs_26mhz.rx_chf_coef_9 = 0x0022,
.rx_chf_coeffs_26mhz.rx_chf_coef_10 = 0x0075,
.rx_chf_coeffs_26mhz.rx_chf_coef_11 = 0x00B2,
/* IEEE 802.15.4 32MHz Channel Filter -- 1.55/1.25/5/0.97/B5 */
.rx_chf_coeffs_32mhz.rx_chf_coef_0 = 0xFFFF,
.rx_chf_coeffs_32mhz.rx_chf_coef_1 = 0xFFFF,
.rx_chf_coeffs_32mhz.rx_chf_coef_2 = 0x0005,
.rx_chf_coeffs_32mhz.rx_chf_coef_3 = 0x0004,
.rx_chf_coeffs_32mhz.rx_chf_coef_4 = 0xFFF2,
.rx_chf_coeffs_32mhz.rx_chf_coef_5 = 0xFFF2,
.rx_chf_coeffs_32mhz.rx_chf_coef_6 = 0x001D,
.rx_chf_coeffs_32mhz.rx_chf_coef_7 = 0x0025,
.rx_chf_coeffs_32mhz.rx_chf_coef_8 = 0xFFCE,
.rx_chf_coeffs_32mhz.rx_chf_coef_9 = 0xFFA1,
.rx_chf_coeffs_32mhz.rx_chf_coef_10 = 0x0040,
.rx_chf_coeffs_32mhz.rx_chf_coef_11 = 0x0124,
.rx_rccal_ctrl_0 = XCVR_RX_DIG_RX_RCCAL_CTRL0_BBA_RCCAL_OFFSET(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_BBA_RCCAL_MANUAL(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_BBA_RCCAL_DIS(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_RCCAL_SMP_DLY(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_RCCAL_COMP_INV(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_TZA_RCCAL_OFFSET(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_TZA_RCCAL_MANUAL(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL0_TZA_RCCAL_DIS(0) ,
.rx_rccal_ctrl_1 = XCVR_RX_DIG_RX_RCCAL_CTRL1_ADC_RCCAL_OFFSET(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL1_ADC_RCCAL_MANUAL(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL1_ADC_RCCAL_DIS(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL1_BBA2_RCCAL_OFFSET(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL1_BBA2_RCCAL_MANUAL(0) |
XCVR_RX_DIG_RX_RCCAL_CTRL1_BBA2_RCCAL_DIS(0) ,
.tx_fsk_scale_26mhz = XCVR_TX_DIG_FSK_SCALE_FSK_MODULATION_SCALE_0(0x1627) | XCVR_TX_DIG_FSK_SCALE_FSK_MODULATION_SCALE_1(0x09d9),
.tx_fsk_scale_32mhz = XCVR_TX_DIG_FSK_SCALE_FSK_MODULATION_SCALE_0(0x1800) | XCVR_TX_DIG_FSK_SCALE_FSK_MODULATION_SCALE_1(0x0800),
};
/* CUSTOM datarate dependent config structure for ONLY 802.15.4 */
/*!
* @brief XCVR 500K bps DATA RATE specific configure structure
*/
const xcvr_datarate_config_t xcvr_802_15_4_500kbps_config =
{
.data_rate = DR_500KBPS,
.phy_el_cfg_init = XCVR_PHY_EL_CFG_EL_ZB_WIN_SIZE(0) |
XCVR_PHY_EL_CFG_EL_WIN_SIZE(0x8) |
XCVR_PHY_EL_CFG_EL_INTERVAL(0x10) ,
.rx_dig_ctrl_init_26mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(1) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.rx_dig_ctrl_init_32mhz = XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_OSR(2) |
XCVR_RX_DIG_RX_DIG_CTRL_RX_DEC_FILT_GAIN(16),
.agc_ctrl_1_init_26mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(13) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.agc_ctrl_1_init_32mhz = XCVR_RX_DIG_AGC_CTRL_1_LNA_GAIN_SETTLE_TIME(10) |
XCVR_RX_DIG_AGC_CTRL_1_PRESLOW_EN(PRESLOW_ENA),
.dcoc_ctrl_0_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(13) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(29),
.dcoc_ctrl_0_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_DLY(21) |
XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORR_HOLD_TIME(47),
.dcoc_ctrl_1_init_26mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(2) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(2),
.dcoc_ctrl_1_init_32mhz = XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_IDX(2) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_TRK_EST_GS_CNT(0) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_SIGN_SCALE_GS_IDX(1) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHAC_SCALE_GS_IDX(3) |
XCVR_RX_DIG_DCOC_CTRL_1_DCOC_ALPHA_RADIUS_GS_IDX(2),
.dcoc_cal_iir_init_26mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(2),
.dcoc_cal_iir_init_32mhz = XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR3A_IDX(1) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR2A_IDX(2) |
XCVR_RX_DIG_DCOC_CAL_IIR_DCOC_CAL_IIR1A_IDX(1),
.dc_resid_ctrl_26mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(26) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(4),
.dc_resid_ctrl_32mhz = XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_NWIN(40) |
XCVR_RX_DIG_DC_RESID_CTRL_DC_RESID_DLY(0),
};

View File

@ -0,0 +1,535 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cpu.h"
#include "fsl_xcvr.h"
#include "ifr_radio.h"
#include "fsl_os_abstraction.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define IFR_RAM (0)
#if RADIO_IS_GEN_3P0
#define RDINDX (0x41U)
#define K3_BASE_INDEX (0x11U) /* Based for read index */
#else
#define RDRSRC (0x03U)
#define KW4x_512_BASE (0x20000U)
#define KW4x_256_BASE (0x10000U)
#endif /* RADIO_IS_GEN_3P0 */
#if RADIO_IS_GEN_2P1
#define FTFA (FTFE)
#endif /* RADIO_IS_GEN_2P1 */
/*******************************************************************************
* Prototypes
******************************************************************************/
static uint32_t read_another_ifr_word(void);
static uint32_t read_first_ifr_word(uint32_t read_addr);
#if RADIO_IS_GEN_3P0
static uint64_t read_index_ifr(uint32_t read_addr);
#else
/*! *********************************************************************************
* @brief Reads a location in block 1 IFR for use by the radio.
*
* This function handles reading IFR data from flash memory for trim loading.
*
* @param read_addr the address in the IFR to be read.
*
* @details This function wraps both the Gen2 read_resource command and the Gen2.1 and Gen3 read_index
***********************************************************************************/
#if RADIO_IS_GEN_2P1
static uint64_t read_resource_ifr(uint32_t read_addr);
#else
static uint32_t read_resource_ifr(uint32_t read_addr);
#endif /* RADIO_IS_GEN_2P1 */
#endif /* RADIO_IS_GEN_3P0 */
static void store_sw_trim(IFR_SW_TRIM_TBL_ENTRY_T * sw_trim_tbl, uint16_t num_entries, uint32_t addr, uint32_t data);
/*******************************************************************************
* Variables
******************************************************************************/
static uint32_t ifr_read_addr;
#if RADIO_IS_GEN_3P0
static uint64_t packed_data_long; /* Storage for 2 32 bit values to be read by read_index */
static uint8_t num_words_avail; /* Number of 32 bit words available in packed_data_long storage */
const uint32_t BLOCK_1_IFR[]=
{
/* Revised fallback table which should work with untrimmed parts */
0xABCDFFFEU, /* Version #FFFE indicates default trim values */
/* Trim table is empty for Gen3 by default */
/* No TRIM_STATUS in SW fallback array. */
0xFEED0E0FU /* End of File */
};
#else
#if RADIO_IS_GEN_2P0
const uint32_t BLOCK_1_IFR[]=
{
/* Revised fallback table which should work with untrimmed parts */
0xABCDFFFEU, /* Version #FFFE indicates default trim values */
0x4005912CU, /* RSIM_ANA_TRIM address */
0x784B0000U, /* RSIM_ANA_TRIM default value */
/* No TRIM_STATUS in SW fallback array. */
0xFEED0E0FU /* End of File */
};
#else
static uint64_t packed_data_long; /* Storage for 2 32 bit values to be read by read_index */
static uint8_t num_words_avail; /* Number of 32 bit words available in packed_data_long storage */
const uint32_t BLOCK_1_IFR[]=
{
/* Revised fallback table which should work with untrimmed parts */
0xABCDFFFEU, /* Version #FFFE indicates default trim values */
0x4005912CU, /* RSIM_ANA_TRIM address */
0x784B0000U, /* RSIM_ANA_TRIM default value */
/* No TRIM_STATUS in SW fallback array. */
0xFEED0E0FU /* End of File */
};
#endif /* RADIO_IS_GEN_2P0 */
#endif /* RADIO_IS_GEN_3P0 */
/*******************************************************************************
* Code
******************************************************************************/
/*! *********************************************************************************
* \brief Read command for reading the first 32bit word from IFR, encapsulates different
* flash IFR read mechanisms for multiple generations of SOC
*
* \param read_addr flash address
*
* \return 8 bytes of packed data containing radio trims only
*
***********************************************************************************/
static uint32_t read_first_ifr_word(uint32_t read_addr)
{
ifr_read_addr = read_addr;
return read_another_ifr_word();
}
/*! *********************************************************************************
* \brief Read command for reading additional 32bit words from IFR. Encapsulates multiple IFR read mechanisms.
*
* \param read_addr flash address
*
* \return 8 bytes of packed data containing radio trims only
*
* \remarks PRE-CONDITIONS:
* The function read_first_ifr_word() must have been called so that the ifr_read_addr variable is setup prior to use.
*
***********************************************************************************/
static uint32_t read_another_ifr_word(void)
{
uint32_t packed_data;
#if (RADIO_IS_GEN_3P0 || RADIO_IS_GEN_2P1)
/* Using some static storage and alternating reads to read_index_ifr to replace read_resource_ifr */
if (num_words_avail == 0)
{
#if RADIO_IS_GEN_3P0
packed_data_long = read_index_ifr(ifr_read_addr);
#else /* Use 64 bit return version of read_resource */
packed_data_long = read_resource_ifr(ifr_read_addr);
#endif /* RADIO_IS_GEN_3P0 */
num_words_avail = 2;
ifr_read_addr++; /* Read index addresses increment by 1 */
}
packed_data = (uint32_t)(packed_data_long & 0xFFFFFFFF);
packed_data_long = packed_data_long >> 32;
num_words_avail--;
#else
packed_data = read_resource_ifr(ifr_read_addr);
ifr_read_addr += 4; /* Read resource addresses increment by 4 */
#endif /* (RADIO_IS_GEN_3P0 || RADIO_IS_GEN_2P1) */
return packed_data;
}
#if RADIO_IS_GEN_3P0
/*! *********************************************************************************
* \brief Read command for reading from IFR using RDINDEX command
*
* \param read_addr flash address
*
* \return 8 bytes of packed data containing radio trims only
*
***********************************************************************************/
static uint64_t read_index_ifr(uint32_t read_addr)
{
uint8_t rdindex = read_addr;
uint64_t read_data;
uint8_t i;
while ((FTFE_FSTAT_CCIF_MASK & FTFE->FSTAT) == 0); /* Wait till CCIF=1 to make sure not interrupting a prior operation */
if ((FTFE->FSTAT & FTFE_FSTAT_ACCERR_MASK) == FTFE_FSTAT_ACCERR_MASK )
{
FTFE->FSTAT = (1 << FTFE_FSTAT_ACCERR_SHIFT); /* Write 1 to ACCEER to clear errors */
}
FTFE->FCCOB[0] = RDINDX;
FTFE->FCCOB[1] = rdindex;
OSA_InterrupDisable();
FTFE->FSTAT = FTFE_FSTAT_CCIF_MASK;
while((FTFE_FSTAT_CCIF_MASK & FTFE->FSTAT) == 0); /* Wait till CCIF=1 */
OSA_InterruptEnable();
/* Pack read data back into 64 bit type */
read_data = FTFE->FCCOB[11]; /* MSB goes in first, will be shifted left sequentially */
for (i = 10; i > 3; i--)
{
read_data = read_data << 8;
read_data |= FTFE->FCCOB[i];
}
return read_data;
}
#else
/*! *********************************************************************************
* \brief Read command for reading from IFR
*
* \param read_addr flash address
*
* \return packed data containing radio trims only
*
***********************************************************************************/
#if RADIO_IS_GEN_2P0
static uint32_t read_resource_ifr(uint32_t read_addr)
{
uint32_t packed_data;
uint8_t flash_addr23_16, flash_addr15_8, flash_addr7_0;
uint32_t read_data31_24, read_data23_16, read_data15_8, read_data7_0;
flash_addr23_16 = (uint8_t)((read_addr & 0xFF0000) >> 16);
flash_addr15_8 = (uint8_t)((read_addr & 0x00FF00) >> 8);
flash_addr7_0 = (uint8_t)(read_addr & 0xFF);
while ((FTFA_FSTAT_CCIF_MASK & FTFA->FSTAT) == 0); /* Wait till CCIF=1 */
if ((FTFA->FSTAT & FTFA_FSTAT_ACCERR_MASK) == FTFA_FSTAT_ACCERR_MASK )
{
FTFA->FSTAT = (1<<FTFA_FSTAT_ACCERR_SHIFT); /* Write 1 to ACCEER to clear errors */
}
FTFA->FCCOB0 = RDRSRC;
FTFA->FCCOB1 = flash_addr23_16;
FTFA->FCCOB2 = flash_addr15_8;
FTFA->FCCOB3 = flash_addr7_0;
FTFA->FCCOB8 = 0x00;
OSA_InterruptDisable();
FTFA->FSTAT = FTFA_FSTAT_CCIF_MASK;
while ((FTFA_FSTAT_CCIF_MASK & FTFA->FSTAT) == 0); /* Wait till CCIF=1 */
OSA_InterruptEnable();
/* Start reading */
read_data31_24 = FTFA->FCCOB4; /* FTFA->FCCOB[4] */
read_data23_16 = FTFA->FCCOB5; /* FTFA->FCCOB[5] */
read_data15_8 = FTFA->FCCOB6; /* FTFA->FCCOB[6] */
read_data7_0 = FTFA->FCCOB7; /* FTFA->FCCOB[7] */
packed_data = (read_data31_24 << 24) | (read_data23_16 << 16) | (read_data15_8 << 8) | (read_data7_0 << 0);
return packed_data;
}
#else
static uint64_t read_resource_ifr(uint32_t read_addr)
{
uint64_t packed_data;
uint8_t flash_addr23_16, flash_addr15_8, flash_addr7_0;
uint8_t read_data[8];
uint64_t temp_64;
uint8_t i;
flash_addr23_16 = (uint8_t)((read_addr & 0xFF0000) >> 16);
flash_addr15_8 = (uint8_t)((read_addr & 0x00FF00) >> 8);
flash_addr7_0 = (uint8_t)(read_addr & 0xFF);
while((FTFE_FSTAT_CCIF_MASK & FTFE->FSTAT) == 0); /* Wait till CCIF=1 */
if ((FTFE->FSTAT & FTFE_FSTAT_ACCERR_MASK) == FTFE_FSTAT_ACCERR_MASK )
{
FTFE->FSTAT = (1<<FTFE_FSTAT_ACCERR_SHIFT); /* Write 1 to ACCEER to clear errors */
}
FTFE->FCCOB0 = RDRSRC;
FTFE->FCCOB1 = flash_addr23_16;
FTFE->FCCOB2 = flash_addr15_8;
FTFE->FCCOB3 = flash_addr7_0;
FTFE->FCCOB4 = 0x00;
OSA_InterruptDisable();
FTFE->FSTAT = FTFE_FSTAT_CCIF_MASK;
while ((FTFE_FSTAT_CCIF_MASK & FTFE->FSTAT) == 0); /* Wait till CCIF=1 */
OSA_InterruptEnable();
/* Start reading */
read_data[7] = FTFE->FCCOB4;
read_data[6] = FTFE->FCCOB5;
read_data[5] = FTFE->FCCOB6;
read_data[4] = FTFE->FCCOB7;
read_data[3] = FTFE->FCCOB8;
read_data[2] = FTFE->FCCOB9;
read_data[1] = FTFE->FCCOBA;
read_data[0] = FTFE->FCCOBB;
packed_data = 0;
for (i = 0; i < 8; i++)
{
temp_64 = read_data[i];
packed_data |= temp_64 << (i * 8);
}
return packed_data;
}
#endif /* RADIO_IS_GEN_2P0 */
#endif /* RADIO_IS_GEN_3P0 */
/*! *********************************************************************************
* \brief Store a SW trim value in the table passed in from calling function.
*
* \param sw_trim_tbl pointer to the software trim table to hold SW trim values
* \param num_entries the number of entries in the SW trim table
* \param addr the software trim ID
* \param data the value of the software trim
*
***********************************************************************************/
static void store_sw_trim(IFR_SW_TRIM_TBL_ENTRY_T * sw_trim_tbl, uint16_t num_entries, uint32_t addr, uint32_t data)
{
uint16_t i;
if (sw_trim_tbl != NULL)
{
for (i = 0; i < num_entries; i++)
{
if (addr == sw_trim_tbl[i].trim_id)
{
sw_trim_tbl[i].trim_value = data;
sw_trim_tbl[i].valid = 1;
break; /* Don't need to scan the array any further... */
}
}
}
}
/*! *********************************************************************************
* \brief Process block 1 IFR data.
*
* \param sw_trim_tbl pointer to the software trim table to hold SW trim values
* \param num_entries the number of entries in the SW trim table
*
* \remarks
* Uses a IFR v2 formatted default array if the IFR is blank or corrupted.
* Stores SW trim values to an array passed into this function.
*
***********************************************************************************/
void handle_ifr(IFR_SW_TRIM_TBL_ENTRY_T * sw_trim_tbl, uint16_t num_entries)
{
uint32_t dest_addr;
uint32_t read_addr;
uint32_t dest_data;
uint32_t packed_data;
const uint32_t *ifr_ptr;
#if RADIO_IS_GEN_3P0
num_words_avail = 0; /* Prep for handling 64 bit words from flash */
#endif /* RADIO_IS_GEN_3P0 */
#if RADIO_IS_GEN_3P0
read_addr = K3_BASE_INDEX;
#else
#ifdef CPU_MODEL_MKW41Z256VHT4
read_addr = KW4x_256_BASE;
#else
read_addr = KW4x_512_BASE;
#endif /* CPU_MODEL_MKW41Z256VHT4 */
#endif /* RADIO_IS_GEN_3P0 */
/* Read first entry in IFR table */
packed_data = read_first_ifr_word(read_addr);
if ((packed_data&~IFR_VERSION_MASK) == IFR_VERSION_HDR)
{
/* Valid header was found, process real IFR data */
XCVR_MISC->OVERWRITE_VER = (packed_data & IFR_VERSION_MASK);
store_sw_trim(sw_trim_tbl, num_entries, 0xABCD, (packed_data & IFR_VERSION_MASK)); /* Place IFR version # in SW trim array*/
packed_data = read_another_ifr_word();
while (packed_data !=IFR_EOF_SYMBOL)
{
if (IS_A_SW_ID(packed_data)) /* SW Trim case (non_reg writes) */
{
dest_addr = packed_data;
packed_data = read_another_ifr_word();
dest_data = packed_data;
/* Place SW trim in array for driver SW to use */
store_sw_trim(sw_trim_tbl, num_entries, dest_addr, dest_data);
}
else
{
if (IS_VALID_REG_ADDR(packed_data)) /* Valid register write address */
{
dest_addr = packed_data;
packed_data = read_another_ifr_word();
dest_data = packed_data;
*(uint32_t *)(dest_addr) = dest_data;
}
else
{ /* Invalid address case */
}
}
packed_data=read_another_ifr_word();
}
}
else
{
/* Valid header is not present, use blind IFR trim table */
ifr_ptr = BLOCK_1_IFR;
packed_data = *ifr_ptr;
XCVR_MISC->OVERWRITE_VER = (packed_data & IFR_VERSION_MASK);
store_sw_trim(sw_trim_tbl, num_entries, 0xABCD, (packed_data & IFR_VERSION_MASK)); /* Place IFR version # in SW trim array */
ifr_ptr++;
packed_data= *ifr_ptr;
while (packed_data != IFR_EOF_SYMBOL)
{
if (IS_A_SW_ID(packed_data))
{
/* SW Trim case (non_reg writes) */
dest_addr = packed_data;
ifr_ptr++;
packed_data = *(ifr_ptr);
dest_data = packed_data;
/* Place SW trim in array for driver SW to use */
store_sw_trim(sw_trim_tbl, num_entries, dest_addr, dest_data);
}
else
{
dest_addr = packed_data;
ifr_ptr++;
packed_data = *ifr_ptr;
dest_data = packed_data;
/* Valid register write address */
if (IS_VALID_REG_ADDR(dest_addr))
{
*(uint32_t *)(dest_addr) = dest_data;
}
else
{
/* Invalid address case */
}
}
ifr_ptr++;
packed_data= *ifr_ptr;
}
}
}
#if RADIO_IS_GEN_3P0
#else
uint32_t handle_ifr_die_id(void)
{
uint32_t id_x, id_y;
uint32_t id;
id = read_resource_ifr(0x90);
id_x = id & 0x00FF0000;
id_y = id & 0x000000FF;
return (id_x | id_y);
}
uint32_t handle_ifr_die_kw_type(void)
{
uint32_t zb, ble;
zb = read_resource_ifr(0x80) & 0x8000;
ble= read_resource_ifr(0x88) & 0x100000;
return (zb | ble);
}
#endif /* RADIO_IS_GEN_3P0 */
/*! *********************************************************************************
* \brief Dumps block 1 IFR data to an array.
*
* \param dump_tbl pointer to the table to hold the dumped IFR values
* \param num_entries the number of entries to dump
*
* \remarks
* Starts at the first address in IFR and dumps sequential entries.
*
***********************************************************************************/
void dump_ifr(uint32_t * dump_tbl, uint8_t num_entries)
{
#if RADIO_IS_GEN_3P0
uint32_t ifr_address = 0x20000;
#else
uint32_t ifr_address = 0x20000;
#endif /* RADIO_IS_GEN_3P0 */
uint32_t * dump_ptr = dump_tbl;
uint8_t i;
*dump_ptr = read_first_ifr_word(ifr_address);
dump_ptr++;
for (i = 0; i < num_entries - 1; i++)
{
*dump_ptr = read_another_ifr_word();
dump_ptr++;
}
}

View File

@ -0,0 +1,193 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __IFR_RADIO_H__
/* clang-format off */
#define __IFR_RADIO_H__
/* clang-format on */
#include <stdint.h>
#include "fsl_xcvr.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @addtogroup xcvr
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
#define IFR_EOF_SYMBOL (0xFEED0E0FU) /* < Denotes the "End of File" for IFR data */
#define IFR_VERSION_HDR (0xABCD0000U) /* < Constant value for upper 16 bits of IFR data header */
#define IFR_VERSION_MASK (0x0000FFFFU) /* < Mask for version number (lower 16 bits) of IFR data header */
#define IFR_SW_ID_MIN (0x00000000U) /* < Lower limit of SW trim IDs */
#define IFR_SW_ID_MAX (0x0000FFFFU) /* < Lower limit of SW trim IDs */
#define IS_A_SW_ID(x) ((IFR_SW_ID_MIN < (x)) && (IFR_SW_ID_MAX >= (x)))
/* K3 valid registers support */
#if (defined(CPU_MODEL_K32W042S1M2CAx_M0P) || defined(CPU_MODEL_K32W042S1M2VPJ_M0P))
#define IS_VALID_REG_ADDR(x) (((x) & 0xFFFF0000U) == 0x41000000U) /* Valid addresses are 0x410xxxxx */
#endif /* (defined(CPU_MODEL_K32W042S1M2CAx_M0P) || defined(CPU_MODEL_K32W042S1M2VPJ_M0P)) */
/* KW41 and KW35/36 valid registers support */
#if (defined(CPU_MODEL_MKW41Z256VHT4) || defined(CPU_MODEL_MKW41Z512VHT4) || \
defined(CPU_MODEL_MKW31Z256VHT4) || defined(CPU_MODEL_MKW31Z512VHT4) || \
defined(CPU_MODEL_MKW21Z256VHT4) || defined(CPU_MODEL_MKW21Z512VHT4) || \
defined(CPU_MODEL_MKW35A512VFP4) || defined(CPU_MODEL_MKW36A512VFP4) )
#define IS_VALID_REG_ADDR(x) (((x) & 0xFFFF0000U) == 0x40050000U) /* Valid addresses are 0x4005xxxx */
#endif
#define MAKE_MASK(size) ((1 << (size)) - 1)
#define MAKE_MASKSHFT(size, bitpos) (MAKE_MASK(size) << (bitpos))
#define IFR_TZA_CAP_TUNE_MASK (0x0000000FU)
#define IFR_TZA_CAP_TUNE_SHIFT (0)
#define IFR_BBF_CAP_TUNE_MASK (0x000F0000U)
#define IFR_BBF_CAP_TUNE_SHIFT (16)
#define IFR_RES_TUNE2_MASK (0x00F00000U)
#define IFR_RES_TUNE2_SHIFT (20)
/* \var typedef uint8_t IFR_ERROR_T */
/* \brief The IFR error reporting type. */
/* See #IFR_ERROR_T_enum for the enumeration definitions. */
typedef uint8_t IFR_ERROR_T;
/* \brief The enumerations used to describe IFR errors. */
enum IFR_ERROR_T_enum
{
IFR_SUCCESS = 0,
INVALID_POINTER = 1, /* < NULL pointer error */
INVALID_DEST_SIZE_SHIFT = 2, /* < the bits won't fit as specified in the destination */
};
/* \var typedef uint16_t SW_TRIM_ID_T */
/* \brief The SW trim ID type. */
/* See #SW_TRIM_ID_T_enum for the enumeration definitions. */
typedef uint16_t SW_TRIM_ID_T;
/* \brief The enumerations used to define SW trim IDs. */
enum SW_TRIM_ID_T_enum
{
Q_RELATIVE_GAIN_BY_PART = 0, /* < Q vs I relative gain trim ID */
ADC_GAIN = 1, /* < ADC gain trim ID */
ZB_FILT_TRIM = 2, /* < Baseband Bandwidth filter trim ID for BLE */
BLE_FILT_TRIM = 3, /* < Baseband Bandwidth filter trim ID for BLE */
TRIM_STATUS = 4, /* < Status result of the trim process (error indications) */
TRIM_VERSION = 0xABCD, /* < Version number of the IFR trim algorithm/format. */
};
/* \var typedef uint32_t IFR_TRIM_STATUS_T */
/* \brief The definition of failure bits stored in IFR trim status word. */
/* See #IFR_TRIM_STATUS_T_enum for the enumeration definitions. */
typedef uint32_t IFR_TRIM_STATUS_T;
/* \brief The enumerations used to describe trim algorithm failures in the status entry in IFR. */
/* This enum represents multiple values which can be OR'd together in a single status word. */
enum IFR_TRIM_STATUS_T_enum
{
TRIM_ALGORITHM_SUCCESS = 0,
BGAP_VOLTAGE_TRIM_FAILED = 1, /* < algorithm failure in BGAP voltagetrim */
IQMC_GAIN_ADJ_FAILED = 2, /* < algorithm failure in IQMC gain trim */
IQMC_PHASE_ADJ_FAILED = 4, /* < algorithm failure in IQMC phase trim */
IQMC_DC_GAIN_ADJ_FAILED = 8, /* < IQMC DC gain trim failure */
ADC_GAIN_TRIM_FAILED = 10, /* < Trim failure for ADC Gain Trim */
ZB_FILT_TRIM_FAILED = 20, /* < Filter trim failure for 802.15.4 */
BLE_FILT_TRIM_FAILED = 40, /* < Filter trim failure for BLE */
};
/* \var typedef struct IFR_SW_TRIM_TBL_ENTRY_T */
/* \brief Structure defining an entry in a table used to contain values to be passed back from IFR */
/* handling routine to XCVR driver software. */
typedef struct
{
SW_TRIM_ID_T trim_id; /* < The assigned ID */
uint32_t trim_value; /* < The value fetched from IFR.*/
uint8_t valid; /* < validity of the trim_value field after IFR processing is complete (TRUE/FALSE).*/
} IFR_SW_TRIM_TBL_ENTRY_T;
/*******************************************************************************
* API
******************************************************************************/
/*!
* @brief Main IFR handler function called by XCVR driver software to process trim table.
*
* This function handles reading data from IFR and either loading to registers or storing to a SW trim values table.
*
* @param sw_trim_tbl pointer to the table used to store software trim values.
* @param num_entries the number of entries that can be stored in the SW trim table.
*/
void handle_ifr(IFR_SW_TRIM_TBL_ENTRY_T * sw_trim_tbl, uint16_t num_entries);
/*!
* @brief Handler function to read die_id from IFR locations..
*
* This function handles reading die ID value for debug and testing usage.
*
* @return the value of the die ID field.
*/
uint32_t handle_ifr_die_id(void);
/*!
* @brief Handler function to read KW chip version from IFR locations..
*
* This function handles reading KW chip version for debug and testing usage.
*
* @return the value of the KW version field.
*/
uint32_t handle_ifr_die_kw_type(void);
/*!
* @brief Debug function to dump the IFR contents to a RAM array.
*
* This function handles reading data from IFR and storing to a RAM array for debug.
*
* @param dump_tbl pointer to the table used to store IFR entry values.
* @param num_entries the number of entries that can be stored in the dump table.
*/
void dump_ifr(uint32_t * dump_tbl, uint8_t num_entries);
#ifdef __cplusplus
}
#endif
#endif /*__IFR_RADIO_H__ */

View File

@ -38,7 +38,8 @@ BOARD_PROVIDES_NETIF := acd52832 airfy-beacon atmega256rfr2-xpro avr-rss2 b-l072
derfmega128 derfmega256 hamilton iotlab-m3 iotlab-a8-m3 lobaro-lorabox lsn50 mulle microbit msba2 \
microduino-corerf native nrf51dk nrf51dongle nrf52dk nrf52840dk nrf52840-mdk nrf6310 \
nucleo-f207zg nucleo-f767zi openmote-b openmote-cc2538 pba-d-01-kw2x remote-pa \
remote-reva ruuvitag samr21-xpro samr30-xpro spark-core telosb thingy52 yunjia-nrf51822 z1
remote-reva ruuvitag samr21-xpro samr30-xpro spark-core telosb thingy52 yunjia-nrf51822 z1 \
frdm-kw41z phynode-kw41z usb-kw41z openlabs-kw41z-mini openlabs-kw41z-mini-256kib
ifneq (,$(filter $(BOARD),$(BOARD_PROVIDES_NETIF)))
# Use modules for networking

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2017 SKF AB
*
* 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 sys_auto_init_gnrc_netif
* @{
*
* @file
* @brief Auto initialization for kw41zrf network interfaces
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @author Thomas Stilwell <stilwellt@openlabs.co>
*/
#ifdef MODULE_KW41ZRF
#include "log.h"
#include "board.h"
#include "net/gnrc.h"
#include "net/gnrc/netif/ieee802154.h"
#ifdef MODULE_GNRC_LWMAC
#include "net/gnrc/lwmac/lwmac.h"
#endif
#ifdef MODULE_GNRC_GOMACH
#include "net/gnrc/gomach/gomach.h"
#endif
#include "kw41zrf.h"
/**
* @name Stack parameters for the MAC layer thread
* @{
*/
#ifndef KW41ZRF_NETIF_STACKSIZE
#define KW41ZRF_NETIF_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#endif
#ifndef KW41ZRF_NETIF_PRIO
#define KW41ZRF_NETIF_PRIO (GNRC_NETIF_PRIO)
#endif
/** @} */
/* There is only one memory mapped transceiver in the supported SoCs, the driver
* does not try to take into account multiple instances of the hardware module */
#define KW41ZRF_NUMOF 1
static kw41zrf_t kw41zrf_devs[KW41ZRF_NUMOF];
static char _kw41zrf_stacks[KW41ZRF_NUMOF][KW41ZRF_NETIF_STACKSIZE];
void auto_init_kw41zrf(void)
{
for (unsigned i = 0; i < KW41ZRF_NUMOF; i++) {
LOG_DEBUG("[auto_init_netif] initializing kw41zrf #%u\n", i);
kw41zrf_setup(&kw41zrf_devs[i]);
#if defined(MODULE_GNRC_GOMACH)
gnrc_netif_gomach_create(_kw41zrf_stacks[i], KW41ZRF_NETIF_STACKSIZE,
KW41ZRF_NETIF_PRIO, "kw41zrf-gomach",
(netdev_t *)&kw41zrf_devs[i]);
#elif defined(MODULE_GNRC_LWMAC)
gnrc_netif_lwmac_create(_kw41zrf_stacks[i], KW41ZRF_NETIF_STACKSIZE,
KW41ZRF_NETIF_PRIO, "kw41zrf-lwmac",
(netdev_t *)&kw41zrf_devs[i]);
#else
gnrc_netif_ieee802154_create(_kw41zrf_stacks[i], KW41ZRF_NETIF_STACKSIZE,
KW41ZRF_NETIF_PRIO, "kw41zrf",
(netdev_t *)&kw41zrf_devs[i]);
#endif
}
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_KW41ZRF */
/** @} */

View File

@ -109,6 +109,11 @@ void gnrc_netif_init_devs(void)
auto_init_kw2xrf();
}
if (IS_USED(MODULE_KW41ZRF)) {
extern void auto_init_kw41zrf(void);
auto_init_kw41zrf();
}
if (IS_USED(MODULE_USBUS_CDC_ECM)) {
extern void auto_init_netdev_cdcecm(void);
auto_init_netdev_cdcecm();