BA / Mbed OS BaBoRo_test2
Committer:
borlanic
Date:
Tue Apr 24 11:45:18 2018 +0000
Revision:
0:02dd72d1d465
BaBoRo_test2 - backup 1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
borlanic 0:02dd72d1d465 1 /*
borlanic 0:02dd72d1d465 2 * Copyright (c) 2016-2016 ARM Limited. All rights reserved.
borlanic 0:02dd72d1d465 3 * SPDX-License-Identifier: Apache-2.0
borlanic 0:02dd72d1d465 4 * Licensed under the Apache License, Version 2.0 (the License); you may
borlanic 0:02dd72d1d465 5 * not use this file except in compliance with the License.
borlanic 0:02dd72d1d465 6 * You may obtain a copy of the License at
borlanic 0:02dd72d1d465 7 *
borlanic 0:02dd72d1d465 8 * http://www.apache.org/licenses/LICENSE-2.0
borlanic 0:02dd72d1d465 9 *
borlanic 0:02dd72d1d465 10 * Unless required by applicable law or agreed to in writing, software
borlanic 0:02dd72d1d465 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
borlanic 0:02dd72d1d465 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
borlanic 0:02dd72d1d465 13 * See the License for the specific language governing permissions and
borlanic 0:02dd72d1d465 14 * limitations under the License.
borlanic 0:02dd72d1d465 15 */
borlanic 0:02dd72d1d465 16 #include "mbed.h"
borlanic 0:02dd72d1d465 17 #include "ns_types.h"
borlanic 0:02dd72d1d465 18 #include <string.h>
borlanic 0:02dd72d1d465 19 #include "common_functions.h"
borlanic 0:02dd72d1d465 20 #include "randLIB.h"
borlanic 0:02dd72d1d465 21 #include "platform/arm_hal_interrupt.h"
borlanic 0:02dd72d1d465 22 #include "platform/arm_hal_phy.h"
borlanic 0:02dd72d1d465 23 #include "NanostackRfPhyNcs36510.h"
borlanic 0:02dd72d1d465 24
borlanic 0:02dd72d1d465 25 extern "C" {
borlanic 0:02dd72d1d465 26 #include "TARGET_NCS36510/memory_map.h"
borlanic 0:02dd72d1d465 27 #include "TARGET_NCS36510/clock.h"
borlanic 0:02dd72d1d465 28 #include "TARGET_NCS36510/ticker.h"
borlanic 0:02dd72d1d465 29 #include "TARGET_NCS36510/rfAna.h"
borlanic 0:02dd72d1d465 30 }
borlanic 0:02dd72d1d465 31
borlanic 0:02dd72d1d465 32 #define RF_THREAD_STACK_SIZE 1024
borlanic 0:02dd72d1d465 33
borlanic 0:02dd72d1d465 34 #define SIGNAL_COUNT_RADIO 1
borlanic 0:02dd72d1d465 35
borlanic 0:02dd72d1d465 36 static void rf_thread_loop();
borlanic 0:02dd72d1d465 37 Thread rf_thread(osPriorityRealtime, RF_THREAD_STACK_SIZE);
borlanic 0:02dd72d1d465 38
borlanic 0:02dd72d1d465 39 #define PHY_MTU_SIZE 127
borlanic 0:02dd72d1d465 40 #define CRC_LENGTH 0
borlanic 0:02dd72d1d465 41 #define PHY_HEADER_LENGTH 0
borlanic 0:02dd72d1d465 42
borlanic 0:02dd72d1d465 43 /**
borlanic 0:02dd72d1d465 44 * MAC status code bit definition
borlanic 0:02dd72d1d465 45 */
borlanic 0:02dd72d1d465 46 #define MAC_STATUS_SUCCESS (0x0) /**< Success */
borlanic 0:02dd72d1d465 47 #define MAC_STATUS_TIMEOUT (0x1) /**< Time out */
borlanic 0:02dd72d1d465 48 #define MAC_STATUS_BUSY (0x2) /**< Channel Busy */
borlanic 0:02dd72d1d465 49 #define MAC_STATUS_CRCFAIL (0x3) /**< CRC Failed */
borlanic 0:02dd72d1d465 50 #define MAC_STATUS_NOACK (0x5) /**< No ACK */
borlanic 0:02dd72d1d465 51 #define MAC_STATUS_UNLOCK (0x6) /**< PLL unlocked */
borlanic 0:02dd72d1d465 52 #define MAC_STATUS_BADSTART (0x7) /**< Bad Start */
borlanic 0:02dd72d1d465 53 #define MAC_STATUS_RXACK_PENDING (0x8) /**< ACK frame was received with the Pending bit set */
borlanic 0:02dd72d1d465 54 #define MAC_STATUS_TXACK_PENDING (0x9) /**< ACK frame was transmitted with the Pending bit set */
borlanic 0:02dd72d1d465 55 #define MAC_STATUS_FAIL_FILTER (0xA) /**< One or more frame filtering tests has failed */
borlanic 0:02dd72d1d465 56 #define MAC_STATUS_PANID_CONFLICT (0xB) /**< A PANID conflict has been detected */
borlanic 0:02dd72d1d465 57 #define MAC_STATUS_NOTCOMPLETE (0xF) /**< Not complete */
borlanic 0:02dd72d1d465 58
borlanic 0:02dd72d1d465 59 /**
borlanic 0:02dd72d1d465 60 * MAC sequence modes
borlanic 0:02dd72d1d465 61 */
borlanic 0:02dd72d1d465 62 #define MAC_SEQUENCE_NOP (0x0) /**< NOP */
borlanic 0:02dd72d1d465 63 #define MAC_SEQUENCE_RX (0x3) /**< RX */
borlanic 0:02dd72d1d465 64 #define MAC_SEQUENCE_TX (0x4) /**< TX */
borlanic 0:02dd72d1d465 65 #define MAC_SEQUENCE_ED (0x5) /**< ED */
borlanic 0:02dd72d1d465 66 #define MAC_SEQUENCE_CCA (0x6) /**< CCA */
borlanic 0:02dd72d1d465 67
borlanic 0:02dd72d1d465 68 /**
borlanic 0:02dd72d1d465 69 * MAC Interrupt enable / disable
borlanic 0:02dd72d1d465 70 */
borlanic 0:02dd72d1d465 71 #define MAC_IRQ_NONE (0x0) /**< No IRQ */
borlanic 0:02dd72d1d465 72 #define MAC_IRQ_COMPLETE (0x1) /**< Event-complete IRQ */
borlanic 0:02dd72d1d465 73 #define MAC_IRQ_EVENT_STARTED (0x2) /**< Event-started IRQ */
borlanic 0:02dd72d1d465 74 #define MAC_IRQ_DATA (0x4) /**< Data-arrived IRQ */
borlanic 0:02dd72d1d465 75 #define MAC_IRQ_FRAME_STARTED (0x8) /**< Frame-started IRQ */
borlanic 0:02dd72d1d465 76 #define MAC_IRQ_PACKET_FAIL (0x10) /**< Failed-packet IRQ */
borlanic 0:02dd72d1d465 77 #define MAC_IRQ_FRAME_MATCH (0x20) /**< Frame-match IRQ (indicating matching process is done) */
borlanic 0:02dd72d1d465 78 #define MAC_IRQ_ALL (0x3F) /**< All IRQs */
borlanic 0:02dd72d1d465 79
borlanic 0:02dd72d1d465 80 #define MAC_RSSI_TO_ED 0
borlanic 0:02dd72d1d465 81 #define MAC_RSSI_TO_LQI 1
borlanic 0:02dd72d1d465 82
borlanic 0:02dd72d1d465 83 #define MAC_RF_TRX_OFF 0
borlanic 0:02dd72d1d465 84 #define MAC_RF_RX_ON 1
borlanic 0:02dd72d1d465 85 #define MAC_RF_TX_ON 2
borlanic 0:02dd72d1d465 86 #define MAC_RF_ED_SCAN 3
borlanic 0:02dd72d1d465 87
borlanic 0:02dd72d1d465 88 static int8_t rf_radio_driver_id = -1;
borlanic 0:02dd72d1d465 89
borlanic 0:02dd72d1d465 90 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
borlanic 0:02dd72d1d465 91 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol);
borlanic 0:02dd72d1d465 92 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr);
borlanic 0:02dd72d1d465 93 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr);
borlanic 0:02dd72d1d465 94
borlanic 0:02dd72d1d465 95 static void rf_mac_hw_init(void);
borlanic 0:02dd72d1d465 96 static void rf_mac_timers_disable_trig_event(void);
borlanic 0:02dd72d1d465 97 static void rf_mac_reset(void);
borlanic 0:02dd72d1d465 98 static void rf_mac_rx_enable(void);
borlanic 0:02dd72d1d465 99 static void rf_mac_ed_state_enable(void);
borlanic 0:02dd72d1d465 100 static uint8_t rf_mac_convert_rssi(uint8_t scale);
borlanic 0:02dd72d1d465 101 static int8_t rf_mac_get_rssi(void);
borlanic 0:02dd72d1d465 102 static void rf_mac_set_rx_on_state(bool enable);
borlanic 0:02dd72d1d465 103 static void rf_mac_write(uint8_t *data_ptr, uint8_t length);
borlanic 0:02dd72d1d465 104
borlanic 0:02dd72d1d465 105 static void rf_mac_set_pending(uint8_t status);
borlanic 0:02dd72d1d465 106
borlanic 0:02dd72d1d465 107 static void rf_mac_set_shortAddress(uint8_t* valueAddress);
borlanic 0:02dd72d1d465 108 static void rf_mac_set_panId(uint8_t* valueAddress);
borlanic 0:02dd72d1d465 109 static void rf_mac_set_mac64(const uint8_t* valueAddress);
borlanic 0:02dd72d1d465 110
borlanic 0:02dd72d1d465 111 static void rf_mac_get_mac64(uint8_t* valueAddress);
borlanic 0:02dd72d1d465 112
borlanic 0:02dd72d1d465 113 static int8_t set_channel(uint8_t channel);
borlanic 0:02dd72d1d465 114 static void handle_IRQ_events(void);
borlanic 0:02dd72d1d465 115
borlanic 0:02dd72d1d465 116 static uint8_t MAC64_addr_default[8] = {1, 2, 3, 4, 5, 6, 7, 8};
borlanic 0:02dd72d1d465 117 static uint8_t MAC64_addr[8];
borlanic 0:02dd72d1d465 118
borlanic 0:02dd72d1d465 119 static uint8_t rf_mac_state = MAC_RF_TRX_OFF;
borlanic 0:02dd72d1d465 120 static bool rf_ack_pending_state = false;
borlanic 0:02dd72d1d465 121 static bool rf_mac_ack_requsted = false;
borlanic 0:02dd72d1d465 122 static uint8_t rf_mac_handle;
borlanic 0:02dd72d1d465 123 volatile uint8_t rf_ed_value = 0;
borlanic 0:02dd72d1d465 124
borlanic 0:02dd72d1d465 125 static NanostackRfPhyNcs36510 *rf = NULL;
borlanic 0:02dd72d1d465 126
borlanic 0:02dd72d1d465 127 #define MAC_PACKET_SIZE 127 //MAX MAC payload is 127 bytes
borlanic 0:02dd72d1d465 128 static uint8_t PHYPAYLOAD[MAC_PACKET_SIZE];
borlanic 0:02dd72d1d465 129
borlanic 0:02dd72d1d465 130 //TODO: verify these values
borlanic 0:02dd72d1d465 131 const phy_rf_channel_configuration_s phy_2_4ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
borlanic 0:02dd72d1d465 132
borlanic 0:02dd72d1d465 133 const phy_device_channel_page_s phy_channel_pages[] = {
borlanic 0:02dd72d1d465 134 {CHANNEL_PAGE_0, &phy_2_4ghz},
borlanic 0:02dd72d1d465 135 {CHANNEL_PAGE_0, NULL}
borlanic 0:02dd72d1d465 136 };
borlanic 0:02dd72d1d465 137
borlanic 0:02dd72d1d465 138 static phy_device_driver_s device_driver = {
borlanic 0:02dd72d1d465 139 PHY_LINK_15_4_2_4GHZ_TYPE,
borlanic 0:02dd72d1d465 140 PHY_LAYER_PAYLOAD_DATA_FLOW,
borlanic 0:02dd72d1d465 141 MAC64_addr,
borlanic 0:02dd72d1d465 142 PHY_MTU_SIZE,
borlanic 0:02dd72d1d465 143 (char*)"ON Semi ncs36510",
borlanic 0:02dd72d1d465 144 CRC_LENGTH,
borlanic 0:02dd72d1d465 145 PHY_HEADER_LENGTH,
borlanic 0:02dd72d1d465 146 &rf_interface_state_control,
borlanic 0:02dd72d1d465 147 &rf_start_cca,
borlanic 0:02dd72d1d465 148 &rf_address_write,
borlanic 0:02dd72d1d465 149 &rf_extension,
borlanic 0:02dd72d1d465 150 phy_channel_pages,
borlanic 0:02dd72d1d465 151 NULL,
borlanic 0:02dd72d1d465 152 NULL,
borlanic 0:02dd72d1d465 153 NULL,
borlanic 0:02dd72d1d465 154 NULL
borlanic 0:02dd72d1d465 155 };
borlanic 0:02dd72d1d465 156
borlanic 0:02dd72d1d465 157 static void rf_thread_loop()
borlanic 0:02dd72d1d465 158 {
borlanic 0:02dd72d1d465 159 for (;;) {
borlanic 0:02dd72d1d465 160 osEvent event = rf_thread.signal_wait(0);
borlanic 0:02dd72d1d465 161 if (event.status != osEventSignal) {
borlanic 0:02dd72d1d465 162 continue;
borlanic 0:02dd72d1d465 163 }
borlanic 0:02dd72d1d465 164
borlanic 0:02dd72d1d465 165 platform_enter_critical();
borlanic 0:02dd72d1d465 166 if (event.value.signals & SIGNAL_COUNT_RADIO) {
borlanic 0:02dd72d1d465 167 handle_IRQ_events();
borlanic 0:02dd72d1d465 168 }
borlanic 0:02dd72d1d465 169 platform_exit_critical();
borlanic 0:02dd72d1d465 170 NVIC_ClearPendingIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 171 NVIC_EnableIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 172 }
borlanic 0:02dd72d1d465 173 }
borlanic 0:02dd72d1d465 174
borlanic 0:02dd72d1d465 175 static int8_t rf_device_register(void)
borlanic 0:02dd72d1d465 176 {
borlanic 0:02dd72d1d465 177 if( rf_radio_driver_id < 0 ) {
borlanic 0:02dd72d1d465 178
borlanic 0:02dd72d1d465 179 rf_mac_hw_init();
borlanic 0:02dd72d1d465 180 /**
borlanic 0:02dd72d1d465 181 * Read factory stored Mac address to RAM
borlanic 0:02dd72d1d465 182 */
borlanic 0:02dd72d1d465 183 common_write_32_bit(MACHWREG->LONG_ADDRESS_HIGH, MAC64_addr);
borlanic 0:02dd72d1d465 184 common_write_32_bit(MACHWREG->LONG_ADDRESS_LOW, MAC64_addr + 4);
borlanic 0:02dd72d1d465 185 rf_radio_driver_id = arm_net_phy_register(&device_driver);
borlanic 0:02dd72d1d465 186 }
borlanic 0:02dd72d1d465 187
borlanic 0:02dd72d1d465 188 return rf_radio_driver_id;
borlanic 0:02dd72d1d465 189 }
borlanic 0:02dd72d1d465 190
borlanic 0:02dd72d1d465 191 static void rf_device_unregister(void)
borlanic 0:02dd72d1d465 192 {
borlanic 0:02dd72d1d465 193 arm_net_phy_unregister(rf_radio_driver_id);
borlanic 0:02dd72d1d465 194 }
borlanic 0:02dd72d1d465 195
borlanic 0:02dd72d1d465 196 void rf_read_mac_address(uint8_t *address_ptr)
borlanic 0:02dd72d1d465 197 {
borlanic 0:02dd72d1d465 198 platform_enter_critical();
borlanic 0:02dd72d1d465 199 rf_mac_get_mac64(address_ptr);
borlanic 0:02dd72d1d465 200 platform_exit_critical();
borlanic 0:02dd72d1d465 201 }
borlanic 0:02dd72d1d465 202
borlanic 0:02dd72d1d465 203 int8_t rf_read_random(void)
borlanic 0:02dd72d1d465 204 {
borlanic 0:02dd72d1d465 205 //TODO: Read random from randomizer
borlanic 0:02dd72d1d465 206 return 1;
borlanic 0:02dd72d1d465 207 }
borlanic 0:02dd72d1d465 208
borlanic 0:02dd72d1d465 209 void rf_set_mac_address(const uint8_t *ptr)
borlanic 0:02dd72d1d465 210 {
borlanic 0:02dd72d1d465 211 platform_enter_critical();
borlanic 0:02dd72d1d465 212 rf_mac_set_mac64(ptr);
borlanic 0:02dd72d1d465 213 platform_exit_critical();
borlanic 0:02dd72d1d465 214 }
borlanic 0:02dd72d1d465 215
borlanic 0:02dd72d1d465 216 static void rf_mac_set_pending(uint8_t status) {
borlanic 0:02dd72d1d465 217
borlanic 0:02dd72d1d465 218 if (status) {
borlanic 0:02dd72d1d465 219 MACHWREG->OPTIONS.BITS.TFPO = 0;
borlanic 0:02dd72d1d465 220 MACHWREG->OPTIONS.BITS.TFP = 1;
borlanic 0:02dd72d1d465 221 rf_ack_pending_state = true;
borlanic 0:02dd72d1d465 222 } else {
borlanic 0:02dd72d1d465 223 rf_ack_pending_state = false;
borlanic 0:02dd72d1d465 224 MACHWREG->OPTIONS.BITS.TFPO = 0;
borlanic 0:02dd72d1d465 225 MACHWREG->OPTIONS.BITS.TFP = 0;
borlanic 0:02dd72d1d465 226 }
borlanic 0:02dd72d1d465 227 }
borlanic 0:02dd72d1d465 228
borlanic 0:02dd72d1d465 229 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
borlanic 0:02dd72d1d465 230 {
borlanic 0:02dd72d1d465 231 platform_enter_critical();
borlanic 0:02dd72d1d465 232 switch(new_state){
borlanic 0:02dd72d1d465 233 case PHY_INTERFACE_RESET: { /**< Reset PHY driver and set to idle. */
borlanic 0:02dd72d1d465 234 rf_mac_set_rx_on_state(false);
borlanic 0:02dd72d1d465 235 break;
borlanic 0:02dd72d1d465 236 }
borlanic 0:02dd72d1d465 237 case PHY_INTERFACE_DOWN: { /**< Disable PHY interface driver (RF radio disable). */
borlanic 0:02dd72d1d465 238 rf_mac_set_rx_on_state(false);
borlanic 0:02dd72d1d465 239 break;
borlanic 0:02dd72d1d465 240 }
borlanic 0:02dd72d1d465 241 case PHY_INTERFACE_UP: { /**< Enable PHY interface driver (RF radio receiver ON). */
borlanic 0:02dd72d1d465 242 set_channel(rf_channel);
borlanic 0:02dd72d1d465 243 rf_mac_set_rx_on_state(true);
borlanic 0:02dd72d1d465 244
borlanic 0:02dd72d1d465 245 break;
borlanic 0:02dd72d1d465 246 }
borlanic 0:02dd72d1d465 247 case PHY_INTERFACE_RX_ENERGY_STATE: { /**< Enable wirless interface ED scan mode. */
borlanic 0:02dd72d1d465 248 rf_ed_value = 0;
borlanic 0:02dd72d1d465 249 set_channel(rf_channel);
borlanic 0:02dd72d1d465 250 rf_mac_set_rx_on_state(false);
borlanic 0:02dd72d1d465 251 rf_mac_ed_state_enable();
borlanic 0:02dd72d1d465 252 break;
borlanic 0:02dd72d1d465 253 }
borlanic 0:02dd72d1d465 254 case PHY_INTERFACE_SNIFFER_STATE: {
borlanic 0:02dd72d1d465 255 set_channel(rf_channel);
borlanic 0:02dd72d1d465 256 rf_mac_set_rx_on_state(true);
borlanic 0:02dd72d1d465 257 break;
borlanic 0:02dd72d1d465 258 }
borlanic 0:02dd72d1d465 259 }
borlanic 0:02dd72d1d465 260 platform_exit_critical();
borlanic 0:02dd72d1d465 261 return 0;
borlanic 0:02dd72d1d465 262 }
borlanic 0:02dd72d1d465 263
borlanic 0:02dd72d1d465 264 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol)
borlanic 0:02dd72d1d465 265 {
borlanic 0:02dd72d1d465 266 platform_enter_critical();
borlanic 0:02dd72d1d465 267 (void)data_protocol;
borlanic 0:02dd72d1d465 268 rf_mac_handle = tx_handle;
borlanic 0:02dd72d1d465 269 rf_mac_write(data_ptr, data_length);
borlanic 0:02dd72d1d465 270 platform_exit_critical();
borlanic 0:02dd72d1d465 271 return 0;
borlanic 0:02dd72d1d465 272 }
borlanic 0:02dd72d1d465 273
borlanic 0:02dd72d1d465 274 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
borlanic 0:02dd72d1d465 275 {
borlanic 0:02dd72d1d465 276 int ret_value = 0;
borlanic 0:02dd72d1d465 277 platform_enter_critical();
borlanic 0:02dd72d1d465 278 switch (address_type) {
borlanic 0:02dd72d1d465 279 case PHY_MAC_64BIT: /**< RF/PLC link layer address. */
borlanic 0:02dd72d1d465 280 rf_mac_set_mac64(address_ptr);
borlanic 0:02dd72d1d465 281 break;
borlanic 0:02dd72d1d465 282 case PHY_MAC_16BIT: /**< RF interface short address. */
borlanic 0:02dd72d1d465 283 rf_mac_set_shortAddress(address_ptr);
borlanic 0:02dd72d1d465 284 break;
borlanic 0:02dd72d1d465 285 case PHY_MAC_PANID: /**< RF interface 16-Bit PAN-ID. */
borlanic 0:02dd72d1d465 286 rf_mac_set_panId(address_ptr);
borlanic 0:02dd72d1d465 287 break;
borlanic 0:02dd72d1d465 288 default:
borlanic 0:02dd72d1d465 289 ret_value = -1;
borlanic 0:02dd72d1d465 290 }
borlanic 0:02dd72d1d465 291 platform_exit_critical();
borlanic 0:02dd72d1d465 292
borlanic 0:02dd72d1d465 293 return ret_value;
borlanic 0:02dd72d1d465 294 }
borlanic 0:02dd72d1d465 295
borlanic 0:02dd72d1d465 296 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
borlanic 0:02dd72d1d465 297 {
borlanic 0:02dd72d1d465 298 int ret_value = 0;
borlanic 0:02dd72d1d465 299 platform_enter_critical();
borlanic 0:02dd72d1d465 300 switch (extension_type) {
borlanic 0:02dd72d1d465 301 case PHY_EXTENSION_CTRL_PENDING_BIT: /**< Control MAC pending bit for indirect data. */
borlanic 0:02dd72d1d465 302 rf_mac_set_pending(*data_ptr);
borlanic 0:02dd72d1d465 303 break;
borlanic 0:02dd72d1d465 304 case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS: /**< Read status if the last ACK is still pending. */
borlanic 0:02dd72d1d465 305 *data_ptr = rf_ack_pending_state;
borlanic 0:02dd72d1d465 306 break;
borlanic 0:02dd72d1d465 307 case PHY_EXTENSION_SET_CHANNEL: /**< Net library channel set. */
borlanic 0:02dd72d1d465 308 return set_channel(*data_ptr);
borlanic 0:02dd72d1d465 309
borlanic 0:02dd72d1d465 310 case PHY_EXTENSION_READ_CHANNEL_ENERGY: /**< RF interface ED scan energy read. */
borlanic 0:02dd72d1d465 311 *data_ptr = rf_ed_value;
borlanic 0:02dd72d1d465 312 break;
borlanic 0:02dd72d1d465 313
borlanic 0:02dd72d1d465 314 case PHY_EXTENSION_READ_LINK_STATUS: /**< Net library could read link status. */
borlanic 0:02dd72d1d465 315 case PHY_EXTENSION_CONVERT_SIGNAL_INFO: /**< Convert signal info. */
borlanic 0:02dd72d1d465 316 default:
borlanic 0:02dd72d1d465 317 ret_value = -1;
borlanic 0:02dd72d1d465 318 }
borlanic 0:02dd72d1d465 319 platform_exit_critical();
borlanic 0:02dd72d1d465 320
borlanic 0:02dd72d1d465 321 return ret_value;
borlanic 0:02dd72d1d465 322 }
borlanic 0:02dd72d1d465 323
borlanic 0:02dd72d1d465 324 static int8_t set_channel(uint8_t channel)
borlanic 0:02dd72d1d465 325 {
borlanic 0:02dd72d1d465 326 if( channel > 10 && channel < 27 ){
borlanic 0:02dd72d1d465 327 fRfAnaIoctl(SET_RF_CHANNEL, &channel);
borlanic 0:02dd72d1d465 328 return 0;
borlanic 0:02dd72d1d465 329 }
borlanic 0:02dd72d1d465 330 return -1;
borlanic 0:02dd72d1d465 331 }
borlanic 0:02dd72d1d465 332
borlanic 0:02dd72d1d465 333
borlanic 0:02dd72d1d465 334 /**
borlanic 0:02dd72d1d465 335 * SET MAC 16 address to Register
borlanic 0:02dd72d1d465 336 */
borlanic 0:02dd72d1d465 337 static void rf_mac_set_shortAddress(uint8_t* valueAddress) {
borlanic 0:02dd72d1d465 338 MACHWREG->SHORT_ADDRESS = common_read_16_bit(valueAddress);
borlanic 0:02dd72d1d465 339 }
borlanic 0:02dd72d1d465 340
borlanic 0:02dd72d1d465 341 /**
borlanic 0:02dd72d1d465 342 * SET PAN-ID to Register
borlanic 0:02dd72d1d465 343 */
borlanic 0:02dd72d1d465 344 static void rf_mac_set_panId(uint8_t* valueAddress) {
borlanic 0:02dd72d1d465 345 MACHWREG->PANID = common_read_16_bit(valueAddress);
borlanic 0:02dd72d1d465 346 }
borlanic 0:02dd72d1d465 347
borlanic 0:02dd72d1d465 348 /**
borlanic 0:02dd72d1d465 349 * SET MAC64 address to register
borlanic 0:02dd72d1d465 350 */
borlanic 0:02dd72d1d465 351 static void rf_mac_set_mac64(const uint8_t* valueAddress) {
borlanic 0:02dd72d1d465 352 MACHWREG->LONG_ADDRESS_HIGH = common_read_32_bit(valueAddress);
borlanic 0:02dd72d1d465 353 valueAddress += 4;
borlanic 0:02dd72d1d465 354 MACHWREG->LONG_ADDRESS_LOW = common_read_32_bit(valueAddress);
borlanic 0:02dd72d1d465 355 }
borlanic 0:02dd72d1d465 356
borlanic 0:02dd72d1d465 357 static void rf_mac_get_mac64(uint8_t* valueAddress) {
borlanic 0:02dd72d1d465 358 valueAddress = common_write_32_bit(MACHWREG->LONG_ADDRESS_HIGH, valueAddress);
borlanic 0:02dd72d1d465 359 common_write_32_bit(MACHWREG->LONG_ADDRESS_LOW, valueAddress);
borlanic 0:02dd72d1d465 360 }
borlanic 0:02dd72d1d465 361
borlanic 0:02dd72d1d465 362 static void rf_mac_timers_disable_trig_event(void) {
borlanic 0:02dd72d1d465 363 MACHWREG->TIMER_DISABLE.BITS.START = true;
borlanic 0:02dd72d1d465 364 MACHWREG->TIMER_DISABLE.BITS.STOP = true;
borlanic 0:02dd72d1d465 365 MACHWREG->SEQ_OPTIONS.BITS.NOW = true;
borlanic 0:02dd72d1d465 366 }
borlanic 0:02dd72d1d465 367
borlanic 0:02dd72d1d465 368 /**
borlanic 0:02dd72d1d465 369 * Call this only One time
borlanic 0:02dd72d1d465 370 */
borlanic 0:02dd72d1d465 371 static void rf_mac_hw_init(void) {
borlanic 0:02dd72d1d465 372 uint32_t periphClockfrequency;
borlanic 0:02dd72d1d465 373 uint8_t lutIndex;
borlanic 0:02dd72d1d465 374 volatile uint8_t *pMatchReg = MACMATCHREG;
borlanic 0:02dd72d1d465 375
borlanic 0:02dd72d1d465 376 /** Initialize rf peripheral */
borlanic 0:02dd72d1d465 377 fRfAnaInit();
borlanic 0:02dd72d1d465 378
borlanic 0:02dd72d1d465 379 /** Enable mac clock */
borlanic 0:02dd72d1d465 380 CLOCK_ENABLE(CLOCK_MACHW);
borlanic 0:02dd72d1d465 381
borlanic 0:02dd72d1d465 382 /** Disable and clear IRQs */
borlanic 0:02dd72d1d465 383 MACHWREG->MASK_IRQ.WORD = MAC_IRQ_NONE;
borlanic 0:02dd72d1d465 384 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_ALL;
borlanic 0:02dd72d1d465 385 NVIC_ClearPendingIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 386
borlanic 0:02dd72d1d465 387 /** Set sequence options */
borlanic 0:02dd72d1d465 388 MACHWREG->SEQ_OPTIONS.BITS.MODE = 0x1;
borlanic 0:02dd72d1d465 389 MACHWREG->SEQ_OPTIONS.BITS.NOACK = false;
borlanic 0:02dd72d1d465 390 MACHWREG->SEQ_OPTIONS.BITS.NOW = true;
borlanic 0:02dd72d1d465 391 MACHWREG->SEQ_OPTIONS.BITS.PRM = false;
borlanic 0:02dd72d1d465 392
borlanic 0:02dd72d1d465 393 MACHWREG->SEQ_OPTIONS.BITS.ACK_ENABLE = false;
borlanic 0:02dd72d1d465 394 MACHWREG->SEQ_OPTIONS.BITS.RES_ENABLE = false;
borlanic 0:02dd72d1d465 395
borlanic 0:02dd72d1d465 396 /** Set clocks */
borlanic 0:02dd72d1d465 397 periphClockfrequency = fClockGetPeriphClockfrequency();
borlanic 0:02dd72d1d465 398 MACHWREG->DIVIDER.BITS.BIT_CLOCK_DIVIDER = (periphClockfrequency / 250000) - 1;
borlanic 0:02dd72d1d465 399 MACHWREG->DIVIDER.BITS.SYSTEM_CLOCK_DIVIDER = (periphClockfrequency / 1000000) - 1;
borlanic 0:02dd72d1d465 400 MACHWREG->DIVIDER.BITS.CHIP_CLOCK_DIVIDER = (periphClockfrequency / 2000000) - 1;
borlanic 0:02dd72d1d465 401
borlanic 0:02dd72d1d465 402 /** Set miscellaneous */
borlanic 0:02dd72d1d465 403
borlanic 0:02dd72d1d465 404 /** This value should be tuned tuned to hit tx sw ack window (192us-204us) */
borlanic 0:02dd72d1d465 405 MACHWREG->RX_TX_WARMPUPS.BITS.TRANSMIT_WARMPUP = 0x16;
borlanic 0:02dd72d1d465 406
borlanic 0:02dd72d1d465 407 /** This value is selected to allocate 1 bit margin between tr sw ack and tx sw ack */
borlanic 0:02dd72d1d465 408 MACHWREG->RX_TX_WARMPUPS.BITS.RECEIVE_WARMPUP = 0x15;
borlanic 0:02dd72d1d465 409
borlanic 0:02dd72d1d465 410 MACHWREG->TXCCA = 0x30;
borlanic 0:02dd72d1d465 411 MACHWREG->CCA.BITS.CCA_LENGTH = 0x43;
borlanic 0:02dd72d1d465 412 MACHWREG->CCA.BITS.CCA_DELAY = 0x26;
borlanic 0:02dd72d1d465 413 MACHWREG->TX_ACK_DELAY = 0x21;
borlanic 0:02dd72d1d465 414 MACHWREG->ACK_STOP.BITS.RXACK_END = 0xA8;
borlanic 0:02dd72d1d465 415 MACHWREG->SLOT_OFFSET.WORD = 0x00070007;
borlanic 0:02dd72d1d465 416 MACHWREG->TX_LENGTH.BITS.TX_PRE_CHIPS = 0x6;
borlanic 0:02dd72d1d465 417 MACHWREG->TX_FLUSH = 0x00000008; /** Transmit flush duration (8 x 4us = 32 us) */
borlanic 0:02dd72d1d465 418
borlanic 0:02dd72d1d465 419 /** Set AGC */
borlanic 0:02dd72d1d465 420 MACHWREG->AGC_CONTROL.WORD = 0x00000007; // AGC enabled / AGC freeze enabled / Preamble detection mode
borlanic 0:02dd72d1d465 421
borlanic 0:02dd72d1d465 422 /** It is unclear from design specification if a 16MHz is mandatory for AGC operations or only to build
borlanic 0:02dd72d1d465 423 * settle and measurements delays */
borlanic 0:02dd72d1d465 424 if (periphClockfrequency == CPU_CLOCK_ROOT_HZ) {
borlanic 0:02dd72d1d465 425 /** AGC time unit = T(PCLK) x 2 = 16MHz period */
borlanic 0:02dd72d1d465 426 MACHWREG->AGC_SETTINGS.BITS.DIVIDER = 1;
borlanic 0:02dd72d1d465 427 /** settle delay = (value + 1) * AGC time unit = 500ns targeted */
borlanic 0:02dd72d1d465 428 MACHWREG->AGC_SETTINGS.BITS.SETTLE_DELAY = 7;
borlanic 0:02dd72d1d465 429 /** measurement delay = (value + 1) * AGC time unit = 1500ns targeted */
borlanic 0:02dd72d1d465 430 MACHWREG->AGC_SETTINGS.BITS.MEASURE_DELAY = 0x17;
borlanic 0:02dd72d1d465 431 } else {
borlanic 0:02dd72d1d465 432 /** AGC time unit is T(PCLK) */
borlanic 0:02dd72d1d465 433 MACHWREG->AGC_SETTINGS.BITS.DIVIDER = 0;
borlanic 0:02dd72d1d465 434 /** settle delay = (value + 1) * AGC time unit = 500ns targeted */
borlanic 0:02dd72d1d465 435 MACHWREG->AGC_SETTINGS.BITS.SETTLE_DELAY = (16 / CPU_CLOCK_DIV) - 1;
borlanic 0:02dd72d1d465 436 /** measurement delay = (value + 1) * AGC time unit = 1500ns targeted */
borlanic 0:02dd72d1d465 437 MACHWREG->AGC_SETTINGS.BITS.MEASURE_DELAY = (48 / CPU_CLOCK_DIV) - 1;
borlanic 0:02dd72d1d465 438 }
borlanic 0:02dd72d1d465 439
borlanic 0:02dd72d1d465 440 /** AGC high threshold: 3dB below the clipping level */
borlanic 0:02dd72d1d465 441 MACHWREG->AGC_SETTINGS.BITS.HIGH_THRESHOLD = 1;
borlanic 0:02dd72d1d465 442 /** AGC low threshold: 9dB below the high threshold */
borlanic 0:02dd72d1d465 443 MACHWREG->AGC_SETTINGS.BITS.LOW_THRESHOLD = 0;
borlanic 0:02dd72d1d465 444
borlanic 0:02dd72d1d465 445 /** Set Demodulator */
borlanic 0:02dd72d1d465 446 DMDREG->DMD_CONTROL0.WORD = 0x7FFF0004;
borlanic 0:02dd72d1d465 447 MACHWREG->SHORT_ADDRESS = 0x0000ffff;
borlanic 0:02dd72d1d465 448 MACHWREG->PANID = 0x0000ffff;
borlanic 0:02dd72d1d465 449
borlanic 0:02dd72d1d465 450 /** Reset macHw peripheral */
borlanic 0:02dd72d1d465 451 rf_mac_reset();
borlanic 0:02dd72d1d465 452
borlanic 0:02dd72d1d465 453 /** Initialise LUT RAM */
borlanic 0:02dd72d1d465 454 for (lutIndex=0;lutIndex<96;lutIndex++) {
borlanic 0:02dd72d1d465 455 *(pMatchReg + lutIndex) = 0xFF;
borlanic 0:02dd72d1d465 456 }
borlanic 0:02dd72d1d465 457 osStatus status = rf_thread.start(mbed::callback(rf_thread_loop));
borlanic 0:02dd72d1d465 458 MBED_ASSERT(status == osOK);
borlanic 0:02dd72d1d465 459
borlanic 0:02dd72d1d465 460 /** Clear and enable MAC IRQ at task level, when scheduler is on. */
borlanic 0:02dd72d1d465 461 NVIC_ClearPendingIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 462 NVIC_EnableIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 463 }
borlanic 0:02dd72d1d465 464
borlanic 0:02dd72d1d465 465 static void rf_mac_set_rx_on_state(bool enable) {
borlanic 0:02dd72d1d465 466 /** Abort ongoing sequence */
borlanic 0:02dd72d1d465 467 rf_mac_reset();
borlanic 0:02dd72d1d465 468 /** Start rx if requested */
borlanic 0:02dd72d1d465 469 if (enable) {
borlanic 0:02dd72d1d465 470 /** Set requested filtering */
borlanic 0:02dd72d1d465 471 MACHWREG->SEQ_OPTIONS.BITS.BEA_ENABLE = true;
borlanic 0:02dd72d1d465 472 MACHWREG->SEQ_OPTIONS.BITS.DATA_ENABLE = true;
borlanic 0:02dd72d1d465 473 MACHWREG->SEQ_OPTIONS.BITS.CMD_ENABLE = true;
borlanic 0:02dd72d1d465 474 /** Start receiver */
borlanic 0:02dd72d1d465 475 rf_mac_rx_enable();
borlanic 0:02dd72d1d465 476 }
borlanic 0:02dd72d1d465 477 }
borlanic 0:02dd72d1d465 478
borlanic 0:02dd72d1d465 479 static void rf_mac_write(uint8_t *data_ptr, uint8_t length) {
borlanic 0:02dd72d1d465 480 uint8_t i;
borlanic 0:02dd72d1d465 481 volatile uint8_t *txRam = MACTXREG;
borlanic 0:02dd72d1d465 482
borlanic 0:02dd72d1d465 483 /* This is not make sense but... */
borlanic 0:02dd72d1d465 484 rf_mac_reset();
borlanic 0:02dd72d1d465 485
borlanic 0:02dd72d1d465 486 /* Set tx state */
borlanic 0:02dd72d1d465 487 rf_mac_state = MAC_RF_TX_ON;
borlanic 0:02dd72d1d465 488
borlanic 0:02dd72d1d465 489 if (*data_ptr & 0x20) {
borlanic 0:02dd72d1d465 490 MACHWREG->SEQ_OPTIONS.BITS.ACK_ENABLE = true;
borlanic 0:02dd72d1d465 491 } else {
borlanic 0:02dd72d1d465 492 MACHWREG->SEQ_OPTIONS.BITS.ACK_ENABLE = false;
borlanic 0:02dd72d1d465 493 }
borlanic 0:02dd72d1d465 494 rf_mac_ack_requsted = MACHWREG->SEQ_OPTIONS.BITS.ACK_ENABLE;
borlanic 0:02dd72d1d465 495
borlanic 0:02dd72d1d465 496 /* Set data length */
borlanic 0:02dd72d1d465 497 MACHWREG->TX_LENGTH.BITS.TXLENGTH = length + 2;
borlanic 0:02dd72d1d465 498
borlanic 0:02dd72d1d465 499 *txRam++ = *data_ptr++;
borlanic 0:02dd72d1d465 500 *txRam++ = *data_ptr++;
borlanic 0:02dd72d1d465 501 *txRam++ = *data_ptr;
borlanic 0:02dd72d1d465 502 //RR: Retransmission for Data request should have same DSN
borlanic 0:02dd72d1d465 503 MACHWREG->TX_SEQ_NUMBER = *data_ptr++;
borlanic 0:02dd72d1d465 504 for (i = 3; i < length; i++) {
borlanic 0:02dd72d1d465 505 *txRam++ = *data_ptr++;
borlanic 0:02dd72d1d465 506 }
borlanic 0:02dd72d1d465 507
borlanic 0:02dd72d1d465 508 MACHWREG->SEQ_OPTIONS.BITS.PRM = 0;
borlanic 0:02dd72d1d465 509
borlanic 0:02dd72d1d465 510 MACHWREG->SEQ_OPTIONS.BITS.NOACK = false;
borlanic 0:02dd72d1d465 511
borlanic 0:02dd72d1d465 512 rf_mac_state = MAC_RF_TX_ON;
borlanic 0:02dd72d1d465 513
borlanic 0:02dd72d1d465 514 /* Start CCA immediately */
borlanic 0:02dd72d1d465 515 rf_mac_timers_disable_trig_event();
borlanic 0:02dd72d1d465 516
borlanic 0:02dd72d1d465 517 while (MACHWREG->TIMER != 0x0) MACHWREG->TIMER = 0x0; // HW ISSUE: field is not set immediately
borlanic 0:02dd72d1d465 518
borlanic 0:02dd72d1d465 519 /* Enable tx irq, reset protocol timer and start tx sequence */
borlanic 0:02dd72d1d465 520 MACHWREG->MASK_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 521 MACHWREG->SEQUENCER = MAC_SEQUENCE_TX;
borlanic 0:02dd72d1d465 522
borlanic 0:02dd72d1d465 523 }
borlanic 0:02dd72d1d465 524
borlanic 0:02dd72d1d465 525
borlanic 0:02dd72d1d465 526 static void rf_mac_ed_state_enable(void) {
borlanic 0:02dd72d1d465 527 rf_mac_state = MAC_RF_ED_SCAN;
borlanic 0:02dd72d1d465 528 /** Enable Energy scan state and event complete interrupt */
borlanic 0:02dd72d1d465 529 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 530 MACHWREG->MASK_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 531 MACHWREG->SEQUENCER = MAC_SEQUENCE_ED;
borlanic 0:02dd72d1d465 532 }
borlanic 0:02dd72d1d465 533
borlanic 0:02dd72d1d465 534
borlanic 0:02dd72d1d465 535 static void rf_mac_rx_enable(void) {
borlanic 0:02dd72d1d465 536 rf_mac_state = MAC_RF_RX_ON;
borlanic 0:02dd72d1d465 537
borlanic 0:02dd72d1d465 538 /** Enable rx irqs, reset protocol timer and start rx sequence */
borlanic 0:02dd72d1d465 539 MACHWREG->MASK_IRQ.WORD = MAC_IRQ_COMPLETE | MAC_IRQ_FRAME_MATCH | MAC_IRQ_DATA;
borlanic 0:02dd72d1d465 540 while (MACHWREG->TIMER != 0x0) MACHWREG->TIMER = 0x0; // HW ISSUE: field is not set immediately
borlanic 0:02dd72d1d465 541 MACHWREG->SEQUENCER = MAC_SEQUENCE_RX;
borlanic 0:02dd72d1d465 542 return;
borlanic 0:02dd72d1d465 543 }
borlanic 0:02dd72d1d465 544
borlanic 0:02dd72d1d465 545
borlanic 0:02dd72d1d465 546 static void rf_mac_reset(void) {
borlanic 0:02dd72d1d465 547 uint32_t macHwDivider;
borlanic 0:02dd72d1d465 548
borlanic 0:02dd72d1d465 549 /** Recommended abort sequence (with synchronous reset) */
borlanic 0:02dd72d1d465 550
borlanic 0:02dd72d1d465 551 /** 1. Set clock divider to minimum (for single clock response) */
borlanic 0:02dd72d1d465 552 macHwDivider = MACHWREG->DIVIDER.WORD;
borlanic 0:02dd72d1d465 553 /** (to cope with protocol timer and ed REVB silicon issues it is required
borlanic 0:02dd72d1d465 554 * to set protocol timer to 1 and not to 0 as suggested in macHw specification) */
borlanic 0:02dd72d1d465 555 /* PK !!!MAC_REVD RevB -> RevD change list Item 25: protocol timer */
borlanic 0:02dd72d1d465 556 MACHWREG->DIVIDER.WORD = 1;
borlanic 0:02dd72d1d465 557
borlanic 0:02dd72d1d465 558 /** 2. Disable interrupts */
borlanic 0:02dd72d1d465 559 MACHWREG->MASK_IRQ.WORD = MAC_IRQ_NONE;
borlanic 0:02dd72d1d465 560
borlanic 0:02dd72d1d465 561 /** 3. Clear interrupts */
borlanic 0:02dd72d1d465 562 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_ALL;
borlanic 0:02dd72d1d465 563
borlanic 0:02dd72d1d465 564 NVIC_ClearPendingIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 565
borlanic 0:02dd72d1d465 566 /** 4. Clear previous sequence type (write no-op sequence) */
borlanic 0:02dd72d1d465 567 MACHWREG->SEQUENCER = MAC_SEQUENCE_NOP;
borlanic 0:02dd72d1d465 568
borlanic 0:02dd72d1d465 569 /** 5. Move all MAC state machines to idle state (on, with synchronous reset) */
borlanic 0:02dd72d1d465 570 MACHWREG->CONTROL.WORD = 0x00000003;
borlanic 0:02dd72d1d465 571
borlanic 0:02dd72d1d465 572 /** 6. Release reset */
borlanic 0:02dd72d1d465 573 MACHWREG->CONTROL.WORD = 0x00000002;
borlanic 0:02dd72d1d465 574
borlanic 0:02dd72d1d465 575 /** 7. Disable start, stop timers */
borlanic 0:02dd72d1d465 576 rf_mac_timers_disable_trig_event();
borlanic 0:02dd72d1d465 577
borlanic 0:02dd72d1d465 578 /** 8. Return clock dividers to original value */
borlanic 0:02dd72d1d465 579 MACHWREG->DIVIDER.WORD = macHwDivider;
borlanic 0:02dd72d1d465 580
borlanic 0:02dd72d1d465 581 MACHWREG->SEQ_OPTIONS.BITS.BEA_ENABLE = False;
borlanic 0:02dd72d1d465 582 MACHWREG->SEQ_OPTIONS.BITS.DATA_ENABLE = False;
borlanic 0:02dd72d1d465 583 MACHWREG->SEQ_OPTIONS.BITS.CMD_ENABLE = False;
borlanic 0:02dd72d1d465 584
borlanic 0:02dd72d1d465 585 /** Set MAC_HW state */
borlanic 0:02dd72d1d465 586 rf_mac_state = MAC_RF_TRX_OFF;
borlanic 0:02dd72d1d465 587 }
borlanic 0:02dd72d1d465 588
borlanic 0:02dd72d1d465 589 static uint8_t rf_mac_convert_rssi(uint8_t scale) {
borlanic 0:02dd72d1d465 590 /* RSSI Value: The value is captured at the end of packet reception or at the end of ED/CCA
borlanic 0:02dd72d1d465 591 * measurements and is interpreted in dBm as follows:
borlanic 0:02dd72d1d465 592 * 1xxxxxxx: not used
borlanic 0:02dd72d1d465 593 * 01111111: 0 dBm (or above)
borlanic 0:02dd72d1d465 594 * 01111110: -1 dBm
borlanic 0:02dd72d1d465 595 * 01111101: -2 dBm
borlanic 0:02dd72d1d465 596 * -
borlanic 0:02dd72d1d465 597 * 00000010: -125 dBm
borlanic 0:02dd72d1d465 598 * 00000001: -126 dBm
borlanic 0:02dd72d1d465 599 * 00000000: -127 dBm (or below)
borlanic 0:02dd72d1d465 600 */
borlanic 0:02dd72d1d465 601
borlanic 0:02dd72d1d465 602 /* check rssi is well in spec range */
borlanic 0:02dd72d1d465 603 //ASSERT ((DMDREG->DMD_STATUS.BITS.RSSI_VALUE & 0x80) != 0x80);
borlanic 0:02dd72d1d465 604 if (DMDREG->DMD_STATUS.BITS.RSSI_VALUE & 0x80) {
borlanic 0:02dd72d1d465 605 return 0;
borlanic 0:02dd72d1d465 606 }
borlanic 0:02dd72d1d465 607
borlanic 0:02dd72d1d465 608 /* convert rssi in sign char: translate 01111111 into 0 and following alike, make negative */
borlanic 0:02dd72d1d465 609 signed char rssi_value = -1 * (DMDREG->DMD_STATUS.BITS.RSSI_VALUE ^ 0x7F);
borlanic 0:02dd72d1d465 610
borlanic 0:02dd72d1d465 611 if (scale == MAC_RSSI_TO_ED ) {
borlanic 0:02dd72d1d465 612 /**
borlanic 0:02dd72d1d465 613 * For ED (IEEE 6.9.7) "The ED result shall be reported to the MLME as an 8 bit integer
borlanic 0:02dd72d1d465 614 * ranging from 0x00 to 0xff. The minimum ED value (zero) shall indicate received power less than 10 dB
borlanic 0:02dd72d1d465 615 * above the specified receiver sensitivity (see 6.5.3.3 and 6.6.3.4), and the range of received power spanned by
borlanic 0:02dd72d1d465 616 * the ED values shall be at least 40 dB. Within this range, the mapping from the received power in decibels to
borlanic 0:02dd72d1d465 617 * ED value shall be linear with an accuracy of � 6 dB."
borlanic 0:02dd72d1d465 618 * (-85dBm receiver sensitivity will be targeted => zero ED value is associated to -75dBm)
borlanic 0:02dd72d1d465 619 * (span will have 51dBm range from 0x0=-75dBm to 0xff=-24dBm)
borlanic 0:02dd72d1d465 620 */
borlanic 0:02dd72d1d465 621
borlanic 0:02dd72d1d465 622 /* Clip maximal and minimal rssi value reported by ED */
borlanic 0:02dd72d1d465 623 if (rssi_value < -75) rssi_value = -75;
borlanic 0:02dd72d1d465 624 if (rssi_value > -24) rssi_value = -24;
borlanic 0:02dd72d1d465 625
borlanic 0:02dd72d1d465 626 /* scale the span -75dBm --> -24dBm to 0x00 --> 0xFF
borlanic 0:02dd72d1d465 627 * Attention: This scaling implies that granularity of the result is changing from 1dBm per unit to 1/5 dBm per unit
borlanic 0:02dd72d1d465 628 * 0xFF: -24 dBm (or above)
borlanic 0:02dd72d1d465 629 * 0xFE - 0xFB: (impossible code)
borlanic 0:02dd72d1d465 630 * 0xFA: -25 dBm
borlanic 0:02dd72d1d465 631 * 0xF9 - 0xF6: (impossible code)
borlanic 0:02dd72d1d465 632 * 0xF5: -26 dBm
borlanic 0:02dd72d1d465 633 * ...
borlanic 0:02dd72d1d465 634 * 0x05: -74 dBm
borlanic 0:02dd72d1d465 635 * 0x01 - 0x04: (impossible code)
borlanic 0:02dd72d1d465 636 * 0x00: -75 dBm (or below)
borlanic 0:02dd72d1d465 637 */
borlanic 0:02dd72d1d465 638 return (rssi_value + 75) * 5;
borlanic 0:02dd72d1d465 639 } else {
borlanic 0:02dd72d1d465 640
borlanic 0:02dd72d1d465 641 /**
borlanic 0:02dd72d1d465 642 * For LQI: (IEEE 6.9.7) "The LQI measurement shall be performed for each received packet, and the result shall be reported to the
borlanic 0:02dd72d1d465 643 * MAC sublayer using PD-DATA.indication (see 6.2.1.3) as an integer ranging from 0x00 to 0xff. The
borlanic 0:02dd72d1d465 644 * minimum and maximum LQI values (0x00 and 0xff) should be associated with the lowest and highest
borlanic 0:02dd72d1d465 645 * quality compliant signals detectable by the receiver, and LQI values in between should be uniformly
borlanic 0:02dd72d1d465 646 * distributed between these two limits. At least eight unique values of LQI shall be used."
borlanic 0:02dd72d1d465 647 * (-85dBm sensitivity will be targeted => zero LQI value will be associated to -85dBm)
borlanic 0:02dd72d1d465 648 * (span will have 64dBm range from 0x0=-85dBm to 0xff=-21dBm)
borlanic 0:02dd72d1d465 649 */
borlanic 0:02dd72d1d465 650
borlanic 0:02dd72d1d465 651 /* Clip maximal and minimal rssi value reported by LQI */
borlanic 0:02dd72d1d465 652 if (rssi_value < -85) rssi_value = -85;
borlanic 0:02dd72d1d465 653 if (rssi_value > -21) rssi_value = -21;
borlanic 0:02dd72d1d465 654
borlanic 0:02dd72d1d465 655 /* scale the span -85dBm --> -21,25dBm to 0x00 --> 0xFF
borlanic 0:02dd72d1d465 656 * Attention: This scaling implies that granularity of the result is changing from 1dBm per unit to 1/4 dBm per unit
borlanic 0:02dd72d1d465 657 * 0xFF: -21,25 dBm (or above)
borlanic 0:02dd72d1d465 658 * 0xFE: (impossible code)
borlanic 0:02dd72d1d465 659 * 0xFD: (impossible code)
borlanic 0:02dd72d1d465 660 * 0xFC: -22 dBm
borlanic 0:02dd72d1d465 661 * 0xFB: (impossible code)
borlanic 0:02dd72d1d465 662 * 0xFA: (impossible code)
borlanic 0:02dd72d1d465 663 * 0xF9: (impossible code)
borlanic 0:02dd72d1d465 664 * 0xF8: -23 dBm
borlanic 0:02dd72d1d465 665 * ...
borlanic 0:02dd72d1d465 666 * 0x05: (impossible code)
borlanic 0:02dd72d1d465 667 * 0x04: - 84dBm
borlanic 0:02dd72d1d465 668 * 0x03: (impossible code)
borlanic 0:02dd72d1d465 669 * 0x02: (impossible code)
borlanic 0:02dd72d1d465 670 * 0x01: (impossible code)
borlanic 0:02dd72d1d465 671 * 0x00: - 85dBm
borlanic 0:02dd72d1d465 672 */
borlanic 0:02dd72d1d465 673 if (rssi_value == -21)
borlanic 0:02dd72d1d465 674 return ((rssi_value + 85) * 4) - 1;
borlanic 0:02dd72d1d465 675 else
borlanic 0:02dd72d1d465 676 return (rssi_value + 85) * 4;
borlanic 0:02dd72d1d465 677 }
borlanic 0:02dd72d1d465 678 }
borlanic 0:02dd72d1d465 679
borlanic 0:02dd72d1d465 680 static int8_t rf_mac_get_rssi(void) {
borlanic 0:02dd72d1d465 681 int8_t rssi_value = -1 * (DMDREG->DMD_STATUS.BITS.RSSI_VALUE ^ 0x7F);
borlanic 0:02dd72d1d465 682 return rssi_value;
borlanic 0:02dd72d1d465 683 }
borlanic 0:02dd72d1d465 684
borlanic 0:02dd72d1d465 685 static void rf_rx_ed_scan_interrupt() {
borlanic 0:02dd72d1d465 686 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 687 if (MACHWREG->STATUS.BITS.CODE == MAC_STATUS_SUCCESS) {
borlanic 0:02dd72d1d465 688 uint8_t ed = rf_mac_convert_rssi(MAC_RSSI_TO_ED);
borlanic 0:02dd72d1d465 689 if (ed) {
borlanic 0:02dd72d1d465 690 if (ed > rf_ed_value) {
borlanic 0:02dd72d1d465 691 rf_ed_value = ed;
borlanic 0:02dd72d1d465 692 }
borlanic 0:02dd72d1d465 693 }
borlanic 0:02dd72d1d465 694 }
borlanic 0:02dd72d1d465 695
borlanic 0:02dd72d1d465 696 MACHWREG->MASK_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 697 MACHWREG->SEQUENCER = MAC_SEQUENCE_ED;
borlanic 0:02dd72d1d465 698 }
borlanic 0:02dd72d1d465 699
borlanic 0:02dd72d1d465 700 static void rf_rx_interrupt() {
borlanic 0:02dd72d1d465 701 // Frame match is used for association and data frames
borlanic 0:02dd72d1d465 702 uint8_t seqSts = MACHWREG->STATUS.BITS.CODE;
borlanic 0:02dd72d1d465 703
borlanic 0:02dd72d1d465 704 if (MACHWREG->IRQ_STATUS.BITS.FM) {
borlanic 0:02dd72d1d465 705 if (!rf_ack_pending_state) {
borlanic 0:02dd72d1d465 706 MACHWREG->OPTIONS.BITS.TFP = 0;
borlanic 0:02dd72d1d465 707 MACHWREG->OPTIONS.BITS.TFPO = 1;
borlanic 0:02dd72d1d465 708 } else {
borlanic 0:02dd72d1d465 709 MACHWREG->OPTIONS.BITS.TFP = 1;
borlanic 0:02dd72d1d465 710 MACHWREG->OPTIONS.BITS.TFPO = 1;
borlanic 0:02dd72d1d465 711 }
borlanic 0:02dd72d1d465 712
borlanic 0:02dd72d1d465 713 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_FRAME_MATCH;
borlanic 0:02dd72d1d465 714 return;
borlanic 0:02dd72d1d465 715 }
borlanic 0:02dd72d1d465 716
borlanic 0:02dd72d1d465 717 /** RR: Process the event complete IRQ */
borlanic 0:02dd72d1d465 718 if (MACHWREG->IRQ_STATUS.BITS.EC || MACHWREG->IRQ_STATUS.BITS.DATA) {
borlanic 0:02dd72d1d465 719 /** Clear the event */
borlanic 0:02dd72d1d465 720 if (MACHWREG->IRQ_STATUS.BITS.EC) {
borlanic 0:02dd72d1d465 721 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 722 }
borlanic 0:02dd72d1d465 723
borlanic 0:02dd72d1d465 724 if (MACHWREG->IRQ_STATUS.BITS.DATA) {
borlanic 0:02dd72d1d465 725 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_DATA;
borlanic 0:02dd72d1d465 726 }
borlanic 0:02dd72d1d465 727
borlanic 0:02dd72d1d465 728 /** Build frame (containing received frame or timeout) */
borlanic 0:02dd72d1d465 729
borlanic 0:02dd72d1d465 730 volatile uint8_t *rxRam = MACRXREG;
borlanic 0:02dd72d1d465 731 uint8_t length;
borlanic 0:02dd72d1d465 732 int8_t rssi;
borlanic 0:02dd72d1d465 733 uint8_t lqi;
borlanic 0:02dd72d1d465 734
borlanic 0:02dd72d1d465 735 /** Return directly in case of timeout */
borlanic 0:02dd72d1d465 736 if (seqSts == MAC_STATUS_TIMEOUT) {
borlanic 0:02dd72d1d465 737 /* Initialize frame status */
borlanic 0:02dd72d1d465 738 return;
borlanic 0:02dd72d1d465 739 }
borlanic 0:02dd72d1d465 740
borlanic 0:02dd72d1d465 741 length = *rxRam++;
borlanic 0:02dd72d1d465 742 if (length < 5){
borlanic 0:02dd72d1d465 743 rf_mac_rx_enable();
borlanic 0:02dd72d1d465 744 return;
borlanic 0:02dd72d1d465 745 }
borlanic 0:02dd72d1d465 746 length -= 2; //Cut CRC OUT
borlanic 0:02dd72d1d465 747
borlanic 0:02dd72d1d465 748 /* Initialize frame status */
borlanic 0:02dd72d1d465 749 for (uint8_t i=0; i < length; i++) {
borlanic 0:02dd72d1d465 750 PHYPAYLOAD[i] = *rxRam++;
borlanic 0:02dd72d1d465 751 }
borlanic 0:02dd72d1d465 752
borlanic 0:02dd72d1d465 753 lqi = rf_mac_convert_rssi(MAC_RSSI_TO_LQI);
borlanic 0:02dd72d1d465 754 rssi = rf_mac_get_rssi();
borlanic 0:02dd72d1d465 755 rf_mac_rx_enable();
borlanic 0:02dd72d1d465 756 //Call ARM API
borlanic 0:02dd72d1d465 757 if( device_driver.phy_rx_cb ){
borlanic 0:02dd72d1d465 758 device_driver.phy_rx_cb(PHYPAYLOAD, length, lqi, rssi, rf_radio_driver_id);
borlanic 0:02dd72d1d465 759 }
borlanic 0:02dd72d1d465 760 }
borlanic 0:02dd72d1d465 761 }
borlanic 0:02dd72d1d465 762
borlanic 0:02dd72d1d465 763 static void rf_mac_tx_interrupt(void)
borlanic 0:02dd72d1d465 764 {
borlanic 0:02dd72d1d465 765 phy_link_tx_status_e status;
borlanic 0:02dd72d1d465 766 /** Clear the event complete IRQ */
borlanic 0:02dd72d1d465 767 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 768 /* This IRQ means that Data Request is complete; check the status */
borlanic 0:02dd72d1d465 769 uint8_t sharedSeqSts = MACHWREG->STATUS.BITS.CODE;
borlanic 0:02dd72d1d465 770
borlanic 0:02dd72d1d465 771 rf_mac_set_rx_on_state(true);
borlanic 0:02dd72d1d465 772
borlanic 0:02dd72d1d465 773 switch (sharedSeqSts) {
borlanic 0:02dd72d1d465 774 case MAC_STATUS_SUCCESS: /* Positive */
borlanic 0:02dd72d1d465 775 //SET Success
borlanic 0:02dd72d1d465 776 if (rf_mac_ack_requsted) {
borlanic 0:02dd72d1d465 777 status = PHY_LINK_TX_DONE;
borlanic 0:02dd72d1d465 778 } else {
borlanic 0:02dd72d1d465 779 status = PHY_LINK_TX_SUCCESS;
borlanic 0:02dd72d1d465 780 }
borlanic 0:02dd72d1d465 781 break;
borlanic 0:02dd72d1d465 782
borlanic 0:02dd72d1d465 783 case MAC_STATUS_RXACK_PENDING: /* Positive for broadcast */
borlanic 0:02dd72d1d465 784 status = PHY_LINK_TX_DONE_PENDING;
borlanic 0:02dd72d1d465 785 break;
borlanic 0:02dd72d1d465 786
borlanic 0:02dd72d1d465 787
borlanic 0:02dd72d1d465 788 case MAC_STATUS_BUSY:
borlanic 0:02dd72d1d465 789 status = PHY_LINK_CCA_FAIL;
borlanic 0:02dd72d1d465 790 break;
borlanic 0:02dd72d1d465 791
borlanic 0:02dd72d1d465 792 default:
borlanic 0:02dd72d1d465 793 status = PHY_LINK_TX_FAIL;
borlanic 0:02dd72d1d465 794 break;
borlanic 0:02dd72d1d465 795 }
borlanic 0:02dd72d1d465 796 rf_mac_ack_requsted = false;
borlanic 0:02dd72d1d465 797 //Call RX TX complete
borlanic 0:02dd72d1d465 798 if( device_driver.phy_tx_done_cb ) {
borlanic 0:02dd72d1d465 799 device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, status, 1, 1);
borlanic 0:02dd72d1d465 800 }
borlanic 0:02dd72d1d465 801 }
borlanic 0:02dd72d1d465 802
borlanic 0:02dd72d1d465 803 /**
borlanic 0:02dd72d1d465 804 * RF MAC Interrupt handler
borlanic 0:02dd72d1d465 805 */
borlanic 0:02dd72d1d465 806 extern "C" void fIrqMacHwHandler(void)
borlanic 0:02dd72d1d465 807 {
borlanic 0:02dd72d1d465 808 NVIC_DisableIRQ(MacHw_IRQn);
borlanic 0:02dd72d1d465 809 rf_thread.signal_set(SIGNAL_COUNT_RADIO);
borlanic 0:02dd72d1d465 810 }
borlanic 0:02dd72d1d465 811
borlanic 0:02dd72d1d465 812 static void handle_IRQ_events(void)
borlanic 0:02dd72d1d465 813 {
borlanic 0:02dd72d1d465 814 /** Set MAC timers to initial state */
borlanic 0:02dd72d1d465 815 MACHWREG->TIMER_ENABLE.BITS.START = false;
borlanic 0:02dd72d1d465 816 MACHWREG->TIMER_ENABLE.BITS.STOP = false;
borlanic 0:02dd72d1d465 817 MACHWREG->TIMER_DISABLE.BITS.START = false;
borlanic 0:02dd72d1d465 818 MACHWREG->TIMER_DISABLE.BITS.STOP = false;
borlanic 0:02dd72d1d465 819
borlanic 0:02dd72d1d465 820 /** Disarm start/stop timers, disable and clear irq (event_complete) */
borlanic 0:02dd72d1d465 821 rf_mac_timers_disable_trig_event();
borlanic 0:02dd72d1d465 822 /** REVD changes to sequence tracking register. Sequence register can be used instead of rf_mac_state */
borlanic 0:02dd72d1d465 823
borlanic 0:02dd72d1d465 824 if (rf_mac_state == MAC_RF_RX_ON) {
borlanic 0:02dd72d1d465 825 rf_rx_interrupt();
borlanic 0:02dd72d1d465 826 } else if(rf_mac_state == MAC_RF_TX_ON) {
borlanic 0:02dd72d1d465 827 rf_mac_tx_interrupt();
borlanic 0:02dd72d1d465 828 } else if (rf_mac_state == MAC_RF_ED_SCAN){
borlanic 0:02dd72d1d465 829 rf_rx_ed_scan_interrupt();
borlanic 0:02dd72d1d465 830 } else {
borlanic 0:02dd72d1d465 831 /** Clear the event complete IRQ */
borlanic 0:02dd72d1d465 832 MACHWREG->CLEAR_IRQ.WORD = MAC_IRQ_COMPLETE;
borlanic 0:02dd72d1d465 833 uint8_t sharedSeqSts = MACHWREG->STATUS.BITS.CODE;
borlanic 0:02dd72d1d465 834 }
borlanic 0:02dd72d1d465 835 }
borlanic 0:02dd72d1d465 836
borlanic 0:02dd72d1d465 837 NanostackRfPhyNcs36510::NanostackRfPhyNcs36510()
borlanic 0:02dd72d1d465 838 {
borlanic 0:02dd72d1d465 839 memcpy(MAC64_addr, MAC64_addr_default, sizeof(MAC64_addr));
borlanic 0:02dd72d1d465 840 }
borlanic 0:02dd72d1d465 841
borlanic 0:02dd72d1d465 842 NanostackRfPhyNcs36510::~NanostackRfPhyNcs36510()
borlanic 0:02dd72d1d465 843 {
borlanic 0:02dd72d1d465 844 // Do nothing
borlanic 0:02dd72d1d465 845 }
borlanic 0:02dd72d1d465 846
borlanic 0:02dd72d1d465 847 int8_t NanostackRfPhyNcs36510::rf_register()
borlanic 0:02dd72d1d465 848 {
borlanic 0:02dd72d1d465 849 platform_enter_critical();
borlanic 0:02dd72d1d465 850
borlanic 0:02dd72d1d465 851 if (rf != NULL) {
borlanic 0:02dd72d1d465 852 platform_exit_critical();
borlanic 0:02dd72d1d465 853 error("Multiple registrations of NanostackRfPhyNcs36510 not supported");
borlanic 0:02dd72d1d465 854 return -1;
borlanic 0:02dd72d1d465 855 }
borlanic 0:02dd72d1d465 856
borlanic 0:02dd72d1d465 857 rf = this;
borlanic 0:02dd72d1d465 858 int8_t radio_id = rf_device_register();
borlanic 0:02dd72d1d465 859 if (radio_id < 0) {
borlanic 0:02dd72d1d465 860 rf = NULL;
borlanic 0:02dd72d1d465 861 }
borlanic 0:02dd72d1d465 862
borlanic 0:02dd72d1d465 863 platform_exit_critical();
borlanic 0:02dd72d1d465 864 return radio_id;
borlanic 0:02dd72d1d465 865 }
borlanic 0:02dd72d1d465 866
borlanic 0:02dd72d1d465 867 void NanostackRfPhyNcs36510::rf_unregister()
borlanic 0:02dd72d1d465 868 {
borlanic 0:02dd72d1d465 869 platform_enter_critical();
borlanic 0:02dd72d1d465 870
borlanic 0:02dd72d1d465 871 if (rf != this) {
borlanic 0:02dd72d1d465 872 platform_exit_critical();
borlanic 0:02dd72d1d465 873 return;
borlanic 0:02dd72d1d465 874 }
borlanic 0:02dd72d1d465 875
borlanic 0:02dd72d1d465 876 rf_device_unregister();
borlanic 0:02dd72d1d465 877 rf = NULL;
borlanic 0:02dd72d1d465 878
borlanic 0:02dd72d1d465 879 platform_exit_critical();
borlanic 0:02dd72d1d465 880 }
borlanic 0:02dd72d1d465 881
borlanic 0:02dd72d1d465 882 void NanostackRfPhyNcs36510::get_mac_address(uint8_t *mac)
borlanic 0:02dd72d1d465 883 {
borlanic 0:02dd72d1d465 884 platform_enter_critical();
borlanic 0:02dd72d1d465 885
borlanic 0:02dd72d1d465 886 memcpy((void*)mac, (void*)MAC64_addr, sizeof(MAC64_addr));
borlanic 0:02dd72d1d465 887
borlanic 0:02dd72d1d465 888 platform_exit_critical();
borlanic 0:02dd72d1d465 889 }
borlanic 0:02dd72d1d465 890
borlanic 0:02dd72d1d465 891 void NanostackRfPhyNcs36510::set_mac_address(uint8_t *mac)
borlanic 0:02dd72d1d465 892 {
borlanic 0:02dd72d1d465 893 platform_enter_critical();
borlanic 0:02dd72d1d465 894
borlanic 0:02dd72d1d465 895 if (NULL != rf) {
borlanic 0:02dd72d1d465 896 error("NanostackRfPhyNcs36510 cannot change mac address when running");
borlanic 0:02dd72d1d465 897 platform_exit_critical();
borlanic 0:02dd72d1d465 898 return;
borlanic 0:02dd72d1d465 899 }
borlanic 0:02dd72d1d465 900 memcpy((void*)MAC64_addr, (void*)mac, sizeof(MAC64_addr));
borlanic 0:02dd72d1d465 901
borlanic 0:02dd72d1d465 902 platform_exit_critical();
borlanic 0:02dd72d1d465 903 }
borlanic 0:02dd72d1d465 904