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:
Fri Jul 21 20:56:10 2017 -0400
Revision:
1:4e0ed8184753
Parent:
0:bb6687c3a462
Child:
2:8b42f07a0f12
Update file headers. Make some parameters configurable

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