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:
Sat Jul 22 13:22:46 2017 -0400
Revision:
2:8b42f07a0f12
Parent:
1:4e0ed8184753
Child:
3:9f6427e86978
Code cleanup

Who changed what in which revision?

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