Igor Stepura / kw41z-rf-driver Featured

ARM mbed Nanostack RF driver for NXP KW41Z 802.15.4 wireless MCU

This driver is used with 6LoWPAN stack.

Code far from being stable yet, but basic functionality seems to be working. Two FRDM-KW41Z boards running code build from mbed-os-example-mesh-minimal and nanostack-border-router are able to build mesh.

Main repository is at https://github.com/istepura/kw41z-rf-driver

Committer:
igor Stepura
Date:
Thu Jul 20 13:06:20 2017 -0400
Revision:
0:bb6687c3a462
Child:
1:4e0ed8184753
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igor Stepura 0:bb6687c3a462 1 #include "NanostackRfPhyKw41z.h"
igor Stepura 0:bb6687c3a462 2 #include "ns_types.h"
igor Stepura 0:bb6687c3a462 3 #include "platform/arm_hal_interrupt.h"
igor Stepura 0:bb6687c3a462 4 #include "nanostack/platform/arm_hal_phy.h"
igor Stepura 0:bb6687c3a462 5 #include <string.h>
igor Stepura 0:bb6687c3a462 6 #include "rtos.h"
igor Stepura 0:bb6687c3a462 7 #include "fsl_xcvr.h"
igor Stepura 0:bb6687c3a462 8 #include "PhyTypes.h"
igor Stepura 0:bb6687c3a462 9
igor Stepura 0:bb6687c3a462 10 /* PHY states */
igor Stepura 0:bb6687c3a462 11 typedef enum {
igor Stepura 0:bb6687c3a462 12 gIdle_c,
igor Stepura 0:bb6687c3a462 13 gRX_c,
igor Stepura 0:bb6687c3a462 14 gTX_c,
igor Stepura 0:bb6687c3a462 15 gCCA_c,
igor Stepura 0:bb6687c3a462 16 gTR_c,
igor Stepura 0:bb6687c3a462 17 gCCCA_c,
igor Stepura 0:bb6687c3a462 18 }phySeqState_t;
igor Stepura 0:bb6687c3a462 19
igor Stepura 0:bb6687c3a462 20 typedef enum{
igor Stepura 0:bb6687c3a462 21 gPhyPwrIdle_c,
igor Stepura 0:bb6687c3a462 22 gPhyPwrAutodoze_c,
igor Stepura 0:bb6687c3a462 23 gPhyPwrDoze_c,
igor Stepura 0:bb6687c3a462 24 gPhyPwrHibernate_c,
igor Stepura 0:bb6687c3a462 25 gPhyPwrDSM_c,
igor Stepura 0:bb6687c3a462 26 gPhyPwrReset_c
igor Stepura 0:bb6687c3a462 27 }phyPwrMode_t;
igor Stepura 0:bb6687c3a462 28
igor Stepura 0:bb6687c3a462 29 /* PHY channel state */
igor Stepura 0:bb6687c3a462 30 enum {
igor Stepura 0:bb6687c3a462 31 gChannelIdle_c,
igor Stepura 0:bb6687c3a462 32 gChannelBusy_c
igor Stepura 0:bb6687c3a462 33 };
igor Stepura 0:bb6687c3a462 34
igor Stepura 0:bb6687c3a462 35 /* PANCORDNTR bit in PP */
igor Stepura 0:bb6687c3a462 36 enum {
igor Stepura 0:bb6687c3a462 37 gMacRole_DeviceOrCoord_c,
igor Stepura 0:bb6687c3a462 38 gMacRole_PanCoord_c
igor Stepura 0:bb6687c3a462 39 };
igor Stepura 0:bb6687c3a462 40
igor Stepura 0:bb6687c3a462 41 /* Cca types */
igor Stepura 0:bb6687c3a462 42 enum {
igor Stepura 0:bb6687c3a462 43 gCcaED_c, /* energy detect - CCA bit not active, not to be used for T and CCCA sequences */
igor Stepura 0:bb6687c3a462 44 gCcaCCA_MODE1_c, /* energy detect - CCA bit ACTIVE */
igor Stepura 0:bb6687c3a462 45 gCcaCCA_MODE2_c, /* 802.15.4 compliant signal detect - CCA bit ACTIVE */
igor Stepura 0:bb6687c3a462 46 gCcaCCA_MODE3_c, /* 802.15.4 compliant signal detect and energy detect - CCA bit ACTIVE */
igor Stepura 0:bb6687c3a462 47 gInvalidCcaType_c /* illegal type */
igor Stepura 0:bb6687c3a462 48 };
igor Stepura 0:bb6687c3a462 49
igor Stepura 0:bb6687c3a462 50 enum {
igor Stepura 0:bb6687c3a462 51 gNormalCca_c,
igor Stepura 0:bb6687c3a462 52 gContinuousCca_c
igor Stepura 0:bb6687c3a462 53 };
igor Stepura 0:bb6687c3a462 54 static phyPwrMode_t mPhyPwrState = gPhyPwrIdle_c;
igor Stepura 0:bb6687c3a462 55 static uint8_t MAC_address[8] = {1, 2, 3, 4, 5, 6, 7, 8};
igor Stepura 0:bb6687c3a462 56 static NanostackRfPhyKw41z *rf = NULL;
igor Stepura 0:bb6687c3a462 57 static Thread irq_thread(osPriorityRealtime, 1024);
igor Stepura 0:bb6687c3a462 58 static phy_device_driver_s device_driver;
igor Stepura 0:bb6687c3a462 59 static int8_t rf_radio_driver_id = -1;
igor Stepura 0:bb6687c3a462 60 static uint8_t mac_tx_handle = 0;
igor Stepura 0:bb6687c3a462 61
igor Stepura 0:bb6687c3a462 62 static uint8_t mPhyIrqDisableCnt = 1;
igor Stepura 0:bb6687c3a462 63 static uint8_t rf_phy_channel = 0;
igor Stepura 0:bb6687c3a462 64 static uint8_t need_ack = 0;
igor Stepura 0:bb6687c3a462 65
igor Stepura 0:bb6687c3a462 66 #define RF_BUFFER_SIZE 128
igor Stepura 0:bb6687c3a462 67 /*RF receive buffer*/
igor Stepura 0:bb6687c3a462 68 static uint8_t rf_buffer[RF_BUFFER_SIZE];
igor Stepura 0:bb6687c3a462 69
igor Stepura 0:bb6687c3a462 70 /* Channel configurations for 2.4 */
igor Stepura 0:bb6687c3a462 71 static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
igor Stepura 0:bb6687c3a462 72
igor Stepura 0:bb6687c3a462 73 static const phy_device_channel_page_s phy_channel_pages[] = {
igor Stepura 0:bb6687c3a462 74 { CHANNEL_PAGE_0, &phy_24ghz},
igor Stepura 0:bb6687c3a462 75 { CHANNEL_PAGE_0, NULL}
igor Stepura 0:bb6687c3a462 76 };
igor Stepura 0:bb6687c3a462 77 /* Set the default power level to 0dBm */
igor Stepura 0:bb6687c3a462 78 #ifndef gPhyDefaultTxPowerLevel_d
igor Stepura 0:bb6687c3a462 79 #define gPhyDefaultTxPowerLevel_d (22)
igor Stepura 0:bb6687c3a462 80 #endif
igor Stepura 0:bb6687c3a462 81 #define CORE_CLOCK_FREQ 47972352U
igor Stepura 0:bb6687c3a462 82 #define gPhyMaxTxPowerLevel_d (32)
igor Stepura 0:bb6687c3a462 83 uint8_t gPhyChannelTxPowerLimits[] = { gPhyMaxTxPowerLevel_d, /* 11 */ \
igor Stepura 0:bb6687c3a462 84 gPhyMaxTxPowerLevel_d, /* 12 */ \
igor Stepura 0:bb6687c3a462 85 gPhyMaxTxPowerLevel_d, /* 13 */ \
igor Stepura 0:bb6687c3a462 86 gPhyMaxTxPowerLevel_d, /* 14 */ \
igor Stepura 0:bb6687c3a462 87 gPhyMaxTxPowerLevel_d, /* 15 */ \
igor Stepura 0:bb6687c3a462 88 gPhyMaxTxPowerLevel_d, /* 16 */ \
igor Stepura 0:bb6687c3a462 89 gPhyMaxTxPowerLevel_d, /* 17 */ \
igor Stepura 0:bb6687c3a462 90 gPhyMaxTxPowerLevel_d, /* 18 */ \
igor Stepura 0:bb6687c3a462 91 gPhyMaxTxPowerLevel_d, /* 19 */ \
igor Stepura 0:bb6687c3a462 92 gPhyMaxTxPowerLevel_d, /* 20 */ \
igor Stepura 0:bb6687c3a462 93 gPhyMaxTxPowerLevel_d, /* 21 */ \
igor Stepura 0:bb6687c3a462 94 gPhyMaxTxPowerLevel_d, /* 22 */ \
igor Stepura 0:bb6687c3a462 95 gPhyMaxTxPowerLevel_d, /* 23 */ \
igor Stepura 0:bb6687c3a462 96 gPhyMaxTxPowerLevel_d, /* 24 */ \
igor Stepura 0:bb6687c3a462 97 gPhyMaxTxPowerLevel_d, /* 25 */ \
igor Stepura 0:bb6687c3a462 98 gPhyMaxTxPowerLevel_d }; /* 26 */
igor Stepura 0:bb6687c3a462 99
igor Stepura 0:bb6687c3a462 100
igor Stepura 0:bb6687c3a462 101
igor Stepura 0:bb6687c3a462 102 MBED_UNUSED static void rf_init(void);
igor Stepura 0:bb6687c3a462 103 MBED_UNUSED static int8_t rf_device_register(void);
igor Stepura 0:bb6687c3a462 104 MBED_UNUSED static void rf_device_unregister(void);
igor Stepura 0:bb6687c3a462 105 MBED_UNUSED static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
igor Stepura 0:bb6687c3a462 106 MBED_UNUSED static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr);
igor Stepura 0:bb6687c3a462 107 MBED_UNUSED static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr);
igor Stepura 0:bb6687c3a462 108 MBED_UNUSED static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol );
igor Stepura 0:bb6687c3a462 109 MBED_UNUSED static void rf_abort(void);
igor Stepura 0:bb6687c3a462 110 MBED_UNUSED static void rf_promiscuous(uint8_t mode);
igor Stepura 0:bb6687c3a462 111 MBED_UNUSED static void rf_receive(void);
igor Stepura 0:bb6687c3a462 112 MBED_UNUSED static void rf_mac64_read(uint8_t *address);
igor Stepura 0:bb6687c3a462 113 MBED_UNUSED static void rf_set_power_state(phyPwrMode_t newState);
igor Stepura 0:bb6687c3a462 114 MBED_UNUSED static void rf_handle_tx_end(uint8_t);
igor Stepura 0:bb6687c3a462 115 static void rf_set_address(uint8_t *address);
igor Stepura 0:bb6687c3a462 116 static inline phySeqState_t rf_get_state(void)
igor Stepura 0:bb6687c3a462 117 {
igor Stepura 0:bb6687c3a462 118 return (phySeqState_t)(((ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) >> ZLL_PHY_CTRL_XCVSEQ_SHIFT));
igor Stepura 0:bb6687c3a462 119 }
igor Stepura 0:bb6687c3a462 120
igor Stepura 0:bb6687c3a462 121
igor Stepura 0:bb6687c3a462 122 static void PHY_InterruptHandler(void);
igor Stepura 0:bb6687c3a462 123 static void PHY_InterruptThread(void);
igor Stepura 0:bb6687c3a462 124 static void handle_interrupt(uint32_t irqStatus);
igor Stepura 0:bb6687c3a462 125
igor Stepura 0:bb6687c3a462 126 static void rf_if_lock(void)
igor Stepura 0:bb6687c3a462 127 {
igor Stepura 0:bb6687c3a462 128 platform_enter_critical();
igor Stepura 0:bb6687c3a462 129 }
igor Stepura 0:bb6687c3a462 130
igor Stepura 0:bb6687c3a462 131 static void rf_if_unlock(void)
igor Stepura 0:bb6687c3a462 132 {
igor Stepura 0:bb6687c3a462 133 platform_exit_critical();
igor Stepura 0:bb6687c3a462 134 }
igor Stepura 0:bb6687c3a462 135
igor Stepura 0:bb6687c3a462 136 static phyStatus_t PhyPlmeSetPwrLevelRequest
igor Stepura 0:bb6687c3a462 137 (
igor Stepura 0:bb6687c3a462 138 uint8_t pwrStep
igor Stepura 0:bb6687c3a462 139 )
igor Stepura 0:bb6687c3a462 140 {
igor Stepura 0:bb6687c3a462 141 phyStatus_t status = gPhySuccess_c;
igor Stepura 0:bb6687c3a462 142 #ifdef PHY_PARAMETERS_VALIDATION
igor Stepura 0:bb6687c3a462 143 if( pwrStep > 32 )
igor Stepura 0:bb6687c3a462 144 {
igor Stepura 0:bb6687c3a462 145 status = gPhyInvalidParameter_c;
igor Stepura 0:bb6687c3a462 146 }
igor Stepura 0:bb6687c3a462 147 else
igor Stepura 0:bb6687c3a462 148 #endif /* PHY_PARAMETERS_VALIDATION */
igor Stepura 0:bb6687c3a462 149 {
igor Stepura 0:bb6687c3a462 150 /* Do not exceed the Tx power limit for the current channel */
igor Stepura 0:bb6687c3a462 151 if( pwrStep > gPhyChannelTxPowerLimits[ZLL->CHANNEL_NUM0 - 11] )
igor Stepura 0:bb6687c3a462 152 {
igor Stepura 0:bb6687c3a462 153 pwrStep = gPhyChannelTxPowerLimits[ZLL->CHANNEL_NUM0 - 11];
igor Stepura 0:bb6687c3a462 154 }
igor Stepura 0:bb6687c3a462 155 if( pwrStep > 2 )
igor Stepura 0:bb6687c3a462 156 {
igor Stepura 0:bb6687c3a462 157 pwrStep = (pwrStep << 1) - 2;
igor Stepura 0:bb6687c3a462 158 }
igor Stepura 0:bb6687c3a462 159
igor Stepura 0:bb6687c3a462 160 ZLL->PA_PWR = pwrStep;
igor Stepura 0:bb6687c3a462 161 }
igor Stepura 0:bb6687c3a462 162 return status;
igor Stepura 0:bb6687c3a462 163 }
igor Stepura 0:bb6687c3a462 164
igor Stepura 0:bb6687c3a462 165 static uint8_t PhyPlmeGetPwrLevelRequest(void)
igor Stepura 0:bb6687c3a462 166 {
igor Stepura 0:bb6687c3a462 167 uint8_t pwrStep = (uint8_t)ZLL->PA_PWR;
igor Stepura 0:bb6687c3a462 168
igor Stepura 0:bb6687c3a462 169 if( pwrStep > 2 )
igor Stepura 0:bb6687c3a462 170 {
igor Stepura 0:bb6687c3a462 171 pwrStep = (pwrStep + 2) >> 1;
igor Stepura 0:bb6687c3a462 172 }
igor Stepura 0:bb6687c3a462 173
igor Stepura 0:bb6687c3a462 174 return pwrStep;
igor Stepura 0:bb6687c3a462 175 }
igor Stepura 0:bb6687c3a462 176
igor Stepura 0:bb6687c3a462 177 static phyStatus_t PhyPlmeSetCurrentChannelRequest
igor Stepura 0:bb6687c3a462 178 (
igor Stepura 0:bb6687c3a462 179 uint8_t channel,
igor Stepura 0:bb6687c3a462 180 uint8_t pan
igor Stepura 0:bb6687c3a462 181 )
igor Stepura 0:bb6687c3a462 182 {
igor Stepura 0:bb6687c3a462 183 phyStatus_t status = gPhySuccess_c;
igor Stepura 0:bb6687c3a462 184 #ifdef PHY_PARAMETERS_VALIDATION
igor Stepura 0:bb6687c3a462 185 if((channel < 11) || (channel > 26))
igor Stepura 0:bb6687c3a462 186 {
igor Stepura 0:bb6687c3a462 187 status = gPhyInvalidParameter_c;
igor Stepura 0:bb6687c3a462 188 }
igor Stepura 0:bb6687c3a462 189 else
igor Stepura 0:bb6687c3a462 190 #endif /* PHY_PARAMETERS_VALIDATION */
igor Stepura 0:bb6687c3a462 191 {
igor Stepura 0:bb6687c3a462 192 if( !pan )
igor Stepura 0:bb6687c3a462 193 {
igor Stepura 0:bb6687c3a462 194 ZLL->CHANNEL_NUM0 = channel;
igor Stepura 0:bb6687c3a462 195 }
igor Stepura 0:bb6687c3a462 196 else
igor Stepura 0:bb6687c3a462 197 {
igor Stepura 0:bb6687c3a462 198 ZLL->CHANNEL_NUM1 = channel;
igor Stepura 0:bb6687c3a462 199 }
igor Stepura 0:bb6687c3a462 200
igor Stepura 0:bb6687c3a462 201 /* Make sure the current Tx power doesn't exceed the Tx power limit for the new channel */
igor Stepura 0:bb6687c3a462 202 if( PhyPlmeGetPwrLevelRequest() > gPhyChannelTxPowerLimits[channel - 11] )
igor Stepura 0:bb6687c3a462 203 {
igor Stepura 0:bb6687c3a462 204 PhyPlmeSetPwrLevelRequest(gPhyChannelTxPowerLimits[channel - 11]);
igor Stepura 0:bb6687c3a462 205 }
igor Stepura 0:bb6687c3a462 206 }
igor Stepura 0:bb6687c3a462 207
igor Stepura 0:bb6687c3a462 208 return status;
igor Stepura 0:bb6687c3a462 209 }
igor Stepura 0:bb6687c3a462 210 static void UnprotectFromXcvrInterrupt(void)
igor Stepura 0:bb6687c3a462 211 {
igor Stepura 0:bb6687c3a462 212 platform_enter_critical();
igor Stepura 0:bb6687c3a462 213
igor Stepura 0:bb6687c3a462 214 if( mPhyIrqDisableCnt )
igor Stepura 0:bb6687c3a462 215 {
igor Stepura 0:bb6687c3a462 216 mPhyIrqDisableCnt--;
igor Stepura 0:bb6687c3a462 217
igor Stepura 0:bb6687c3a462 218 if( mPhyIrqDisableCnt == 0 )
igor Stepura 0:bb6687c3a462 219 {
igor Stepura 0:bb6687c3a462 220 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TRCV_MSK_MASK;
igor Stepura 0:bb6687c3a462 221 }
igor Stepura 0:bb6687c3a462 222 }
igor Stepura 0:bb6687c3a462 223
igor Stepura 0:bb6687c3a462 224 platform_exit_critical();
igor Stepura 0:bb6687c3a462 225 }
igor Stepura 0:bb6687c3a462 226 #ifndef gPhyIrqPriority_c
igor Stepura 0:bb6687c3a462 227 #define gPhyIrqPriority_c (0x80)
igor Stepura 0:bb6687c3a462 228 #endif
igor Stepura 0:bb6687c3a462 229 #define gPhyIrqNo_d (Radio_1_IRQn)
igor Stepura 0:bb6687c3a462 230 static void PHY_InstallIsr()
igor Stepura 0:bb6687c3a462 231 {
igor Stepura 0:bb6687c3a462 232 NVIC_SetVector(gPhyIrqNo_d, (uint32_t)&PHY_InterruptHandler);
igor Stepura 0:bb6687c3a462 233 NVIC_ClearPendingIRQ(gPhyIrqNo_d);
igor Stepura 0:bb6687c3a462 234 NVIC_EnableIRQ(gPhyIrqNo_d);
igor Stepura 0:bb6687c3a462 235 /* set transceiver interrupt priority */
igor Stepura 0:bb6687c3a462 236 //NVIC_SetPriority(gPhyIrqNo_d, gPhyIrqPriority_c >> (8 - __NVIC_PRIO_BITS));
igor Stepura 0:bb6687c3a462 237 UnprotectFromXcvrInterrupt();
igor Stepura 0:bb6687c3a462 238 }
igor Stepura 0:bb6687c3a462 239
igor Stepura 0:bb6687c3a462 240 static void rf_channel_set(uint8_t channel)
igor Stepura 0:bb6687c3a462 241 {
igor Stepura 0:bb6687c3a462 242 rf_phy_channel = channel;
igor Stepura 0:bb6687c3a462 243 PhyPlmeSetCurrentChannelRequest(channel, 0);
igor Stepura 0:bb6687c3a462 244 }
igor Stepura 0:bb6687c3a462 245
igor Stepura 0:bb6687c3a462 246 static void rf_init(void)
igor Stepura 0:bb6687c3a462 247 {
igor Stepura 0:bb6687c3a462 248 uint32_t phyReg;
igor Stepura 0:bb6687c3a462 249 XCVR_Init( ZIGBEE_MODE, DR_500KBPS );
igor Stepura 0:bb6687c3a462 250
igor Stepura 0:bb6687c3a462 251 XCVR_SetXtalTrim(0x30);
igor Stepura 0:bb6687c3a462 252
igor Stepura 0:bb6687c3a462 253 /* Enable 16 bit mode for TC2 - TC2 prime EN, disable all timers,
igor Stepura 0:bb6687c3a462 254 enable AUTOACK, mask all interrupts */
igor Stepura 0:bb6687c3a462 255 ZLL->PHY_CTRL = (gCcaCCA_MODE1_c << ZLL_PHY_CTRL_CCATYPE_SHIFT) |
igor Stepura 0:bb6687c3a462 256 ZLL_PHY_CTRL_TC2PRIME_EN_MASK |
igor Stepura 0:bb6687c3a462 257 ZLL_PHY_CTRL_TSM_MSK_MASK |
igor Stepura 0:bb6687c3a462 258 ZLL_PHY_CTRL_WAKE_MSK_MASK |
igor Stepura 0:bb6687c3a462 259 ZLL_PHY_CTRL_CRC_MSK_MASK |
igor Stepura 0:bb6687c3a462 260 ZLL_PHY_CTRL_PLL_UNLOCK_MSK_MASK |
igor Stepura 0:bb6687c3a462 261 ZLL_PHY_CTRL_FILTERFAIL_MSK_MASK |
igor Stepura 0:bb6687c3a462 262 ZLL_PHY_CTRL_RX_WMRK_MSK_MASK |
igor Stepura 0:bb6687c3a462 263 ZLL_PHY_CTRL_CCAMSK_MASK |
igor Stepura 0:bb6687c3a462 264 ZLL_PHY_CTRL_RXMSK_MASK |
igor Stepura 0:bb6687c3a462 265 ZLL_PHY_CTRL_TXMSK_MASK |
igor Stepura 0:bb6687c3a462 266 ZLL_PHY_CTRL_SEQMSK_MASK |
igor Stepura 0:bb6687c3a462 267 ZLL_PHY_CTRL_AUTOACK_MASK |
igor Stepura 0:bb6687c3a462 268 ZLL_PHY_CTRL_TRCV_MSK_MASK;
igor Stepura 0:bb6687c3a462 269
igor Stepura 0:bb6687c3a462 270 /* Clear all PP IRQ bits to avoid unexpected interrupts immediately after init
igor Stepura 0:bb6687c3a462 271 disable all timer interrupts */
igor Stepura 0:bb6687c3a462 272 ZLL->IRQSTS = ZLL->IRQSTS;
igor Stepura 0:bb6687c3a462 273
igor Stepura 0:bb6687c3a462 274 /* Enable Source Addresing Match module */
igor Stepura 0:bb6687c3a462 275 ZLL->SAM_CTRL |= ZLL_SAM_CTRL_SAP0_EN_MASK;
igor Stepura 0:bb6687c3a462 276
igor Stepura 0:bb6687c3a462 277 /* Clear HW indirect queue */
igor Stepura 0:bb6687c3a462 278 ZLL->SAM_TABLE |= ZLL_SAM_TABLE_INVALIDATE_ALL_MASK;
igor Stepura 0:bb6687c3a462 279
igor Stepura 0:bb6687c3a462 280 /* Frame Filtering
igor Stepura 0:bb6687c3a462 281 FRM_VER[7:6] = b11. Accept FrameVersion 0 and 1 packets, reject all others */
igor Stepura 0:bb6687c3a462 282 ZLL->RX_FRAME_FILTER &= ~ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK;
igor Stepura 0:bb6687c3a462 283 ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3) |
igor Stepura 0:bb6687c3a462 284 ZLL_RX_FRAME_FILTER_CMD_FT_MASK |
igor Stepura 0:bb6687c3a462 285 ZLL_RX_FRAME_FILTER_DATA_FT_MASK |
igor Stepura 0:bb6687c3a462 286 ZLL_RX_FRAME_FILTER_BEACON_FT_MASK;
igor Stepura 0:bb6687c3a462 287
igor Stepura 0:bb6687c3a462 288 /* Set prescaller to obtain 1 symbol (16us) timebase */
igor Stepura 0:bb6687c3a462 289 ZLL->TMR_PRESCALE = 0x05;
igor Stepura 0:bb6687c3a462 290
igor Stepura 0:bb6687c3a462 291 /* Set CCA threshold to -75 dBm */
igor Stepura 0:bb6687c3a462 292 ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK;
igor Stepura 0:bb6687c3a462 293 ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_CCA1_THRESH(0xB5);
igor Stepura 0:bb6687c3a462 294
igor Stepura 0:bb6687c3a462 295 /* Set the default power level */
igor Stepura 0:bb6687c3a462 296 PhyPlmeSetPwrLevelRequest(gPhyDefaultTxPowerLevel_d);
igor Stepura 0:bb6687c3a462 297
igor Stepura 0:bb6687c3a462 298 /* Adjust ACK delay to fulfill the 802.15.4 turnaround requirements */
igor Stepura 0:bb6687c3a462 299 ZLL->ACKDELAY &= ~ZLL_ACKDELAY_ACKDELAY_MASK;
igor Stepura 0:bb6687c3a462 300 ZLL->ACKDELAY |= ZLL_ACKDELAY_ACKDELAY(-8);
igor Stepura 0:bb6687c3a462 301
igor Stepura 0:bb6687c3a462 302 /* Adjust LQI compensation */
igor Stepura 0:bb6687c3a462 303 ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP_MASK;
igor Stepura 0:bb6687c3a462 304 ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP(96);
igor Stepura 0:bb6687c3a462 305
igor Stepura 0:bb6687c3a462 306 /* Enable the RxWatermark IRQ and FilterFail IRQ */
igor Stepura 0:bb6687c3a462 307 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RX_WMRK_MSK_MASK;
igor Stepura 0:bb6687c3a462 308 /* Set Rx watermark level */
igor Stepura 0:bb6687c3a462 309 ZLL->RX_WTR_MARK = 0;
igor Stepura 0:bb6687c3a462 310
igor Stepura 0:bb6687c3a462 311 /*Read eui64*/
igor Stepura 0:bb6687c3a462 312 //rf_set_address(MAC_address);
igor Stepura 0:bb6687c3a462 313 /*set default channel to 11*/
igor Stepura 0:bb6687c3a462 314 rf_channel_set(12);
igor Stepura 0:bb6687c3a462 315 /*Start receiver*/
igor Stepura 0:bb6687c3a462 316
igor Stepura 0:bb6687c3a462 317 /* DSM settings */
igor Stepura 0:bb6687c3a462 318 phyReg = (RSIM->RF_OSC_CTRL & RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_MASK) >>
igor Stepura 0:bb6687c3a462 319 RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_SHIFT;
igor Stepura 0:bb6687c3a462 320 phyReg = (1024U << phyReg) / (CORE_CLOCK_FREQ / 32768) + 1;
igor Stepura 0:bb6687c3a462 321 RSIM->DSM_OSC_OFFSET = phyReg;
igor Stepura 0:bb6687c3a462 322
igor Stepura 0:bb6687c3a462 323 /* Install PHY ISR */
igor Stepura 0:bb6687c3a462 324 PHY_InstallIsr();
igor Stepura 0:bb6687c3a462 325 rf_receive();
igor Stepura 0:bb6687c3a462 326 }
igor Stepura 0:bb6687c3a462 327
igor Stepura 0:bb6687c3a462 328 static void rf_mac64_read(uint8_t *address)
igor Stepura 0:bb6687c3a462 329 {
igor Stepura 0:bb6687c3a462 330 uint64_t val = ZLL->MACLONGADDRS0_MSB;
igor Stepura 0:bb6687c3a462 331 val <<= 32;
igor Stepura 0:bb6687c3a462 332 val |= ZLL->MACLONGADDRS0_LSB;
igor Stepura 0:bb6687c3a462 333
igor Stepura 0:bb6687c3a462 334 *((uint64_t*)address) = val;
igor Stepura 0:bb6687c3a462 335 }
igor Stepura 0:bb6687c3a462 336
igor Stepura 0:bb6687c3a462 337 static void rf_promiscuous(uint8_t state)
igor Stepura 0:bb6687c3a462 338 {
igor Stepura 0:bb6687c3a462 339 if( state )
igor Stepura 0:bb6687c3a462 340 {
igor Stepura 0:bb6687c3a462 341 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_PROMISCUOUS_MASK;
igor Stepura 0:bb6687c3a462 342 /* FRM_VER[11:8] = b1111. Any FrameVersion accepted */
igor Stepura 0:bb6687c3a462 343 ZLL->RX_FRAME_FILTER |= (ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK |
igor Stepura 0:bb6687c3a462 344 ZLL_RX_FRAME_FILTER_ACK_FT_MASK |
igor Stepura 0:bb6687c3a462 345 ZLL_RX_FRAME_FILTER_NS_FT_MASK);
igor Stepura 0:bb6687c3a462 346 }
igor Stepura 0:bb6687c3a462 347 else
igor Stepura 0:bb6687c3a462 348 {
igor Stepura 0:bb6687c3a462 349 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_PROMISCUOUS_MASK;
igor Stepura 0:bb6687c3a462 350 /* FRM_VER[11:8] = b0011. Accept FrameVersion 0 and 1 packets, reject all others */
igor Stepura 0:bb6687c3a462 351 /* Beacon, Data and MAC command frame types accepted */
igor Stepura 0:bb6687c3a462 352 ZLL->RX_FRAME_FILTER &= ~(ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK |
igor Stepura 0:bb6687c3a462 353 ZLL_RX_FRAME_FILTER_ACK_FT_MASK |
igor Stepura 0:bb6687c3a462 354 ZLL_RX_FRAME_FILTER_NS_FT_MASK |
igor Stepura 0:bb6687c3a462 355 ZLL_RX_FRAME_FILTER_ACTIVE_PROMISCUOUS_MASK);
igor Stepura 0:bb6687c3a462 356 ZLL->RX_FRAME_FILTER |= ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3);
igor Stepura 0:bb6687c3a462 357 }
igor Stepura 0:bb6687c3a462 358 }
igor Stepura 0:bb6687c3a462 359
igor Stepura 0:bb6687c3a462 360 static void rf_receive(void)
igor Stepura 0:bb6687c3a462 361 {
igor Stepura 0:bb6687c3a462 362 uint32_t irqSts;
igor Stepura 0:bb6687c3a462 363 /* RX can start only from Idle state */
igor Stepura 0:bb6687c3a462 364 if( rf_get_state() != gIdle_c )
igor Stepura 0:bb6687c3a462 365 {
igor Stepura 0:bb6687c3a462 366 return;
igor Stepura 0:bb6687c3a462 367 }
igor Stepura 0:bb6687c3a462 368 rf_set_power_state(gPhyPwrAutodoze_c);
igor Stepura 0:bb6687c3a462 369
igor Stepura 0:bb6687c3a462 370 /* Ensure that no spurious interrupts are raised, but do not change TMR1 and TMR4 IRQ status */
igor Stepura 0:bb6687c3a462 371 irqSts = ZLL->IRQSTS;
igor Stepura 0:bb6687c3a462 372 irqSts &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK);
igor Stepura 0:bb6687c3a462 373 irqSts |= ZLL_IRQSTS_TMR3MSK_MASK;
igor Stepura 0:bb6687c3a462 374 ZLL->IRQSTS = irqSts;
igor Stepura 0:bb6687c3a462 375
igor Stepura 0:bb6687c3a462 376 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
igor Stepura 0:bb6687c3a462 377 /* Start the RX sequence */
igor Stepura 0:bb6687c3a462 378 ZLL->PHY_CTRL |= gRX_c ;
igor Stepura 0:bb6687c3a462 379 /* unmask SEQ interrupt */
igor Stepura 0:bb6687c3a462 380 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;
igor Stepura 0:bb6687c3a462 381 }
igor Stepura 0:bb6687c3a462 382
igor Stepura 0:bb6687c3a462 383 static int8_t rf_device_register(void)
igor Stepura 0:bb6687c3a462 384 {
igor Stepura 0:bb6687c3a462 385
igor Stepura 0:bb6687c3a462 386 rf_init();
igor Stepura 0:bb6687c3a462 387
igor Stepura 0:bb6687c3a462 388 /*Set pointer to MAC address*/
igor Stepura 0:bb6687c3a462 389 device_driver.PHY_MAC = MAC_address;
igor Stepura 0:bb6687c3a462 390 device_driver.driver_description = (char*)"NXP_KWx";
igor Stepura 0:bb6687c3a462 391
igor Stepura 0:bb6687c3a462 392 //Create setup Used Radio chips
igor Stepura 0:bb6687c3a462 393 /*Type of RF PHY is SubGHz*/
igor Stepura 0:bb6687c3a462 394 device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
igor Stepura 0:bb6687c3a462 395
igor Stepura 0:bb6687c3a462 396 device_driver.phy_channel_pages = phy_channel_pages;
igor Stepura 0:bb6687c3a462 397 /*Maximum size of payload is 127*/
igor Stepura 0:bb6687c3a462 398 device_driver.phy_MTU = 127;
igor Stepura 0:bb6687c3a462 399 /*No header in PHY*/
igor Stepura 0:bb6687c3a462 400 device_driver.phy_header_length = 0;
igor Stepura 0:bb6687c3a462 401 /*No tail in PHY*/
igor Stepura 0:bb6687c3a462 402 device_driver.phy_tail_length = 0;
igor Stepura 0:bb6687c3a462 403 /*Set address write function*/
igor Stepura 0:bb6687c3a462 404 device_driver.address_write = &rf_address_write;
igor Stepura 0:bb6687c3a462 405 /*Set RF extension function*/
igor Stepura 0:bb6687c3a462 406 device_driver.extension = &rf_extension;
igor Stepura 0:bb6687c3a462 407 /*Set RF state control function*/
igor Stepura 0:bb6687c3a462 408 device_driver.state_control = &rf_interface_state_control;
igor Stepura 0:bb6687c3a462 409 /*Set transmit function*/
igor Stepura 0:bb6687c3a462 410 device_driver.tx = &rf_start_cca;
igor Stepura 0:bb6687c3a462 411 /*Upper layer callbacks init to NULL*/
igor Stepura 0:bb6687c3a462 412 device_driver.phy_rx_cb = NULL;
igor Stepura 0:bb6687c3a462 413 device_driver.phy_tx_done_cb = NULL;
igor Stepura 0:bb6687c3a462 414 /*Virtual upper data callback init to NULL*/
igor Stepura 0:bb6687c3a462 415 device_driver.arm_net_virtual_rx_cb = NULL;
igor Stepura 0:bb6687c3a462 416 device_driver.arm_net_virtual_tx_cb = NULL;
igor Stepura 0:bb6687c3a462 417
igor Stepura 0:bb6687c3a462 418 /*Register device driver*/
igor Stepura 0:bb6687c3a462 419 rf_radio_driver_id = arm_net_phy_register(&device_driver);
igor Stepura 0:bb6687c3a462 420
igor Stepura 0:bb6687c3a462 421 return rf_radio_driver_id;
igor Stepura 0:bb6687c3a462 422 }
igor Stepura 0:bb6687c3a462 423
igor Stepura 0:bb6687c3a462 424 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol )
igor Stepura 0:bb6687c3a462 425 {
igor Stepura 0:bb6687c3a462 426 if( rf_get_state() == gRX_c )
igor Stepura 0:bb6687c3a462 427 {
igor Stepura 0:bb6687c3a462 428 uint8_t phyReg = (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK);
igor Stepura 0:bb6687c3a462 429 /* Check for an Rx in progress. */
igor Stepura 0:bb6687c3a462 430 if((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16))
igor Stepura 0:bb6687c3a462 431 {
igor Stepura 0:bb6687c3a462 432 if (device_driver.phy_tx_done_cb) {
igor Stepura 0:bb6687c3a462 433 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
igor Stepura 0:bb6687c3a462 434 }
igor Stepura 0:bb6687c3a462 435 return -1;
igor Stepura 0:bb6687c3a462 436 }
igor Stepura 0:bb6687c3a462 437 rf_abort();
igor Stepura 0:bb6687c3a462 438 }
igor Stepura 0:bb6687c3a462 439 uint8_t* pPB = (uint8_t*)ZLL->PKT_BUFFER_TX;
igor Stepura 0:bb6687c3a462 440 pPB[0] = data_length + 2; /* including 2 bytes of FCS */
igor Stepura 0:bb6687c3a462 441 memcpy(&pPB[1], data_ptr, data_length);
igor Stepura 0:bb6687c3a462 442
igor Stepura 0:bb6687c3a462 443 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCABFRTX_MASK;
igor Stepura 0:bb6687c3a462 444 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_CCATYPE_MASK;
igor Stepura 0:bb6687c3a462 445 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCATYPE(gCcaCCA_MODE1_c);
igor Stepura 0:bb6687c3a462 446
igor Stepura 0:bb6687c3a462 447 mac_tx_handle = tx_handle;
igor Stepura 0:bb6687c3a462 448 need_ack = (*data_ptr & 0x20) == 0x20;
igor Stepura 0:bb6687c3a462 449
igor Stepura 0:bb6687c3a462 450 /* Set XCVR power state in run mode */
igor Stepura 0:bb6687c3a462 451 rf_set_power_state(gPhyPwrAutodoze_c);
igor Stepura 0:bb6687c3a462 452
igor Stepura 0:bb6687c3a462 453 uint8_t xcvseq;
igor Stepura 0:bb6687c3a462 454 if(need_ack)
igor Stepura 0:bb6687c3a462 455 {
igor Stepura 0:bb6687c3a462 456 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_RXACKRQD_MASK;
igor Stepura 0:bb6687c3a462 457 xcvseq = gTR_c;
igor Stepura 0:bb6687c3a462 458
igor Stepura 0:bb6687c3a462 459 }
igor Stepura 0:bb6687c3a462 460 else
igor Stepura 0:bb6687c3a462 461 {
igor Stepura 0:bb6687c3a462 462 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RXACKRQD_MASK;
igor Stepura 0:bb6687c3a462 463 xcvseq = gTX_c;
igor Stepura 0:bb6687c3a462 464 }
igor Stepura 0:bb6687c3a462 465 uint32_t irqSts;
igor Stepura 0:bb6687c3a462 466 /* Ensure that no spurious interrupts are raised(do not change TMR1 and TMR4 IRQ status) */
igor Stepura 0:bb6687c3a462 467 irqSts = ZLL->IRQSTS;
igor Stepura 0:bb6687c3a462 468 irqSts &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK);
igor Stepura 0:bb6687c3a462 469 irqSts |= ZLL_IRQSTS_TMR3MSK_MASK;
igor Stepura 0:bb6687c3a462 470 ZLL->IRQSTS = irqSts;
igor Stepura 0:bb6687c3a462 471
igor Stepura 0:bb6687c3a462 472 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
igor Stepura 0:bb6687c3a462 473 /* Start the TX / TRX / CCA sequence */
igor Stepura 0:bb6687c3a462 474 ZLL->PHY_CTRL |= xcvseq;
igor Stepura 0:bb6687c3a462 475 /* Unmask SEQ interrupt */
igor Stepura 0:bb6687c3a462 476 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;
igor Stepura 0:bb6687c3a462 477
igor Stepura 0:bb6687c3a462 478 return 0;
igor Stepura 0:bb6687c3a462 479 }
igor Stepura 0:bb6687c3a462 480
igor Stepura 0:bb6687c3a462 481 static void rf_set_short_adr(uint8_t * short_address)
igor Stepura 0:bb6687c3a462 482 {
igor Stepura 0:bb6687c3a462 483 uint16_t value = ((uint16_t)short_address[0] << 8) | (uint16_t)short_address[1];
igor Stepura 0:bb6687c3a462 484 //memcpy(&value, short_address, sizeof(value));
igor Stepura 0:bb6687c3a462 485 ZLL->MACSHORTADDRS0 &= ~ZLL_MACSHORTADDRS0_MACSHORTADDRS0_MASK;
igor Stepura 0:bb6687c3a462 486 ZLL->MACSHORTADDRS0 |= ZLL_MACSHORTADDRS0_MACSHORTADDRS0(value);
igor Stepura 0:bb6687c3a462 487 }
igor Stepura 0:bb6687c3a462 488
igor Stepura 0:bb6687c3a462 489 static void rf_set_pan_id(uint8_t *pan_id)
igor Stepura 0:bb6687c3a462 490 {
igor Stepura 0:bb6687c3a462 491 uint16_t value = ((uint16_t)pan_id[0] << 8) | (uint16_t)pan_id[1];
igor Stepura 0:bb6687c3a462 492 ZLL->MACSHORTADDRS0 &= ~ZLL_MACSHORTADDRS0_MACPANID0_MASK;
igor Stepura 0:bb6687c3a462 493 ZLL->MACSHORTADDRS0 |= ZLL_MACSHORTADDRS0_MACPANID0(value);
igor Stepura 0:bb6687c3a462 494 }
igor Stepura 0:bb6687c3a462 495
igor Stepura 0:bb6687c3a462 496 #define TO_UINT32(ptr, num) do {\
igor Stepura 0:bb6687c3a462 497 num = (((uint32_t)(ptr)[0] << 24) |\
igor Stepura 0:bb6687c3a462 498 ((uint32_t)(ptr)[1] << 16) |\
igor Stepura 0:bb6687c3a462 499 ((uint32_t)(ptr)[2] << 8) |\
igor Stepura 0:bb6687c3a462 500 ((uint32_t)(ptr)[3])); \
igor Stepura 0:bb6687c3a462 501 }while(0)
igor Stepura 0:bb6687c3a462 502
igor Stepura 0:bb6687c3a462 503 static void rf_set_address(uint8_t *address)
igor Stepura 0:bb6687c3a462 504 {
igor Stepura 0:bb6687c3a462 505 uint32_t addrLo;
igor Stepura 0:bb6687c3a462 506 uint32_t addrHi;
igor Stepura 0:bb6687c3a462 507
igor Stepura 0:bb6687c3a462 508 TO_UINT32(address, addrHi);
igor Stepura 0:bb6687c3a462 509 TO_UINT32(address + 4, addrLo);
igor Stepura 0:bb6687c3a462 510
igor Stepura 0:bb6687c3a462 511 ZLL->MACLONGADDRS0_LSB = addrLo;
igor Stepura 0:bb6687c3a462 512 ZLL->MACLONGADDRS0_MSB = addrHi;
igor Stepura 0:bb6687c3a462 513 }
igor Stepura 0:bb6687c3a462 514
igor Stepura 0:bb6687c3a462 515 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
igor Stepura 0:bb6687c3a462 516 {
igor Stepura 0:bb6687c3a462 517 int8_t ret_val = 0;
igor Stepura 0:bb6687c3a462 518 switch (address_type)
igor Stepura 0:bb6687c3a462 519 {
igor Stepura 0:bb6687c3a462 520 /*Set 48-bit address*/
igor Stepura 0:bb6687c3a462 521 case PHY_MAC_48BIT:
igor Stepura 0:bb6687c3a462 522 break;
igor Stepura 0:bb6687c3a462 523 /*Set 64-bit address*/
igor Stepura 0:bb6687c3a462 524 case PHY_MAC_64BIT:
igor Stepura 0:bb6687c3a462 525 rf_set_address(address_ptr);
igor Stepura 0:bb6687c3a462 526 break;
igor Stepura 0:bb6687c3a462 527 /*Set 16-bit address*/
igor Stepura 0:bb6687c3a462 528 case PHY_MAC_16BIT:
igor Stepura 0:bb6687c3a462 529 rf_set_short_adr(address_ptr);
igor Stepura 0:bb6687c3a462 530 break;
igor Stepura 0:bb6687c3a462 531 /*Set PAN Id*/
igor Stepura 0:bb6687c3a462 532 case PHY_MAC_PANID:
igor Stepura 0:bb6687c3a462 533 rf_set_pan_id(address_ptr);
igor Stepura 0:bb6687c3a462 534 break;
igor Stepura 0:bb6687c3a462 535 }
igor Stepura 0:bb6687c3a462 536 return ret_val;
igor Stepura 0:bb6687c3a462 537 }
igor Stepura 0:bb6687c3a462 538
igor Stepura 0:bb6687c3a462 539 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
igor Stepura 0:bb6687c3a462 540 {
igor Stepura 0:bb6687c3a462 541 uint32_t type = (uint32_t)extension_type;
igor Stepura 0:bb6687c3a462 542 switch (type)
igor Stepura 0:bb6687c3a462 543 {
igor Stepura 0:bb6687c3a462 544 /*Return frame pending status*/
igor Stepura 0:bb6687c3a462 545 case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
igor Stepura 0:bb6687c3a462 546 *data_ptr = ((ZLL->IRQSTS & ZLL_IRQSTS_RX_FRM_PEND_MASK) >> ZLL_IRQSTS_RX_FRM_PEND_SHIFT);
igor Stepura 0:bb6687c3a462 547 break;
igor Stepura 0:bb6687c3a462 548 /*Read energy on the channel*/
igor Stepura 0:bb6687c3a462 549 case PHY_EXTENSION_READ_CHANNEL_ENERGY:
igor Stepura 0:bb6687c3a462 550 *data_ptr = 100;
igor Stepura 0:bb6687c3a462 551 break;
igor Stepura 0:bb6687c3a462 552 }
igor Stepura 0:bb6687c3a462 553 return 0;
igor Stepura 0:bb6687c3a462 554 }
igor Stepura 0:bb6687c3a462 555
igor Stepura 0:bb6687c3a462 556 #define mPhyDSM_GuardTime_d (5) /* DSM_TIME ticks (32.768KHz) */
igor Stepura 0:bb6687c3a462 557 static uint32_t mPhyDSMDuration = 0xFFFFF0;
igor Stepura 0:bb6687c3a462 558 static void rf_set_power_state(phyPwrMode_t newState)
igor Stepura 0:bb6687c3a462 559 {
igor Stepura 0:bb6687c3a462 560 /* Parameter validation */
igor Stepura 0:bb6687c3a462 561 if( newState > gPhyPwrReset_c )
igor Stepura 0:bb6687c3a462 562 {
igor Stepura 0:bb6687c3a462 563 return;
igor Stepura 0:bb6687c3a462 564 }
igor Stepura 0:bb6687c3a462 565 /* Check if the new power state = old power state */
igor Stepura 0:bb6687c3a462 566 else if( newState == mPhyPwrState )
igor Stepura 0:bb6687c3a462 567 {
igor Stepura 0:bb6687c3a462 568 return;
igor Stepura 0:bb6687c3a462 569 }
igor Stepura 0:bb6687c3a462 570 else
igor Stepura 0:bb6687c3a462 571 {
igor Stepura 0:bb6687c3a462 572 switch(newState)
igor Stepura 0:bb6687c3a462 573 {
igor Stepura 0:bb6687c3a462 574 case gPhyPwrIdle_c:
igor Stepura 0:bb6687c3a462 575 /* Set XCVR in run mode if not allready */
igor Stepura 0:bb6687c3a462 576 if(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK)
igor Stepura 0:bb6687c3a462 577 {
igor Stepura 0:bb6687c3a462 578 RSIM->ZIG_WAKE = (RSIM->DSM_TIMER + mPhyDSM_GuardTime_d);
igor Stepura 0:bb6687c3a462 579 while(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK);
igor Stepura 0:bb6687c3a462 580 }
igor Stepura 0:bb6687c3a462 581 break;
igor Stepura 0:bb6687c3a462 582
igor Stepura 0:bb6687c3a462 583 case gPhyPwrDSM_c:
igor Stepura 0:bb6687c3a462 584 /* Set XCVR in low power mode if not allready */
igor Stepura 0:bb6687c3a462 585 if(!(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK))
igor Stepura 0:bb6687c3a462 586 {
igor Stepura 0:bb6687c3a462 587 uint32_t minTime = (RSIM->DSM_OSC_OFFSET > mPhyDSM_GuardTime_d) ? RSIM->DSM_OSC_OFFSET : mPhyDSM_GuardTime_d;
igor Stepura 0:bb6687c3a462 588
igor Stepura 0:bb6687c3a462 589 RSIM->ZIG_SLEEP = RSIM->DSM_TIMER + minTime;
igor Stepura 0:bb6687c3a462 590 RSIM->ZIG_WAKE = RSIM->DSM_TIMER + mPhyDSMDuration;
igor Stepura 0:bb6687c3a462 591 RSIM->DSM_CONTROL |= RSIM_DSM_CONTROL_ZIG_SYSCLK_REQUEST_EN_MASK |
igor Stepura 0:bb6687c3a462 592 RSIM_DSM_CONTROL_DSM_TIMER_EN_MASK |
igor Stepura 0:bb6687c3a462 593 RSIM_DSM_CONTROL_ZIG_SYSCLK_INTERRUPT_EN_MASK;
igor Stepura 0:bb6687c3a462 594 }
igor Stepura 0:bb6687c3a462 595 break;
igor Stepura 0:bb6687c3a462 596
igor Stepura 0:bb6687c3a462 597 default:
igor Stepura 0:bb6687c3a462 598 /* do not change current state */
igor Stepura 0:bb6687c3a462 599 newState = mPhyPwrState;
igor Stepura 0:bb6687c3a462 600 break;
igor Stepura 0:bb6687c3a462 601 }
igor Stepura 0:bb6687c3a462 602
igor Stepura 0:bb6687c3a462 603 mPhyPwrState = newState;
igor Stepura 0:bb6687c3a462 604 }
igor Stepura 0:bb6687c3a462 605 }
igor Stepura 0:bb6687c3a462 606
igor Stepura 0:bb6687c3a462 607 static void rf_off(void)
igor Stepura 0:bb6687c3a462 608 {
igor Stepura 0:bb6687c3a462 609 /* Abort any ongoing sequences */
igor Stepura 0:bb6687c3a462 610 rf_abort();
igor Stepura 0:bb6687c3a462 611 /* Set XCVR in a low power state */
igor Stepura 0:bb6687c3a462 612 rf_set_power_state(gPhyPwrHibernate_c);
igor Stepura 0:bb6687c3a462 613 }
igor Stepura 0:bb6687c3a462 614
igor Stepura 0:bb6687c3a462 615 static void rf_shutdown(void)
igor Stepura 0:bb6687c3a462 616 {
igor Stepura 0:bb6687c3a462 617 /*Call RF OFF*/
igor Stepura 0:bb6687c3a462 618 rf_off();
igor Stepura 0:bb6687c3a462 619 }
igor Stepura 0:bb6687c3a462 620
igor Stepura 0:bb6687c3a462 621 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
igor Stepura 0:bb6687c3a462 622 {
igor Stepura 0:bb6687c3a462 623 int8_t ret_val = 0;
igor Stepura 0:bb6687c3a462 624 switch (new_state)
igor Stepura 0:bb6687c3a462 625 {
igor Stepura 0:bb6687c3a462 626 /*Reset PHY driver and set to idle*/
igor Stepura 0:bb6687c3a462 627 case PHY_INTERFACE_RESET:
igor Stepura 0:bb6687c3a462 628 break;
igor Stepura 0:bb6687c3a462 629 /*Disable PHY Interface driver*/
igor Stepura 0:bb6687c3a462 630 case PHY_INTERFACE_DOWN:
igor Stepura 0:bb6687c3a462 631 rf_shutdown();
igor Stepura 0:bb6687c3a462 632 break;
igor Stepura 0:bb6687c3a462 633 /*Enable PHY Interface driver*/
igor Stepura 0:bb6687c3a462 634 case PHY_INTERFACE_UP:
igor Stepura 0:bb6687c3a462 635 rf_channel_set(rf_channel);
igor Stepura 0:bb6687c3a462 636 rf_receive();
igor Stepura 0:bb6687c3a462 637 break;
igor Stepura 0:bb6687c3a462 638 /*Enable wireless interface ED scan mode*/
igor Stepura 0:bb6687c3a462 639 case PHY_INTERFACE_RX_ENERGY_STATE:
igor Stepura 0:bb6687c3a462 640 rf_abort();
igor Stepura 0:bb6687c3a462 641 rf_channel_set(rf_channel);
igor Stepura 0:bb6687c3a462 642 break;
igor Stepura 0:bb6687c3a462 643 case PHY_INTERFACE_SNIFFER_STATE: /**< Enable Sniffer state */
igor Stepura 0:bb6687c3a462 644 rf_promiscuous(1);
igor Stepura 0:bb6687c3a462 645 rf_channel_set(rf_channel);
igor Stepura 0:bb6687c3a462 646 rf_receive();
igor Stepura 0:bb6687c3a462 647 break;
igor Stepura 0:bb6687c3a462 648 }
igor Stepura 0:bb6687c3a462 649 return ret_val;
igor Stepura 0:bb6687c3a462 650 }
igor Stepura 0:bb6687c3a462 651
igor Stepura 0:bb6687c3a462 652 static void rf_device_unregister(void)
igor Stepura 0:bb6687c3a462 653 {
igor Stepura 0:bb6687c3a462 654 arm_net_phy_unregister(rf_radio_driver_id);
igor Stepura 0:bb6687c3a462 655 }
igor Stepura 0:bb6687c3a462 656
igor Stepura 0:bb6687c3a462 657 static void rf_abort(void)
igor Stepura 0:bb6687c3a462 658 {
igor Stepura 0:bb6687c3a462 659 /* Mask SEQ interrupt */
igor Stepura 0:bb6687c3a462 660 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK;
igor Stepura 0:bb6687c3a462 661 /* Disable timer trigger (for scheduled XCVSEQ) */
igor Stepura 0:bb6687c3a462 662 if( ZLL->PHY_CTRL & ZLL_PHY_CTRL_TMRTRIGEN_MASK )
igor Stepura 0:bb6687c3a462 663 {
igor Stepura 0:bb6687c3a462 664 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMRTRIGEN_MASK;
igor Stepura 0:bb6687c3a462 665 /* give the FSM enough time to start if it was triggered */
igor Stepura 0:bb6687c3a462 666 while( (XCVR_MISC->XCVR_CTRL & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) == 0) {}
igor Stepura 0:bb6687c3a462 667 }
igor Stepura 0:bb6687c3a462 668
igor Stepura 0:bb6687c3a462 669 /* If XCVR is not idle, abort current SEQ */
igor Stepura 0:bb6687c3a462 670 if( ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK )
igor Stepura 0:bb6687c3a462 671 {
igor Stepura 0:bb6687c3a462 672 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
igor Stepura 0:bb6687c3a462 673 /* wait for Sequence Idle (if not already) */
igor Stepura 0:bb6687c3a462 674 while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
igor Stepura 0:bb6687c3a462 675 }
igor Stepura 0:bb6687c3a462 676
igor Stepura 0:bb6687c3a462 677 /* Stop timers */
igor Stepura 0:bb6687c3a462 678 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR2CMP_EN_MASK |
igor Stepura 0:bb6687c3a462 679 ZLL_PHY_CTRL_TMR3CMP_EN_MASK |
igor Stepura 0:bb6687c3a462 680 ZLL_PHY_CTRL_TC3TMOUT_MASK );
igor Stepura 0:bb6687c3a462 681 /* clear all PP IRQ bits to avoid unexpected interrupts( do not change TMR1 and TMR4 IRQ status ) */
igor Stepura 0:bb6687c3a462 682 ZLL->IRQSTS &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK);
igor Stepura 0:bb6687c3a462 683 }
igor Stepura 0:bb6687c3a462 684
igor Stepura 0:bb6687c3a462 685
igor Stepura 0:bb6687c3a462 686
igor Stepura 0:bb6687c3a462 687 /*
igor Stepura 0:bb6687c3a462 688 * \brief Function is a RF interrupt vector. End of frame in RX and TX are handled here as well as CCA process interrupt.
igor Stepura 0:bb6687c3a462 689 *
igor Stepura 0:bb6687c3a462 690 * \param none
igor Stepura 0:bb6687c3a462 691 *
igor Stepura 0:bb6687c3a462 692 * \return none
igor Stepura 0:bb6687c3a462 693 */
igor Stepura 0:bb6687c3a462 694 static volatile uint8_t gIrqStatus = 0;
igor Stepura 0:bb6687c3a462 695 static void PHY_InterruptHandler(void)
igor Stepura 0:bb6687c3a462 696 {
igor Stepura 0:bb6687c3a462 697 gIrqStatus = ZLL->IRQSTS;
igor Stepura 0:bb6687c3a462 698 ZLL->IRQSTS = gIrqStatus;
igor Stepura 0:bb6687c3a462 699 irq_thread.signal_set(1);
igor Stepura 0:bb6687c3a462 700 }
igor Stepura 0:bb6687c3a462 701
igor Stepura 0:bb6687c3a462 702 static void PHY_InterruptThread(void)
igor Stepura 0:bb6687c3a462 703 {
igor Stepura 0:bb6687c3a462 704 for (;;) {
igor Stepura 0:bb6687c3a462 705 osEvent event = irq_thread.signal_wait(0);
igor Stepura 0:bb6687c3a462 706 if (event.status != osEventSignal) {
igor Stepura 0:bb6687c3a462 707 continue;
igor Stepura 0:bb6687c3a462 708 }
igor Stepura 0:bb6687c3a462 709 // rf_if_lock();
igor Stepura 0:bb6687c3a462 710 handle_interrupt(gIrqStatus);
igor Stepura 0:bb6687c3a462 711 // rf_if_unlock();
igor Stepura 0:bb6687c3a462 712
igor Stepura 0:bb6687c3a462 713 }
igor Stepura 0:bb6687c3a462 714 }
igor Stepura 0:bb6687c3a462 715
igor Stepura 0:bb6687c3a462 716 static void PhyIsrSeqCleanup(void)
igor Stepura 0:bb6687c3a462 717 {
igor Stepura 0:bb6687c3a462 718 uint32_t irqStatus;
igor Stepura 0:bb6687c3a462 719
igor Stepura 0:bb6687c3a462 720 /* Set the PHY sequencer back to IDLE */
igor Stepura 0:bb6687c3a462 721 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
igor Stepura 0:bb6687c3a462 722 /* Mask SEQ, RX, TX and CCA interrupts */
igor Stepura 0:bb6687c3a462 723 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK |
igor Stepura 0:bb6687c3a462 724 ZLL_PHY_CTRL_RXMSK_MASK |
igor Stepura 0:bb6687c3a462 725 ZLL_PHY_CTRL_TXMSK_MASK |
igor Stepura 0:bb6687c3a462 726 ZLL_PHY_CTRL_SEQMSK_MASK;
igor Stepura 0:bb6687c3a462 727
igor Stepura 0:bb6687c3a462 728 while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
igor Stepura 0:bb6687c3a462 729
igor Stepura 0:bb6687c3a462 730 irqStatus = ZLL->IRQSTS;
igor Stepura 0:bb6687c3a462 731 /* Mask TMR3 interrupt */
igor Stepura 0:bb6687c3a462 732 irqStatus |= ZLL_IRQSTS_TMR3MSK_MASK;
igor Stepura 0:bb6687c3a462 733 /* Clear transceiver interrupts except TMRxIRQ */
igor Stepura 0:bb6687c3a462 734 irqStatus &= ~( ZLL_IRQSTS_TMR1IRQ_MASK |
igor Stepura 0:bb6687c3a462 735 ZLL_IRQSTS_TMR2IRQ_MASK |
igor Stepura 0:bb6687c3a462 736 ZLL_IRQSTS_TMR3IRQ_MASK |
igor Stepura 0:bb6687c3a462 737 ZLL_IRQSTS_TMR4IRQ_MASK );
igor Stepura 0:bb6687c3a462 738 ZLL->IRQSTS = irqStatus;
igor Stepura 0:bb6687c3a462 739 }
igor Stepura 0:bb6687c3a462 740
igor Stepura 0:bb6687c3a462 741 static void PhyIsrTimeoutCleanup(void)
igor Stepura 0:bb6687c3a462 742 {
igor Stepura 0:bb6687c3a462 743 uint32_t irqStatus;
igor Stepura 0:bb6687c3a462 744
igor Stepura 0:bb6687c3a462 745 /* Set the PHY sequencer back to IDLE and disable TMR3 comparator and timeout */
igor Stepura 0:bb6687c3a462 746 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR3CMP_EN_MASK |
igor Stepura 0:bb6687c3a462 747 ZLL_PHY_CTRL_TC3TMOUT_MASK |
igor Stepura 0:bb6687c3a462 748 ZLL_PHY_CTRL_XCVSEQ_MASK);
igor Stepura 0:bb6687c3a462 749 /* Mask SEQ, RX, TX and CCA interrupts */
igor Stepura 0:bb6687c3a462 750 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK |
igor Stepura 0:bb6687c3a462 751 ZLL_PHY_CTRL_RXMSK_MASK |
igor Stepura 0:bb6687c3a462 752 ZLL_PHY_CTRL_TXMSK_MASK |
igor Stepura 0:bb6687c3a462 753 ZLL_PHY_CTRL_SEQMSK_MASK;
igor Stepura 0:bb6687c3a462 754
igor Stepura 0:bb6687c3a462 755 while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
igor Stepura 0:bb6687c3a462 756
igor Stepura 0:bb6687c3a462 757 irqStatus = ZLL->IRQSTS;
igor Stepura 0:bb6687c3a462 758 /* Mask TMR3 interrupt */
igor Stepura 0:bb6687c3a462 759 irqStatus |= ZLL_IRQSTS_TMR3MSK_MASK;
igor Stepura 0:bb6687c3a462 760 /* Clear transceiver interrupts except TMR1IRQ and TMR4IRQ. */
igor Stepura 0:bb6687c3a462 761 irqStatus &= ~( ZLL_IRQSTS_TMR1IRQ_MASK |
igor Stepura 0:bb6687c3a462 762 ZLL_IRQSTS_TMR4IRQ_MASK );
igor Stepura 0:bb6687c3a462 763 ZLL->IRQSTS = irqStatus;
igor Stepura 0:bb6687c3a462 764 }
igor Stepura 0:bb6687c3a462 765
igor Stepura 0:bb6687c3a462 766 static inline uint8_t rf_convert_lqi(uint8_t rssi)
igor Stepura 0:bb6687c3a462 767 {
igor Stepura 0:bb6687c3a462 768 if (rssi >= 220)
igor Stepura 0:bb6687c3a462 769 {
igor Stepura 0:bb6687c3a462 770 rssi = 255;
igor Stepura 0:bb6687c3a462 771 }
igor Stepura 0:bb6687c3a462 772 else
igor Stepura 0:bb6687c3a462 773 {
igor Stepura 0:bb6687c3a462 774 rssi = (51 * rssi) / 44;
igor Stepura 0:bb6687c3a462 775 }
igor Stepura 0:bb6687c3a462 776
igor Stepura 0:bb6687c3a462 777 return rssi;
igor Stepura 0:bb6687c3a462 778 }
igor Stepura 0:bb6687c3a462 779
igor Stepura 0:bb6687c3a462 780 static void rf_handle_rx_end(void)
igor Stepura 0:bb6687c3a462 781 {
igor Stepura 0:bb6687c3a462 782 uint32_t irqSts;
igor Stepura 0:bb6687c3a462 783
igor Stepura 0:bb6687c3a462 784 /* disable TMR3 compare */
igor Stepura 0:bb6687c3a462 785 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK;
igor Stepura 0:bb6687c3a462 786 /* disable autosequence stop by TC3 match */
igor Stepura 0:bb6687c3a462 787 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TC3TMOUT_MASK;
igor Stepura 0:bb6687c3a462 788 /* mask TMR3 interrupt (do not change other IRQ status) */
igor Stepura 0:bb6687c3a462 789 irqSts = ZLL->IRQSTS & (ZLL_IRQSTS_TMR1MSK_MASK |
igor Stepura 0:bb6687c3a462 790 ZLL_IRQSTS_TMR2MSK_MASK |
igor Stepura 0:bb6687c3a462 791 ZLL_IRQSTS_TMR3MSK_MASK |
igor Stepura 0:bb6687c3a462 792 ZLL_IRQSTS_TMR4MSK_MASK );
igor Stepura 0:bb6687c3a462 793 irqSts |= ZLL_IRQSTS_TMR3MSK_MASK;
igor Stepura 0:bb6687c3a462 794 /* aknowledge TMR3 IRQ */
igor Stepura 0:bb6687c3a462 795 irqSts |= ZLL_IRQSTS_TMR3IRQ_MASK;
igor Stepura 0:bb6687c3a462 796 ZLL->IRQSTS = irqSts;
igor Stepura 0:bb6687c3a462 797
igor Stepura 0:bb6687c3a462 798 uint8_t rssi = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >> ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT;
igor Stepura 0:bb6687c3a462 799 uint8_t lqi = rf_convert_lqi(rssi);
igor Stepura 0:bb6687c3a462 800 uint8_t psduLength = (ZLL->IRQSTS & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK) >> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT; /* Including FCS (2 bytes) */
igor Stepura 0:bb6687c3a462 801 uint8_t len = psduLength - 2;
igor Stepura 0:bb6687c3a462 802
igor Stepura 0:bb6687c3a462 803 rf_receive();
igor Stepura 0:bb6687c3a462 804 if (psduLength > 0 )
igor Stepura 0:bb6687c3a462 805 {
igor Stepura 0:bb6687c3a462 806 for (uint8_t i = 0; i < len; i++)
igor Stepura 0:bb6687c3a462 807 {
igor Stepura 0:bb6687c3a462 808 rf_buffer[i] = ((uint8_t*)ZLL->PKT_BUFFER_RX)[i];
igor Stepura 0:bb6687c3a462 809 }
igor Stepura 0:bb6687c3a462 810
igor Stepura 0:bb6687c3a462 811 if (device_driver.phy_rx_cb) {
igor Stepura 0:bb6687c3a462 812 device_driver.phy_rx_cb(rf_buffer, len, lqi, rssi, rf_radio_driver_id);
igor Stepura 0:bb6687c3a462 813 }
igor Stepura 0:bb6687c3a462 814 }
igor Stepura 0:bb6687c3a462 815
igor Stepura 0:bb6687c3a462 816 }
igor Stepura 0:bb6687c3a462 817
igor Stepura 0:bb6687c3a462 818 static void handle_interrupt(uint32_t irqStatus)
igor Stepura 0:bb6687c3a462 819 {
igor Stepura 0:bb6687c3a462 820 /* RSIM Wake-up IRQ */
igor Stepura 0:bb6687c3a462 821 if(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_SYSCLK_REQ_INT_MASK)
igor Stepura 0:bb6687c3a462 822 {
igor Stepura 0:bb6687c3a462 823 RSIM->DSM_CONTROL = RSIM->DSM_CONTROL;
igor Stepura 0:bb6687c3a462 824 return;
igor Stepura 0:bb6687c3a462 825 }
igor Stepura 0:bb6687c3a462 826
igor Stepura 0:bb6687c3a462 827 /* Read current XCVRSEQ and interrup status */
igor Stepura 0:bb6687c3a462 828 uint32_t xcvseqCopy = ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK;
igor Stepura 0:bb6687c3a462 829
igor Stepura 0:bb6687c3a462 830 /* WAKE IRQ */
igor Stepura 0:bb6687c3a462 831 if( irqStatus & ZLL_IRQSTS_WAKE_IRQ_MASK )
igor Stepura 0:bb6687c3a462 832 {
igor Stepura 0:bb6687c3a462 833 uint32_t timeAdjust = RSIM->ZIG_WAKE;
igor Stepura 0:bb6687c3a462 834 /* Adjust the 802.15.4 EVENT_TMR */
igor Stepura 0:bb6687c3a462 835 timeAdjust = (timeAdjust - RSIM->ZIG_SLEEP)/32768U * 1000000U; /* [us] */
igor Stepura 0:bb6687c3a462 836 ZLL->EVENT_TMR = (timeAdjust << 4) | ZLL_EVENT_TMR_EVENT_TMR_ADD_MASK;
igor Stepura 0:bb6687c3a462 837 //Radio_Phy_TimeRxTimeoutIndication(mPhyInstance);
igor Stepura 0:bb6687c3a462 838 }
igor Stepura 0:bb6687c3a462 839
igor Stepura 0:bb6687c3a462 840 /* Flter Fail IRQ */
igor Stepura 0:bb6687c3a462 841 if( irqStatus & ZLL_IRQSTS_FILTERFAIL_IRQ_MASK )
igor Stepura 0:bb6687c3a462 842 {
igor Stepura 0:bb6687c3a462 843 }
igor Stepura 0:bb6687c3a462 844 /* Rx Watermark IRQ */
igor Stepura 0:bb6687c3a462 845 else
igor Stepura 0:bb6687c3a462 846 {
igor Stepura 0:bb6687c3a462 847 if( (!(ZLL->PHY_CTRL & ZLL_PHY_CTRL_RX_WMRK_MSK_MASK)) && (irqStatus & ZLL_IRQSTS_RXWTRMRKIRQ_MASK) )
igor Stepura 0:bb6687c3a462 848 {
igor Stepura 0:bb6687c3a462 849 uint32_t length = (irqStatus & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK) >> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT;
igor Stepura 0:bb6687c3a462 850 }
igor Stepura 0:bb6687c3a462 851 }
igor Stepura 0:bb6687c3a462 852
igor Stepura 0:bb6687c3a462 853 /* Timer 1 Compare Match */
igor Stepura 0:bb6687c3a462 854 if( (irqStatus & ZLL_IRQSTS_TMR1IRQ_MASK) && (!(irqStatus & ZLL_IRQSTS_TMR1MSK_MASK)) )
igor Stepura 0:bb6687c3a462 855 {
igor Stepura 0:bb6687c3a462 856 }
igor Stepura 0:bb6687c3a462 857
igor Stepura 0:bb6687c3a462 858 /* Sequencer interrupt, the autosequence has completed */
igor Stepura 0:bb6687c3a462 859 if( (!(ZLL->PHY_CTRL & ZLL_PHY_CTRL_SEQMSK_MASK)) && (irqStatus & ZLL_IRQSTS_SEQIRQ_MASK) )
igor Stepura 0:bb6687c3a462 860 {
igor Stepura 0:bb6687c3a462 861 /* PLL unlock, the autosequence has been aborted due to PLL unlock */
igor Stepura 0:bb6687c3a462 862 if( irqStatus & ZLL_IRQSTS_PLL_UNLOCK_IRQ_MASK )
igor Stepura 0:bb6687c3a462 863 {
igor Stepura 0:bb6687c3a462 864 PhyIsrSeqCleanup();
igor Stepura 0:bb6687c3a462 865 }
igor Stepura 0:bb6687c3a462 866 /* TMR3 timeout, the autosequence has been aborted due to TMR3 timeout */
igor Stepura 0:bb6687c3a462 867 else if( (irqStatus & ZLL_IRQSTS_TMR3IRQ_MASK) &&
igor Stepura 0:bb6687c3a462 868 (!(irqStatus & ZLL_IRQSTS_RXIRQ_MASK)) &&
igor Stepura 0:bb6687c3a462 869 (gTX_c != xcvseqCopy) )
igor Stepura 0:bb6687c3a462 870 {
igor Stepura 0:bb6687c3a462 871 PhyIsrTimeoutCleanup();
igor Stepura 0:bb6687c3a462 872 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 1);
igor Stepura 0:bb6687c3a462 873 }
igor Stepura 0:bb6687c3a462 874 else
igor Stepura 0:bb6687c3a462 875 {
igor Stepura 0:bb6687c3a462 876 PhyIsrSeqCleanup();
igor Stepura 0:bb6687c3a462 877 switch(xcvseqCopy)
igor Stepura 0:bb6687c3a462 878 {
igor Stepura 0:bb6687c3a462 879 case gTX_c:
igor Stepura 0:bb6687c3a462 880 if( (ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCABFRTX_MASK) && (irqStatus & ZLL_IRQSTS_CCA_MASK ) )
igor Stepura 0:bb6687c3a462 881 {
igor Stepura 0:bb6687c3a462 882 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
igor Stepura 0:bb6687c3a462 883 }
igor Stepura 0:bb6687c3a462 884 else
igor Stepura 0:bb6687c3a462 885 {
igor Stepura 0:bb6687c3a462 886 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
igor Stepura 0:bb6687c3a462 887 /* wait for Sequence Idle (if not already) */
igor Stepura 0:bb6687c3a462 888 ZLL->PHY_CTRL |= (ZLL_PHY_CTRL_CCAMSK_MASK |
igor Stepura 0:bb6687c3a462 889 ZLL_PHY_CTRL_RXMSK_MASK |
igor Stepura 0:bb6687c3a462 890 ZLL_PHY_CTRL_TXMSK_MASK |
igor Stepura 0:bb6687c3a462 891 ZLL_PHY_CTRL_SEQMSK_MASK);
igor Stepura 0:bb6687c3a462 892 while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
igor Stepura 0:bb6687c3a462 893 rf_handle_tx_end(0);
igor Stepura 0:bb6687c3a462 894 }
igor Stepura 0:bb6687c3a462 895 break;
igor Stepura 0:bb6687c3a462 896
igor Stepura 0:bb6687c3a462 897 case gTR_c:
igor Stepura 0:bb6687c3a462 898 if( (ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCABFRTX_MASK) && (irqStatus & ZLL_IRQSTS_CCA_MASK ) )
igor Stepura 0:bb6687c3a462 899 {
igor Stepura 0:bb6687c3a462 900 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
igor Stepura 0:bb6687c3a462 901 }
igor Stepura 0:bb6687c3a462 902 else
igor Stepura 0:bb6687c3a462 903 {
igor Stepura 0:bb6687c3a462 904 rf_handle_tx_end((irqStatus & ZLL_IRQSTS_RX_FRM_PEND_MASK) > 0);
igor Stepura 0:bb6687c3a462 905
igor Stepura 0:bb6687c3a462 906 }
igor Stepura 0:bb6687c3a462 907 break;
igor Stepura 0:bb6687c3a462 908
igor Stepura 0:bb6687c3a462 909 case gRX_c:
igor Stepura 0:bb6687c3a462 910 rf_handle_rx_end();
igor Stepura 0:bb6687c3a462 911 break;
igor Stepura 0:bb6687c3a462 912
igor Stepura 0:bb6687c3a462 913 case gCCA_c:
igor Stepura 0:bb6687c3a462 914 if( gCcaED_c == ((ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCATYPE_MASK) >> ZLL_PHY_CTRL_CCATYPE_SHIFT) )
igor Stepura 0:bb6687c3a462 915 {
igor Stepura 0:bb6687c3a462 916 //Radio_Phy_PlmeEdConfirm( (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_CCA1_ED_FNL_MASK) >> ZLL_LQI_AND_RSSI_CCA1_ED_FNL_SHIFT, mPhyInstance );
igor Stepura 0:bb6687c3a462 917 }
igor Stepura 0:bb6687c3a462 918 else /* CCA */
igor Stepura 0:bb6687c3a462 919 {
igor Stepura 0:bb6687c3a462 920 if( irqStatus & ZLL_IRQSTS_CCA_MASK )
igor Stepura 0:bb6687c3a462 921 {
igor Stepura 0:bb6687c3a462 922 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
igor Stepura 0:bb6687c3a462 923 }
igor Stepura 0:bb6687c3a462 924 else
igor Stepura 0:bb6687c3a462 925 {
igor Stepura 0:bb6687c3a462 926 }
igor Stepura 0:bb6687c3a462 927 }
igor Stepura 0:bb6687c3a462 928 break;
igor Stepura 0:bb6687c3a462 929
igor Stepura 0:bb6687c3a462 930 case gCCCA_c:
igor Stepura 0:bb6687c3a462 931 //Radio_Phy_PlmeCcaConfirm(gPhyChannelIdle_c, mPhyInstance);
igor Stepura 0:bb6687c3a462 932 break;
igor Stepura 0:bb6687c3a462 933
igor Stepura 0:bb6687c3a462 934 default:
igor Stepura 0:bb6687c3a462 935 break;
igor Stepura 0:bb6687c3a462 936 }
igor Stepura 0:bb6687c3a462 937 }
igor Stepura 0:bb6687c3a462 938 }
igor Stepura 0:bb6687c3a462 939 /* Timers interrupt */
igor Stepura 0:bb6687c3a462 940 else
igor Stepura 0:bb6687c3a462 941 {
igor Stepura 0:bb6687c3a462 942 /* Timer 2 Compare Match */
igor Stepura 0:bb6687c3a462 943 if( (irqStatus & ZLL_IRQSTS_TMR2IRQ_MASK) && (!(irqStatus & ZLL_IRQSTS_TMR2MSK_MASK)) )
igor Stepura 0:bb6687c3a462 944 {
igor Stepura 0:bb6687c3a462 945 if( gIdle_c != xcvseqCopy )
igor Stepura 0:bb6687c3a462 946 {
igor Stepura 0:bb6687c3a462 947 //Radio_Phy_TimeStartEventIndication(mPhyInstance);
igor Stepura 0:bb6687c3a462 948 }
igor Stepura 0:bb6687c3a462 949 }
igor Stepura 0:bb6687c3a462 950
igor Stepura 0:bb6687c3a462 951 /* Timer 3 Compare Match */
igor Stepura 0:bb6687c3a462 952 if( (irqStatus & ZLL_IRQSTS_TMR3IRQ_MASK) && (!(irqStatus & ZLL_IRQSTS_TMR3MSK_MASK)) )
igor Stepura 0:bb6687c3a462 953 {
igor Stepura 0:bb6687c3a462 954
igor Stepura 0:bb6687c3a462 955 /* Ensure that we're not issuing TimeoutIndication while the Automated sequence is still in progress */
igor Stepura 0:bb6687c3a462 956 /* TMR3 can expire during R-T turnaround for example, case in which the sequence is not interrupted */
igor Stepura 0:bb6687c3a462 957 if( gIdle_c == xcvseqCopy )
igor Stepura 0:bb6687c3a462 958 {
igor Stepura 0:bb6687c3a462 959 //device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 1);
igor Stepura 0:bb6687c3a462 960 //Radio_Phy_TimeRxTimeoutIndication(mPhyInstance);
igor Stepura 0:bb6687c3a462 961 }
igor Stepura 0:bb6687c3a462 962 }
igor Stepura 0:bb6687c3a462 963
igor Stepura 0:bb6687c3a462 964 /* Timer 4 Compare Match */
igor Stepura 0:bb6687c3a462 965 if( (irqStatus & ZLL_IRQSTS_TMR4IRQ_MASK) && (!(irqStatus & ZLL_IRQSTS_TMR4MSK_MASK)) )
igor Stepura 0:bb6687c3a462 966 {
igor Stepura 0:bb6687c3a462 967 /* Disable TMR4 comparator */
igor Stepura 0:bb6687c3a462 968 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR4CMP_EN_MASK;
igor Stepura 0:bb6687c3a462 969 /* Mask and clear TMR4 interrupt (do not change other IRQ status) */
igor Stepura 0:bb6687c3a462 970 irqStatus &= ~( ZLL_IRQSTS_TMR1MSK_MASK |
igor Stepura 0:bb6687c3a462 971 ZLL_IRQSTS_TMR2MSK_MASK |
igor Stepura 0:bb6687c3a462 972 ZLL_IRQSTS_TMR3MSK_MASK );
igor Stepura 0:bb6687c3a462 973 irqStatus |= ZLL_IRQSTS_TMR4IRQ_MASK | ZLL_IRQSTS_TMR4MSK_MASK;
igor Stepura 0:bb6687c3a462 974 ZLL->IRQSTS = irqStatus;
igor Stepura 0:bb6687c3a462 975 }
igor Stepura 0:bb6687c3a462 976 }
igor Stepura 0:bb6687c3a462 977 }
igor Stepura 0:bb6687c3a462 978
igor Stepura 0:bb6687c3a462 979 static void rf_handle_tx_end(uint8_t rx_frame_pending)
igor Stepura 0:bb6687c3a462 980 {
igor Stepura 0:bb6687c3a462 981 rf_receive();
igor Stepura 0:bb6687c3a462 982
igor Stepura 0:bb6687c3a462 983 if (!device_driver.phy_tx_done_cb) {
igor Stepura 0:bb6687c3a462 984 return;
igor Stepura 0:bb6687c3a462 985 }
igor Stepura 0:bb6687c3a462 986 if( need_ack )
igor Stepura 0:bb6687c3a462 987 {
igor Stepura 0:bb6687c3a462 988 if( rx_frame_pending )
igor Stepura 0:bb6687c3a462 989 {
igor Stepura 0:bb6687c3a462 990 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE_PENDING, 1, 1);
igor Stepura 0:bb6687c3a462 991 }
igor Stepura 0:bb6687c3a462 992 else
igor Stepura 0:bb6687c3a462 993 {
igor Stepura 0:bb6687c3a462 994 // arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
igor Stepura 0:bb6687c3a462 995 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1);
igor Stepura 0:bb6687c3a462 996 }
igor Stepura 0:bb6687c3a462 997 }
igor Stepura 0:bb6687c3a462 998 else
igor Stepura 0:bb6687c3a462 999 {
igor Stepura 0:bb6687c3a462 1000 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
igor Stepura 0:bb6687c3a462 1001 }
igor Stepura 0:bb6687c3a462 1002
igor Stepura 0:bb6687c3a462 1003
igor Stepura 0:bb6687c3a462 1004 }
igor Stepura 0:bb6687c3a462 1005
igor Stepura 0:bb6687c3a462 1006 NanostackRfPhyKw41z::NanostackRfPhyKw41z()
igor Stepura 0:bb6687c3a462 1007 {
igor Stepura 0:bb6687c3a462 1008 }
igor Stepura 0:bb6687c3a462 1009
igor Stepura 0:bb6687c3a462 1010 NanostackRfPhyKw41z::~NanostackRfPhyKw41z()
igor Stepura 0:bb6687c3a462 1011 {
igor Stepura 0:bb6687c3a462 1012 }
igor Stepura 0:bb6687c3a462 1013
igor Stepura 0:bb6687c3a462 1014 int8_t NanostackRfPhyKw41z::rf_register()
igor Stepura 0:bb6687c3a462 1015 {
igor Stepura 0:bb6687c3a462 1016
igor Stepura 0:bb6687c3a462 1017 rf_if_lock();
igor Stepura 0:bb6687c3a462 1018
igor Stepura 0:bb6687c3a462 1019 if (rf != NULL) {
igor Stepura 0:bb6687c3a462 1020 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1021 error("Multiple registrations of NanostackRfPhyKw41z not supported");
igor Stepura 0:bb6687c3a462 1022 return -1;
igor Stepura 0:bb6687c3a462 1023 }
igor Stepura 0:bb6687c3a462 1024
igor Stepura 0:bb6687c3a462 1025 irq_thread.start(mbed::callback(PHY_InterruptThread));
igor Stepura 0:bb6687c3a462 1026
igor Stepura 0:bb6687c3a462 1027 int8_t radio_id = rf_device_register();
igor Stepura 0:bb6687c3a462 1028 if (radio_id < 0) {
igor Stepura 0:bb6687c3a462 1029 rf = NULL;
igor Stepura 0:bb6687c3a462 1030 }
igor Stepura 0:bb6687c3a462 1031
igor Stepura 0:bb6687c3a462 1032 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1033 return radio_id;
igor Stepura 0:bb6687c3a462 1034 }
igor Stepura 0:bb6687c3a462 1035
igor Stepura 0:bb6687c3a462 1036 void NanostackRfPhyKw41z::rf_unregister()
igor Stepura 0:bb6687c3a462 1037 {
igor Stepura 0:bb6687c3a462 1038 rf_if_lock();
igor Stepura 0:bb6687c3a462 1039
igor Stepura 0:bb6687c3a462 1040 if (rf != this) {
igor Stepura 0:bb6687c3a462 1041 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1042 return;
igor Stepura 0:bb6687c3a462 1043 }
igor Stepura 0:bb6687c3a462 1044
igor Stepura 0:bb6687c3a462 1045 rf_device_unregister();
igor Stepura 0:bb6687c3a462 1046 rf = NULL;
igor Stepura 0:bb6687c3a462 1047 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1048 }
igor Stepura 0:bb6687c3a462 1049
igor Stepura 0:bb6687c3a462 1050
igor Stepura 0:bb6687c3a462 1051 void NanostackRfPhyKw41z::set_mac_address(uint8_t* mac)
igor Stepura 0:bb6687c3a462 1052 {
igor Stepura 0:bb6687c3a462 1053 rf_if_lock();
igor Stepura 0:bb6687c3a462 1054
igor Stepura 0:bb6687c3a462 1055 if (NULL != rf) {
igor Stepura 0:bb6687c3a462 1056 error("NanostackRfPhyKw41z cannot change mac address when running");
igor Stepura 0:bb6687c3a462 1057 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1058 return;
igor Stepura 0:bb6687c3a462 1059 }
igor Stepura 0:bb6687c3a462 1060 memcpy((void*)MAC_address, (void*)mac, sizeof(MAC_address));
igor Stepura 0:bb6687c3a462 1061
igor Stepura 0:bb6687c3a462 1062 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1063 }
igor Stepura 0:bb6687c3a462 1064
igor Stepura 0:bb6687c3a462 1065 void NanostackRfPhyKw41z::get_mac_address(uint8_t *mac)
igor Stepura 0:bb6687c3a462 1066 {
igor Stepura 0:bb6687c3a462 1067 rf_if_lock();
igor Stepura 0:bb6687c3a462 1068
igor Stepura 0:bb6687c3a462 1069 memcpy((void*)mac, (void*)MAC_address, sizeof(MAC_address));
igor Stepura 0:bb6687c3a462 1070
igor Stepura 0:bb6687c3a462 1071 rf_if_unlock();
igor Stepura 0:bb6687c3a462 1072 }
igor Stepura 0:bb6687c3a462 1073