Version of easy-connect with the u-blox cellular platforms C027 and C030 added.

Dependents:   HelloMQTT

Committer:
RobMeades
Date:
Fri Nov 03 13:01:23 2017 +0000
Revision:
6:304d3ba87a01
Parent:
0:19aa55d66228
Add comment concerning N2XX baud rate.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
group-ublox 0:19aa55d66228 1 #if MBED_CONF_RTOS_PRESENT
group-ublox 0:19aa55d66228 2
group-ublox 0:19aa55d66228 3 #include "NanostackRfPhySpirit1.h"
group-ublox 0:19aa55d66228 4 #include "SimpleSpirit1.h"
group-ublox 0:19aa55d66228 5 #include "nanostack/platform/arm_hal_phy.h"
group-ublox 0:19aa55d66228 6 #include "platform/arm_hal_interrupt.h"
group-ublox 0:19aa55d66228 7
group-ublox 0:19aa55d66228 8 #include "mbed_trace.h"
group-ublox 0:19aa55d66228 9 #define TRACE_GROUP "SPIRIT"
group-ublox 0:19aa55d66228 10
group-ublox 0:19aa55d66228 11 /* Define beyond macro if you want to perform heavy debug tracing (includes tracing in IRQ context) */
group-ublox 0:19aa55d66228 12 // #define HEAVY_TRACING
group-ublox 0:19aa55d66228 13
group-ublox 0:19aa55d66228 14 static phy_device_driver_s device_driver;
group-ublox 0:19aa55d66228 15 static int8_t rf_radio_driver_id = -1;
group-ublox 0:19aa55d66228 16
group-ublox 0:19aa55d66228 17 const phy_rf_channel_configuration_s phy_subghz = {868000000, 1000000, 250000, 11, M_GFSK};
group-ublox 0:19aa55d66228 18
group-ublox 0:19aa55d66228 19 static phy_device_channel_page_s phy_channel_pages[] = {
group-ublox 0:19aa55d66228 20 {CHANNEL_PAGE_2, &phy_subghz},
group-ublox 0:19aa55d66228 21 {CHANNEL_PAGE_0, NULL}
group-ublox 0:19aa55d66228 22 };
group-ublox 0:19aa55d66228 23
group-ublox 0:19aa55d66228 24 static uint8_t tx_sequence = 0xff;
group-ublox 0:19aa55d66228 25 static uint8_t mac_tx_handle = 0;
group-ublox 0:19aa55d66228 26
group-ublox 0:19aa55d66228 27 static SimpleSpirit1 *rf_device = NULL;
group-ublox 0:19aa55d66228 28 static uint8_t rf_rx_buf[MAX_PACKET_LEN];
group-ublox 0:19aa55d66228 29
group-ublox 0:19aa55d66228 30 static uint16_t stored_short_adr;
group-ublox 0:19aa55d66228 31 static uint16_t stored_pan_id;
group-ublox 0:19aa55d66228 32 static uint8_t stored_mac_address[8] = MBED_CONF_SPIRIT1_MAC_ADDRESS;
group-ublox 0:19aa55d66228 33
group-ublox 0:19aa55d66228 34 #define RF_SIG_ACK_NEEDED (1<<0)
group-ublox 0:19aa55d66228 35 #define RF_SIG_CB_TX_DONE (1<<1)
group-ublox 0:19aa55d66228 36 #define RF_SIG_CB_RX_RCVD (1<<2)
group-ublox 0:19aa55d66228 37 static Thread rf_ack_sender(osPriorityRealtime);
group-ublox 0:19aa55d66228 38 static volatile uint8_t rf_rx_sequence;
group-ublox 0:19aa55d66228 39 static volatile bool rf_ack_sent = false;
group-ublox 0:19aa55d66228 40 static volatile bool expecting_ack = false;
group-ublox 0:19aa55d66228 41 static volatile bool need_ack = false;
group-ublox 0:19aa55d66228 42
group-ublox 0:19aa55d66228 43 /* MAC frame helper macros */
group-ublox 0:19aa55d66228 44 #define MAC_FCF_FRAME_TYPE_MASK 0x0007
group-ublox 0:19aa55d66228 45 #define MAC_FCF_FRAME_TYPE_SHIFT 0
group-ublox 0:19aa55d66228 46 #define MAC_FCF_SECURITY_BIT_MASK 0x0008
group-ublox 0:19aa55d66228 47 #define MAC_FCF_SECURITY_BIT_SHIFT 3
group-ublox 0:19aa55d66228 48 #define MAC_FCF_PENDING_BIT_MASK 0x0010
group-ublox 0:19aa55d66228 49 #define MAC_FCF_PENDING_BIT_SHIFT 4
group-ublox 0:19aa55d66228 50 #define MAC_FCF_ACK_REQ_BIT_MASK 0x0020
group-ublox 0:19aa55d66228 51 #define MAC_FCF_ACK_REQ_BIT_SHIFT 5
group-ublox 0:19aa55d66228 52 #define MAC_FCF_INTRA_PANID_MASK 0x0040
group-ublox 0:19aa55d66228 53 #define MAC_FCF_INTRA_PANID_SHIFT 6
group-ublox 0:19aa55d66228 54 #define MAC_FCF_DST_ADDR_MASK 0x0c00
group-ublox 0:19aa55d66228 55 #define MAC_FCF_DST_ADDR_SHIFT 10
group-ublox 0:19aa55d66228 56 #define MAC_FCF_VERSION_MASK 0x3000
group-ublox 0:19aa55d66228 57 #define MAC_FCF_VERSION_SHIFT 12
group-ublox 0:19aa55d66228 58 #define MAC_FCF_SRC_ADDR_MASK 0xc000
group-ublox 0:19aa55d66228 59 #define MAC_FCF_SRC_ADDR_SHIFT 14
group-ublox 0:19aa55d66228 60
group-ublox 0:19aa55d66228 61 /* MAC supported frame types */
group-ublox 0:19aa55d66228 62 #define FC_BEACON_FRAME 0x00
group-ublox 0:19aa55d66228 63 #define FC_DATA_FRAME 0x01
group-ublox 0:19aa55d66228 64 #define FC_ACK_FRAME 0x02
group-ublox 0:19aa55d66228 65 #define FC_CMD_FRAME 0x03
group-ublox 0:19aa55d66228 66
group-ublox 0:19aa55d66228 67 static inline void rf_if_lock(void)
group-ublox 0:19aa55d66228 68 {
group-ublox 0:19aa55d66228 69 platform_enter_critical();
group-ublox 0:19aa55d66228 70 }
group-ublox 0:19aa55d66228 71
group-ublox 0:19aa55d66228 72 static inline void rf_if_unlock(void)
group-ublox 0:19aa55d66228 73 {
group-ublox 0:19aa55d66228 74 platform_exit_critical();
group-ublox 0:19aa55d66228 75 }
group-ublox 0:19aa55d66228 76
group-ublox 0:19aa55d66228 77 static inline uint16_t rf_read_16_bit(uint8_t *data_ptr) { // little-endian
group-ublox 0:19aa55d66228 78 uint16_t ret;
group-ublox 0:19aa55d66228 79
group-ublox 0:19aa55d66228 80 ret = ((uint16_t)data_ptr[0]) + (((uint16_t)data_ptr[1]) << 8);
group-ublox 0:19aa55d66228 81 return ret;
group-ublox 0:19aa55d66228 82 }
group-ublox 0:19aa55d66228 83
group-ublox 0:19aa55d66228 84 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 85 static inline void rf_send_signal(int32_t signal) {
group-ublox 0:19aa55d66228 86 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 87 tr_info("%s (%d): %d", __func__, __LINE__, signal);
group-ublox 0:19aa55d66228 88 #endif
group-ublox 0:19aa55d66228 89 rf_ack_sender.signal_set(signal);
group-ublox 0:19aa55d66228 90 }
group-ublox 0:19aa55d66228 91
group-ublox 0:19aa55d66228 92 static volatile phy_link_tx_status_e phy_status;
group-ublox 0:19aa55d66228 93 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 94 static void rf_handle_ack(uint8_t seq_number)
group-ublox 0:19aa55d66228 95 {
group-ublox 0:19aa55d66228 96 /*Received ACK sequence must be equal with transmitted packet sequence*/
group-ublox 0:19aa55d66228 97 if(tx_sequence == seq_number)
group-ublox 0:19aa55d66228 98 {
group-ublox 0:19aa55d66228 99 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 100 tr_info("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 101 #endif
group-ublox 0:19aa55d66228 102
group-ublox 0:19aa55d66228 103 /*Call PHY TX Done API*/
group-ublox 0:19aa55d66228 104 if(device_driver.phy_tx_done_cb){
group-ublox 0:19aa55d66228 105 phy_status = PHY_LINK_TX_DONE;
group-ublox 0:19aa55d66228 106 rf_send_signal(RF_SIG_CB_TX_DONE);
group-ublox 0:19aa55d66228 107 }
group-ublox 0:19aa55d66228 108 } else {
group-ublox 0:19aa55d66228 109 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 110 tr_info("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 111 #endif
group-ublox 0:19aa55d66228 112
group-ublox 0:19aa55d66228 113 /*Call PHY TX Done API*/
group-ublox 0:19aa55d66228 114 if(device_driver.phy_tx_done_cb){
group-ublox 0:19aa55d66228 115 phy_status = PHY_LINK_TX_FAIL;
group-ublox 0:19aa55d66228 116 rf_send_signal(RF_SIG_CB_TX_DONE);
group-ublox 0:19aa55d66228 117 }
group-ublox 0:19aa55d66228 118 }
group-ublox 0:19aa55d66228 119 }
group-ublox 0:19aa55d66228 120
group-ublox 0:19aa55d66228 121 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 122 static inline bool rf_check_mac_address(uint8_t *dest) {
group-ublox 0:19aa55d66228 123 for(int i = 0; i < 8; i++) {
group-ublox 0:19aa55d66228 124 if(dest[i] != stored_mac_address[7-i]) {
group-ublox 0:19aa55d66228 125 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 126 tr_debug("%s (%d): i=%d, dest=%x, stored=%x",
group-ublox 0:19aa55d66228 127 __func__, __LINE__,
group-ublox 0:19aa55d66228 128 i, dest[i], stored_mac_address[7-i]);
group-ublox 0:19aa55d66228 129 #endif
group-ublox 0:19aa55d66228 130 return false;
group-ublox 0:19aa55d66228 131 }
group-ublox 0:19aa55d66228 132 }
group-ublox 0:19aa55d66228 133 return true;
group-ublox 0:19aa55d66228 134 }
group-ublox 0:19aa55d66228 135
group-ublox 0:19aa55d66228 136 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 137 /* Returns true if packet should be accepted */
group-ublox 0:19aa55d66228 138 static bool rf_check_destination(int len, uint8_t *ack_requested) {
group-ublox 0:19aa55d66228 139 uint8_t frame_type;
group-ublox 0:19aa55d66228 140 uint16_t dst_pan_id;
group-ublox 0:19aa55d66228 141 uint16_t dst_short_adr;
group-ublox 0:19aa55d66228 142 uint8_t dst_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
group-ublox 0:19aa55d66228 143 uint8_t src_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
group-ublox 0:19aa55d66228 144 uint8_t min_size = 3; // FCF & SeqNr
group-ublox 0:19aa55d66228 145 bool ret = false;
group-ublox 0:19aa55d66228 146 #if defined(HEAVY_TRACING)
group-ublox 0:19aa55d66228 147 bool panid_compr = false;
group-ublox 0:19aa55d66228 148 #endif
group-ublox 0:19aa55d66228 149
group-ublox 0:19aa55d66228 150 if(len < 3) {
group-ublox 0:19aa55d66228 151 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 152 return false;
group-ublox 0:19aa55d66228 153 }
group-ublox 0:19aa55d66228 154
group-ublox 0:19aa55d66228 155 uint16_t fcf = rf_read_16_bit(rf_rx_buf);
group-ublox 0:19aa55d66228 156 frame_type = ((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT);
group-ublox 0:19aa55d66228 157 (*ack_requested) = ((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT);
group-ublox 0:19aa55d66228 158 dst_addr_mode = ((fcf & MAC_FCF_DST_ADDR_MASK) >> MAC_FCF_DST_ADDR_SHIFT);
group-ublox 0:19aa55d66228 159 src_addr_mode = ((fcf & MAC_FCF_SRC_ADDR_MASK) >> MAC_FCF_SRC_ADDR_SHIFT);
group-ublox 0:19aa55d66228 160 #if defined(HEAVY_TRACING)
group-ublox 0:19aa55d66228 161 panid_compr = ((fcf & MAC_FCF_INTRA_PANID_MASK) >> MAC_FCF_INTRA_PANID_SHIFT);
group-ublox 0:19aa55d66228 162 #endif
group-ublox 0:19aa55d66228 163
group-ublox 0:19aa55d66228 164 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 165 tr_info("%s (%d): len=%d, ftype=%x, snr=%x, ack=%d, dst=%x, src=%x, intra=%d", __func__, __LINE__, len, frame_type,
group-ublox 0:19aa55d66228 166 rf_rx_buf[2], (*ack_requested), dst_addr_mode, src_addr_mode, panid_compr);
group-ublox 0:19aa55d66228 167 #endif
group-ublox 0:19aa55d66228 168
group-ublox 0:19aa55d66228 169 if(frame_type == FC_ACK_FRAME) { // betzw: we support up to two different forms of ACK frames!
group-ublox 0:19aa55d66228 170 if((len == 3) && (dst_addr_mode == 0x0) && (src_addr_mode == 0x0)) {
group-ublox 0:19aa55d66228 171 ret = true;
group-ublox 0:19aa55d66228 172 }
group-ublox 0:19aa55d66228 173
group-ublox 0:19aa55d66228 174 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 175 tr_info("%s (%d): ret=%d", __func__, __LINE__, ret);
group-ublox 0:19aa55d66228 176 #endif
group-ublox 0:19aa55d66228 177 (*ack_requested) = 0; // Never acknowledge ACK frames
group-ublox 0:19aa55d66228 178 return ret;
group-ublox 0:19aa55d66228 179 }
group-ublox 0:19aa55d66228 180
group-ublox 0:19aa55d66228 181 switch(dst_addr_mode) {
group-ublox 0:19aa55d66228 182 case 0x00:
group-ublox 0:19aa55d66228 183 ret = true; // no check possible;
group-ublox 0:19aa55d66228 184 break;
group-ublox 0:19aa55d66228 185
group-ublox 0:19aa55d66228 186 case 0x02:
group-ublox 0:19aa55d66228 187 min_size += 4; // pan id + short dest adr
group-ublox 0:19aa55d66228 188
group-ublox 0:19aa55d66228 189 if(len < 5) {
group-ublox 0:19aa55d66228 190 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 191 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 192 #endif
group-ublox 0:19aa55d66228 193 return false;
group-ublox 0:19aa55d66228 194 }
group-ublox 0:19aa55d66228 195
group-ublox 0:19aa55d66228 196 dst_pan_id = rf_read_16_bit(&rf_rx_buf[3]);
group-ublox 0:19aa55d66228 197 if((dst_pan_id != stored_pan_id) && (dst_pan_id != 0xFFFF)) {
group-ublox 0:19aa55d66228 198 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 199 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 200 #endif
group-ublox 0:19aa55d66228 201 return false;
group-ublox 0:19aa55d66228 202 }
group-ublox 0:19aa55d66228 203
group-ublox 0:19aa55d66228 204 if(len < 7) {
group-ublox 0:19aa55d66228 205 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 206 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 207 #endif
group-ublox 0:19aa55d66228 208 return false;
group-ublox 0:19aa55d66228 209 }
group-ublox 0:19aa55d66228 210
group-ublox 0:19aa55d66228 211 dst_short_adr = rf_read_16_bit(&rf_rx_buf[5]);
group-ublox 0:19aa55d66228 212 if((dst_short_adr != stored_short_adr) && (dst_short_adr != 0xFFFF)) {
group-ublox 0:19aa55d66228 213 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 214 tr_debug("%s (%d): %d!=%d", __func__, __LINE__, dst_short_adr, stored_short_adr);
group-ublox 0:19aa55d66228 215 #endif
group-ublox 0:19aa55d66228 216 return false;
group-ublox 0:19aa55d66228 217 }
group-ublox 0:19aa55d66228 218
group-ublox 0:19aa55d66228 219 ret = true;
group-ublox 0:19aa55d66228 220 break;
group-ublox 0:19aa55d66228 221
group-ublox 0:19aa55d66228 222 case 0x03:
group-ublox 0:19aa55d66228 223 min_size += 10; // pan id + dest mac addr
group-ublox 0:19aa55d66228 224
group-ublox 0:19aa55d66228 225 if(len < 5) {
group-ublox 0:19aa55d66228 226 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 227 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 228 #endif
group-ublox 0:19aa55d66228 229 return false;
group-ublox 0:19aa55d66228 230 }
group-ublox 0:19aa55d66228 231
group-ublox 0:19aa55d66228 232 dst_pan_id = rf_read_16_bit(&rf_rx_buf[3]);
group-ublox 0:19aa55d66228 233 if((dst_pan_id != stored_pan_id) && (dst_pan_id != 0xFFFF)) {
group-ublox 0:19aa55d66228 234 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 235 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 236 #endif
group-ublox 0:19aa55d66228 237 return false;
group-ublox 0:19aa55d66228 238 }
group-ublox 0:19aa55d66228 239
group-ublox 0:19aa55d66228 240 if(len < 13) {
group-ublox 0:19aa55d66228 241 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 242 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 243 #endif
group-ublox 0:19aa55d66228 244 return false;
group-ublox 0:19aa55d66228 245 }
group-ublox 0:19aa55d66228 246
group-ublox 0:19aa55d66228 247 ret = rf_check_mac_address(&rf_rx_buf[5]);
group-ublox 0:19aa55d66228 248
group-ublox 0:19aa55d66228 249 if(!ret) {
group-ublox 0:19aa55d66228 250 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 251 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 252 #endif
group-ublox 0:19aa55d66228 253 return false;
group-ublox 0:19aa55d66228 254 }
group-ublox 0:19aa55d66228 255
group-ublox 0:19aa55d66228 256 break;
group-ublox 0:19aa55d66228 257
group-ublox 0:19aa55d66228 258 default:
group-ublox 0:19aa55d66228 259 /* not supported */
group-ublox 0:19aa55d66228 260 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 261 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 262 #endif
group-ublox 0:19aa55d66228 263 return false;
group-ublox 0:19aa55d66228 264 }
group-ublox 0:19aa55d66228 265
group-ublox 0:19aa55d66228 266 if(ret && (*ack_requested)) {
group-ublox 0:19aa55d66228 267 rf_rx_sequence = rf_rx_buf[2];
group-ublox 0:19aa55d66228 268 }
group-ublox 0:19aa55d66228 269
group-ublox 0:19aa55d66228 270 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 271 tr_info("%s (%d), ret=%d, ack=%d", __func__, __LINE__, ret, (*ack_requested));
group-ublox 0:19aa55d66228 272 #endif
group-ublox 0:19aa55d66228 273 return ret;
group-ublox 0:19aa55d66228 274 }
group-ublox 0:19aa55d66228 275
group-ublox 0:19aa55d66228 276 static uint16_t rf_buffer_len = 0;
group-ublox 0:19aa55d66228 277 static uint8_t rf_sqi;
group-ublox 0:19aa55d66228 278 static int8_t rf_rssi;
group-ublox 0:19aa55d66228 279 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 280 static inline void rf_handle_rx_end(void)
group-ublox 0:19aa55d66228 281 {
group-ublox 0:19aa55d66228 282 uint8_t ack_requested = 0;
group-ublox 0:19aa55d66228 283
group-ublox 0:19aa55d66228 284 /* Get received data */
group-ublox 0:19aa55d66228 285 rf_buffer_len = rf_device->read(rf_rx_buf, MAX_PACKET_LEN);
group-ublox 0:19aa55d66228 286 if(!rf_buffer_len)
group-ublox 0:19aa55d66228 287 return;
group-ublox 0:19aa55d66228 288
group-ublox 0:19aa55d66228 289 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 290 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 291 #endif
group-ublox 0:19aa55d66228 292
group-ublox 0:19aa55d66228 293 /* Check if packet should be accepted */
group-ublox 0:19aa55d66228 294 if(!rf_check_destination(rf_buffer_len, &ack_requested)) {
group-ublox 0:19aa55d66228 295 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 296 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 297 #endif
group-ublox 0:19aa55d66228 298 return;
group-ublox 0:19aa55d66228 299 }
group-ublox 0:19aa55d66228 300
group-ublox 0:19aa55d66228 301 /* If waiting for ACK, check here if the packet is an ACK to a message previously sent */
group-ublox 0:19aa55d66228 302 if(expecting_ack) {
group-ublox 0:19aa55d66228 303 uint16_t fcf = rf_read_16_bit(rf_rx_buf);
group-ublox 0:19aa55d66228 304 expecting_ack = false;
group-ublox 0:19aa55d66228 305
group-ublox 0:19aa55d66228 306 if(((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT) == FC_ACK_FRAME) {
group-ublox 0:19aa55d66228 307 /*Send sequence number in ACK handler*/
group-ublox 0:19aa55d66228 308 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 309 tr_debug("%s (%d), len=%u", __func__, __LINE__, (unsigned int)rf_buffer_len);
group-ublox 0:19aa55d66228 310 #endif
group-ublox 0:19aa55d66228 311 rf_handle_ack(rf_rx_buf[2]);
group-ublox 0:19aa55d66228 312 return;
group-ublox 0:19aa55d66228 313 } else {
group-ublox 0:19aa55d66228 314 /*Call PHY TX Done API*/
group-ublox 0:19aa55d66228 315 if(device_driver.phy_tx_done_cb){
group-ublox 0:19aa55d66228 316 phy_status = PHY_LINK_TX_FAIL;
group-ublox 0:19aa55d66228 317 rf_send_signal(RF_SIG_CB_TX_DONE);
group-ublox 0:19aa55d66228 318 }
group-ublox 0:19aa55d66228 319 }
group-ublox 0:19aa55d66228 320 }
group-ublox 0:19aa55d66228 321
group-ublox 0:19aa55d66228 322 /* Kick off ACK sending */
group-ublox 0:19aa55d66228 323 if(ack_requested) {
group-ublox 0:19aa55d66228 324 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 325 tr_debug("%s (%d), len=%u", __func__, __LINE__, (unsigned int)rf_buffer_len);
group-ublox 0:19aa55d66228 326 #endif
group-ublox 0:19aa55d66228 327 rf_send_signal(RF_SIG_ACK_NEEDED);
group-ublox 0:19aa55d66228 328 }
group-ublox 0:19aa55d66228 329
group-ublox 0:19aa55d66228 330 /* Get link information */
group-ublox 0:19aa55d66228 331 rf_rssi = (int8_t)rf_device->get_last_rssi_dbm();
group-ublox 0:19aa55d66228 332 rf_sqi = (uint8_t)rf_device->get_last_sqi(); // use SQI as link quality
group-ublox 0:19aa55d66228 333
group-ublox 0:19aa55d66228 334 /* Note: Checksum of the packet must be checked and removed before entering here */
group-ublox 0:19aa55d66228 335 /* TODO - betzw: what to do? */
group-ublox 0:19aa55d66228 336
group-ublox 0:19aa55d66228 337 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 338 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 339 #endif
group-ublox 0:19aa55d66228 340
group-ublox 0:19aa55d66228 341 /* Send received data and link information to the network stack */
group-ublox 0:19aa55d66228 342 if( device_driver.phy_rx_cb ){
group-ublox 0:19aa55d66228 343 rf_send_signal(RF_SIG_CB_RX_RCVD);
group-ublox 0:19aa55d66228 344 }
group-ublox 0:19aa55d66228 345 }
group-ublox 0:19aa55d66228 346
group-ublox 0:19aa55d66228 347 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 348 static inline void rf_handle_tx_end(void)
group-ublox 0:19aa55d66228 349 {
group-ublox 0:19aa55d66228 350 /* Check if this is an ACK sending which is still pending */
group-ublox 0:19aa55d66228 351 if(rf_ack_sent) {
group-ublox 0:19aa55d66228 352 rf_ack_sent = false;
group-ublox 0:19aa55d66228 353 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 354 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 355 #endif
group-ublox 0:19aa55d66228 356 return; // no need to inform stack
group-ublox 0:19aa55d66228 357 }
group-ublox 0:19aa55d66228 358
group-ublox 0:19aa55d66228 359 /* Transform `need_ack` in `expecting_ack` */
group-ublox 0:19aa55d66228 360 if(need_ack) {
group-ublox 0:19aa55d66228 361 need_ack = false;
group-ublox 0:19aa55d66228 362 expecting_ack = true;
group-ublox 0:19aa55d66228 363 }
group-ublox 0:19aa55d66228 364
group-ublox 0:19aa55d66228 365 /*Call PHY TX Done API*/
group-ublox 0:19aa55d66228 366 if(device_driver.phy_tx_done_cb){
group-ublox 0:19aa55d66228 367 phy_status = PHY_LINK_TX_SUCCESS;
group-ublox 0:19aa55d66228 368 rf_send_signal(RF_SIG_CB_TX_DONE);
group-ublox 0:19aa55d66228 369 }
group-ublox 0:19aa55d66228 370 }
group-ublox 0:19aa55d66228 371
group-ublox 0:19aa55d66228 372 /* Note: we might be in IRQ context */
group-ublox 0:19aa55d66228 373 static inline void rf_handle_tx_err(phy_link_tx_status_e phy_val = PHY_LINK_TX_FAIL) {
group-ublox 0:19aa55d66228 374 /*Call PHY TX Done API*/
group-ublox 0:19aa55d66228 375 if(device_driver.phy_tx_done_cb){
group-ublox 0:19aa55d66228 376 need_ack = false;
group-ublox 0:19aa55d66228 377 phy_status = phy_val;
group-ublox 0:19aa55d66228 378 rf_send_signal(RF_SIG_CB_TX_DONE);
group-ublox 0:19aa55d66228 379 }
group-ublox 0:19aa55d66228 380 }
group-ublox 0:19aa55d66228 381
group-ublox 0:19aa55d66228 382 /* Note: we are in IRQ context */
group-ublox 0:19aa55d66228 383 static void rf_callback_func(int event) {
group-ublox 0:19aa55d66228 384 switch(event) {
group-ublox 0:19aa55d66228 385 case SimpleSpirit1::RX_DONE:
group-ublox 0:19aa55d66228 386 rf_handle_rx_end();
group-ublox 0:19aa55d66228 387 break;
group-ublox 0:19aa55d66228 388 case SimpleSpirit1::TX_DONE:
group-ublox 0:19aa55d66228 389 rf_handle_tx_end();
group-ublox 0:19aa55d66228 390 break;
group-ublox 0:19aa55d66228 391 case SimpleSpirit1::TX_ERR:
group-ublox 0:19aa55d66228 392 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 393 tr_debug("%s (%d): TX_ERR!!!", __func__, __LINE__);
group-ublox 0:19aa55d66228 394 #endif
group-ublox 0:19aa55d66228 395 rf_handle_tx_err();
group-ublox 0:19aa55d66228 396 break;
group-ublox 0:19aa55d66228 397 }
group-ublox 0:19aa55d66228 398 }
group-ublox 0:19aa55d66228 399
group-ublox 0:19aa55d66228 400 static int8_t rf_trigger_send(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol)
group-ublox 0:19aa55d66228 401 {
group-ublox 0:19aa55d66228 402 #ifndef NDEBUG
group-ublox 0:19aa55d66228 403 debug_if(!(data_length >= 3), "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__);
group-ublox 0:19aa55d66228 404 #endif
group-ublox 0:19aa55d66228 405
group-ublox 0:19aa55d66228 406 /* Give 'rf_ack_sender' a better chance to run */
group-ublox 0:19aa55d66228 407 Thread::yield();
group-ublox 0:19aa55d66228 408
group-ublox 0:19aa55d66228 409 /* Get Lock */
group-ublox 0:19aa55d66228 410 rf_if_lock();
group-ublox 0:19aa55d66228 411
group-ublox 0:19aa55d66228 412 /*Check if transmitter is busy*/
group-ublox 0:19aa55d66228 413 if(rf_device->is_receiving()) { /* betzw - WAS: (rf_device->channel_clear() != 0)), do NOT use this but rather study and enable automatic CCA */
group-ublox 0:19aa55d66228 414 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 415 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 416 #endif
group-ublox 0:19aa55d66228 417
group-ublox 0:19aa55d66228 418 /* Release Lock */
group-ublox 0:19aa55d66228 419 rf_if_unlock();
group-ublox 0:19aa55d66228 420
group-ublox 0:19aa55d66228 421 /*Return busy*/
group-ublox 0:19aa55d66228 422 return -1;
group-ublox 0:19aa55d66228 423 } else {
group-ublox 0:19aa55d66228 424 uint16_t fcf = rf_read_16_bit(data_ptr);
group-ublox 0:19aa55d66228 425
group-ublox 0:19aa55d66228 426 /*Check if transmitted data needs to be acked*/
group-ublox 0:19aa55d66228 427 if((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT)
group-ublox 0:19aa55d66228 428 need_ack = true;
group-ublox 0:19aa55d66228 429 else
group-ublox 0:19aa55d66228 430 need_ack = false;
group-ublox 0:19aa55d66228 431
group-ublox 0:19aa55d66228 432 /*Store the sequence number for ACK handling*/
group-ublox 0:19aa55d66228 433 tx_sequence = *(data_ptr + 2);
group-ublox 0:19aa55d66228 434
group-ublox 0:19aa55d66228 435 /*Store TX handle*/
group-ublox 0:19aa55d66228 436 mac_tx_handle = tx_handle;
group-ublox 0:19aa55d66228 437
group-ublox 0:19aa55d66228 438 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 439 tr_info("%s (%d), len=%d, tx_handle=%x, tx_seq=%x, need_ack=%d (%x:%x, %x:%x, %x:%x, %x:%x)", __func__, __LINE__,
group-ublox 0:19aa55d66228 440 data_length, tx_handle, tx_sequence, need_ack,
group-ublox 0:19aa55d66228 441 data_ptr[3], data_ptr[4], data_ptr[5], data_ptr[6],
group-ublox 0:19aa55d66228 442 data_ptr[7], data_ptr[8], data_ptr[9], data_ptr[10]);
group-ublox 0:19aa55d66228 443 #endif
group-ublox 0:19aa55d66228 444
group-ublox 0:19aa55d66228 445 /*Send the packet*/
group-ublox 0:19aa55d66228 446 int ret = rf_device->send(data_ptr, data_length);
group-ublox 0:19aa55d66228 447 if(ret != RADIO_TX_OK) {
group-ublox 0:19aa55d66228 448 rf_handle_tx_err(PHY_LINK_CCA_FAIL);
group-ublox 0:19aa55d66228 449 }
group-ublox 0:19aa55d66228 450
group-ublox 0:19aa55d66228 451 /* Release Lock */
group-ublox 0:19aa55d66228 452 rf_if_unlock();
group-ublox 0:19aa55d66228 453 }
group-ublox 0:19aa55d66228 454
group-ublox 0:19aa55d66228 455 /*Return success*/
group-ublox 0:19aa55d66228 456 return 0;
group-ublox 0:19aa55d66228 457 }
group-ublox 0:19aa55d66228 458
group-ublox 0:19aa55d66228 459 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
group-ublox 0:19aa55d66228 460 {
group-ublox 0:19aa55d66228 461 int8_t ret_val = 0;
group-ublox 0:19aa55d66228 462 switch (new_state)
group-ublox 0:19aa55d66228 463 {
group-ublox 0:19aa55d66228 464 /*Reset PHY driver and set to idle*/
group-ublox 0:19aa55d66228 465 case PHY_INTERFACE_RESET:
group-ublox 0:19aa55d66228 466 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 467 rf_device->reset_board();
group-ublox 0:19aa55d66228 468 break;
group-ublox 0:19aa55d66228 469 /*Disable PHY Interface driver*/
group-ublox 0:19aa55d66228 470 case PHY_INTERFACE_DOWN:
group-ublox 0:19aa55d66228 471 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 472 ret_val = rf_device->off();
group-ublox 0:19aa55d66228 473 if(ret_val != 0) ret_val = -1;
group-ublox 0:19aa55d66228 474 break;
group-ublox 0:19aa55d66228 475 /*Enable PHY Interface driver*/
group-ublox 0:19aa55d66228 476 case PHY_INTERFACE_UP:
group-ublox 0:19aa55d66228 477 ret_val = rf_device->on();
group-ublox 0:19aa55d66228 478 if(ret_val != 0) {
group-ublox 0:19aa55d66228 479 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 480 ret_val = -1;
group-ublox 0:19aa55d66228 481 break;
group-ublox 0:19aa55d66228 482 }
group-ublox 0:19aa55d66228 483 tr_debug("%s (%d) - channel: %d", __func__, __LINE__, (int)rf_channel);
group-ublox 0:19aa55d66228 484 rf_device->set_channel(rf_channel);
group-ublox 0:19aa55d66228 485 break;
group-ublox 0:19aa55d66228 486 /*Enable wireless interface ED scan mode*/
group-ublox 0:19aa55d66228 487 case PHY_INTERFACE_RX_ENERGY_STATE:
group-ublox 0:19aa55d66228 488 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 489 break;
group-ublox 0:19aa55d66228 490 /*Enable Sniffer state*/
group-ublox 0:19aa55d66228 491 case PHY_INTERFACE_SNIFFER_STATE:
group-ublox 0:19aa55d66228 492 // TODO - if we really need this - WAS: rf_setup_sniffer(rf_channel);
group-ublox 0:19aa55d66228 493 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 494 ret_val = -1;
group-ublox 0:19aa55d66228 495 break;
group-ublox 0:19aa55d66228 496 default:
group-ublox 0:19aa55d66228 497 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 498 break;
group-ublox 0:19aa55d66228 499 }
group-ublox 0:19aa55d66228 500 return ret_val;
group-ublox 0:19aa55d66228 501 }
group-ublox 0:19aa55d66228 502
group-ublox 0:19aa55d66228 503 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
group-ublox 0:19aa55d66228 504 {
group-ublox 0:19aa55d66228 505 switch (extension_type)
group-ublox 0:19aa55d66228 506 {
group-ublox 0:19aa55d66228 507 /*Control MAC pending bit for Indirect data transmission*/
group-ublox 0:19aa55d66228 508 case PHY_EXTENSION_CTRL_PENDING_BIT:
group-ublox 0:19aa55d66228 509 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 510 break;
group-ublox 0:19aa55d66228 511
group-ublox 0:19aa55d66228 512 /*Return frame pending status*/
group-ublox 0:19aa55d66228 513 case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
group-ublox 0:19aa55d66228 514 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 515 *data_ptr = 0;
group-ublox 0:19aa55d66228 516 break;
group-ublox 0:19aa55d66228 517
group-ublox 0:19aa55d66228 518 /*Set channel, used for setting channel for energy scan*/
group-ublox 0:19aa55d66228 519 case PHY_EXTENSION_SET_CHANNEL:
group-ublox 0:19aa55d66228 520 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 521 break;
group-ublox 0:19aa55d66228 522
group-ublox 0:19aa55d66228 523 /*Read energy on the channel*/
group-ublox 0:19aa55d66228 524 case PHY_EXTENSION_READ_CHANNEL_ENERGY:
group-ublox 0:19aa55d66228 525 // TODO: *data_ptr = rf_get_channel_energy();
group-ublox 0:19aa55d66228 526 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 527 *data_ptr = (int8_t)rf_device->get_last_rssi_dbm();
group-ublox 0:19aa55d66228 528 break;
group-ublox 0:19aa55d66228 529
group-ublox 0:19aa55d66228 530 /*Read status of the link*/
group-ublox 0:19aa55d66228 531 case PHY_EXTENSION_READ_LINK_STATUS:
group-ublox 0:19aa55d66228 532 // TODO: *data_ptr = rf_get_link_status();
group-ublox 0:19aa55d66228 533 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 534 *data_ptr = rf_device->get_last_sqi(); // use SQI as link quality
group-ublox 0:19aa55d66228 535 break;
group-ublox 0:19aa55d66228 536
group-ublox 0:19aa55d66228 537 default:
group-ublox 0:19aa55d66228 538 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 539 break;
group-ublox 0:19aa55d66228 540 }
group-ublox 0:19aa55d66228 541 return 0;
group-ublox 0:19aa55d66228 542 }
group-ublox 0:19aa55d66228 543
group-ublox 0:19aa55d66228 544 static inline void rf_set_mac_address(uint8_t *ptr) {
group-ublox 0:19aa55d66228 545 tr_debug("%s (%d), adr0=%x, adr1=%x, adr2=%x, adr3=%x, adr4=%x, adr5=%x, adr6=%x, adr7=%x",
group-ublox 0:19aa55d66228 546 __func__, __LINE__,
group-ublox 0:19aa55d66228 547 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
group-ublox 0:19aa55d66228 548 for(int i = 0; i < 8; i++) {
group-ublox 0:19aa55d66228 549 stored_mac_address[i] = ptr[i];
group-ublox 0:19aa55d66228 550 }
group-ublox 0:19aa55d66228 551 }
group-ublox 0:19aa55d66228 552
group-ublox 0:19aa55d66228 553 static inline void rf_get_mac_address(uint8_t *ptr) {
group-ublox 0:19aa55d66228 554 for(int i = 0; i < 8; i++) {
group-ublox 0:19aa55d66228 555 ptr[i] = stored_mac_address[i];
group-ublox 0:19aa55d66228 556 }
group-ublox 0:19aa55d66228 557 tr_debug("%s (%d), adr0=%x, adr1=%x, adr2=%x, adr3=%x, adr4=%x, adr5=%x, adr6=%x, adr7=%x",
group-ublox 0:19aa55d66228 558 __func__, __LINE__,
group-ublox 0:19aa55d66228 559 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
group-ublox 0:19aa55d66228 560 }
group-ublox 0:19aa55d66228 561
group-ublox 0:19aa55d66228 562 static inline void rf_set_short_adr(uint8_t *ptr) {
group-ublox 0:19aa55d66228 563 stored_short_adr = (ptr[0] << 8) + ptr[1]; // big-endian
group-ublox 0:19aa55d66228 564 tr_debug("%s (%d), adr0=%x, adr1=%x, val=%d",
group-ublox 0:19aa55d66228 565 __func__, __LINE__,
group-ublox 0:19aa55d66228 566 ptr[0], ptr[1], stored_short_adr);
group-ublox 0:19aa55d66228 567 }
group-ublox 0:19aa55d66228 568
group-ublox 0:19aa55d66228 569 static inline void rf_set_pan_id(uint8_t *ptr) {
group-ublox 0:19aa55d66228 570 stored_pan_id = (ptr[0] << 8) + ptr[1]; // big-endian
group-ublox 0:19aa55d66228 571 tr_debug("%s (%d), adr0=%x, adr1=%x, val=%d",
group-ublox 0:19aa55d66228 572 __func__, __LINE__,
group-ublox 0:19aa55d66228 573 ptr[0], ptr[1], stored_pan_id);
group-ublox 0:19aa55d66228 574 }
group-ublox 0:19aa55d66228 575
group-ublox 0:19aa55d66228 576 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
group-ublox 0:19aa55d66228 577 {
group-ublox 0:19aa55d66228 578 switch (address_type)
group-ublox 0:19aa55d66228 579 {
group-ublox 0:19aa55d66228 580 /*Set 48-bit address*/
group-ublox 0:19aa55d66228 581 case PHY_MAC_48BIT:
group-ublox 0:19aa55d66228 582 /* Not used in this example */
group-ublox 0:19aa55d66228 583 // betzw - WAS: rf_set_mac_48bit(address_ptr);
group-ublox 0:19aa55d66228 584 break;
group-ublox 0:19aa55d66228 585 /*Set 64-bit address*/
group-ublox 0:19aa55d66228 586 case PHY_MAC_64BIT:
group-ublox 0:19aa55d66228 587 rf_set_mac_address(address_ptr);
group-ublox 0:19aa55d66228 588 break;
group-ublox 0:19aa55d66228 589 /*Set 16-bit address*/
group-ublox 0:19aa55d66228 590 case PHY_MAC_16BIT:
group-ublox 0:19aa55d66228 591 rf_set_short_adr(address_ptr);
group-ublox 0:19aa55d66228 592 break;
group-ublox 0:19aa55d66228 593 /*Set PAN Id*/
group-ublox 0:19aa55d66228 594 case PHY_MAC_PANID:
group-ublox 0:19aa55d66228 595 rf_set_pan_id(address_ptr);
group-ublox 0:19aa55d66228 596 break;
group-ublox 0:19aa55d66228 597 }
group-ublox 0:19aa55d66228 598
group-ublox 0:19aa55d66228 599 return 0;
group-ublox 0:19aa55d66228 600 }
group-ublox 0:19aa55d66228 601
group-ublox 0:19aa55d66228 602 static void rf_ack_loop(void) {
group-ublox 0:19aa55d66228 603 static uint16_t buffer[2] = {
group-ublox 0:19aa55d66228 604 (FC_ACK_FRAME << MAC_FCF_FRAME_TYPE_SHIFT),
group-ublox 0:19aa55d66228 605 0x0
group-ublox 0:19aa55d66228 606 };
group-ublox 0:19aa55d66228 607
group-ublox 0:19aa55d66228 608 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 609
group-ublox 0:19aa55d66228 610 do {
group-ublox 0:19aa55d66228 611 /* Wait for signal */
group-ublox 0:19aa55d66228 612 osEvent event = rf_ack_sender.signal_wait(0);
group-ublox 0:19aa55d66228 613
group-ublox 0:19aa55d66228 614 if(event.status != osEventSignal) {
group-ublox 0:19aa55d66228 615 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 616 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 617 #endif
group-ublox 0:19aa55d66228 618 continue;
group-ublox 0:19aa55d66228 619 }
group-ublox 0:19aa55d66228 620
group-ublox 0:19aa55d66228 621 int32_t signals = event.value.signals;
group-ublox 0:19aa55d66228 622
group-ublox 0:19aa55d66228 623 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 624 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 625 #endif
group-ublox 0:19aa55d66228 626
group-ublox 0:19aa55d66228 627 /* Get Lock */
group-ublox 0:19aa55d66228 628 rf_if_lock();
group-ublox 0:19aa55d66228 629
group-ublox 0:19aa55d66228 630 if(signals & RF_SIG_ACK_NEEDED) {
group-ublox 0:19aa55d66228 631 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 632 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 633 #endif
group-ublox 0:19aa55d66228 634
group-ublox 0:19aa55d66228 635 /* Prepare payload */
group-ublox 0:19aa55d66228 636 uint8_t *ptr = (uint8_t*)&buffer[1];
group-ublox 0:19aa55d66228 637 ptr[0] = rf_rx_sequence; // Sequence number
group-ublox 0:19aa55d66228 638
group-ublox 0:19aa55d66228 639 /* Wait for device not receiving */
group-ublox 0:19aa55d66228 640 while(rf_device->is_receiving()) {
group-ublox 0:19aa55d66228 641 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 642 tr_info("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 643 #endif
group-ublox 0:19aa55d66228 644 wait_us(10);
group-ublox 0:19aa55d66228 645 }
group-ublox 0:19aa55d66228 646
group-ublox 0:19aa55d66228 647 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 648 tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]);
group-ublox 0:19aa55d66228 649 #endif
group-ublox 0:19aa55d66228 650
group-ublox 0:19aa55d66228 651 /* Set information that we have sent an ACK */
group-ublox 0:19aa55d66228 652 rf_ack_sent = true;
group-ublox 0:19aa55d66228 653
group-ublox 0:19aa55d66228 654 /*Send the packet*/
group-ublox 0:19aa55d66228 655 rf_device->send((uint8_t*)buffer, 3, false);
group-ublox 0:19aa55d66228 656
group-ublox 0:19aa55d66228 657 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 658 tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]);
group-ublox 0:19aa55d66228 659 #endif
group-ublox 0:19aa55d66228 660 }
group-ublox 0:19aa55d66228 661
group-ublox 0:19aa55d66228 662 if(signals & RF_SIG_CB_TX_DONE) {
group-ublox 0:19aa55d66228 663 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status,
group-ublox 0:19aa55d66228 664 (phy_status == PHY_LINK_CCA_FAIL) ? 0xFF : 0, 0);
group-ublox 0:19aa55d66228 665 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 666 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 667 #endif
group-ublox 0:19aa55d66228 668 }
group-ublox 0:19aa55d66228 669
group-ublox 0:19aa55d66228 670 if(signals & RF_SIG_CB_RX_RCVD) {
group-ublox 0:19aa55d66228 671 device_driver.phy_rx_cb(rf_rx_buf, rf_buffer_len, rf_sqi, rf_rssi, rf_radio_driver_id);
group-ublox 0:19aa55d66228 672 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 673 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 674 #endif
group-ublox 0:19aa55d66228 675 }
group-ublox 0:19aa55d66228 676
group-ublox 0:19aa55d66228 677 /* Release Lock */
group-ublox 0:19aa55d66228 678 rf_if_unlock();
group-ublox 0:19aa55d66228 679
group-ublox 0:19aa55d66228 680 #ifdef HEAVY_TRACING
group-ublox 0:19aa55d66228 681 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 682 #endif
group-ublox 0:19aa55d66228 683 } while(true);
group-ublox 0:19aa55d66228 684 }
group-ublox 0:19aa55d66228 685
group-ublox 0:19aa55d66228 686 void NanostackRfPhySpirit1::rf_init(void) {
group-ublox 0:19aa55d66228 687 #ifndef NDEBUG
group-ublox 0:19aa55d66228 688 osStatus ret;
group-ublox 0:19aa55d66228 689 #endif
group-ublox 0:19aa55d66228 690
group-ublox 0:19aa55d66228 691 if(rf_device == NULL) {
group-ublox 0:19aa55d66228 692 rf_device = &SimpleSpirit1::CreateInstance(_spi_mosi, _spi_miso, _spi_sclk, _dev_irq, _dev_cs, _dev_sdn, _brd_led);
group-ublox 0:19aa55d66228 693 rf_device->attach_irq_callback(rf_callback_func);
group-ublox 0:19aa55d66228 694
group-ublox 0:19aa55d66228 695 #ifndef NDEBUG
group-ublox 0:19aa55d66228 696 ret =
group-ublox 0:19aa55d66228 697 #endif
group-ublox 0:19aa55d66228 698 rf_ack_sender.start(rf_ack_loop);
group-ublox 0:19aa55d66228 699
group-ublox 0:19aa55d66228 700 #ifndef NDEBUG
group-ublox 0:19aa55d66228 701 debug_if(!(ret == osOK), "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__);
group-ublox 0:19aa55d66228 702 #endif
group-ublox 0:19aa55d66228 703 }
group-ublox 0:19aa55d66228 704 }
group-ublox 0:19aa55d66228 705
group-ublox 0:19aa55d66228 706 NanostackRfPhySpirit1::NanostackRfPhySpirit1(PinName spi_mosi, PinName spi_miso, PinName spi_sclk,
group-ublox 0:19aa55d66228 707 PinName dev_irq, PinName dev_cs, PinName dev_sdn, PinName brd_led) :
group-ublox 0:19aa55d66228 708 _spi_mosi(spi_mosi),
group-ublox 0:19aa55d66228 709 _spi_miso(spi_miso),
group-ublox 0:19aa55d66228 710 _spi_sclk(spi_sclk),
group-ublox 0:19aa55d66228 711 _dev_irq(dev_irq),
group-ublox 0:19aa55d66228 712 _dev_cs(dev_cs),
group-ublox 0:19aa55d66228 713 _dev_sdn(dev_sdn),
group-ublox 0:19aa55d66228 714 _brd_led(brd_led)
group-ublox 0:19aa55d66228 715 {
group-ublox 0:19aa55d66228 716 /* Nothing to do */
group-ublox 0:19aa55d66228 717 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 718 }
group-ublox 0:19aa55d66228 719
group-ublox 0:19aa55d66228 720 NanostackRfPhySpirit1::~NanostackRfPhySpirit1()
group-ublox 0:19aa55d66228 721 {
group-ublox 0:19aa55d66228 722 /* Nothing to do */
group-ublox 0:19aa55d66228 723 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 724 }
group-ublox 0:19aa55d66228 725
group-ublox 0:19aa55d66228 726 int8_t NanostackRfPhySpirit1::rf_register()
group-ublox 0:19aa55d66228 727 {
group-ublox 0:19aa55d66228 728 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 729
group-ublox 0:19aa55d66228 730 /* Get Lock */
group-ublox 0:19aa55d66228 731 rf_if_lock();
group-ublox 0:19aa55d66228 732
group-ublox 0:19aa55d66228 733 /* Do some initialization */
group-ublox 0:19aa55d66228 734 rf_init();
group-ublox 0:19aa55d66228 735
group-ublox 0:19aa55d66228 736 /* Set pointer to MAC address */
group-ublox 0:19aa55d66228 737 device_driver.PHY_MAC = stored_mac_address;
group-ublox 0:19aa55d66228 738
group-ublox 0:19aa55d66228 739 /* Set driver Name */
group-ublox 0:19aa55d66228 740 device_driver.driver_description = (char*)"Spirit1 Sub-GHz RF";
group-ublox 0:19aa55d66228 741
group-ublox 0:19aa55d66228 742 /*Type of RF PHY is SubGHz*/
group-ublox 0:19aa55d66228 743 device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
group-ublox 0:19aa55d66228 744
group-ublox 0:19aa55d66228 745 /*Maximum size of payload*/
group-ublox 0:19aa55d66228 746 device_driver.phy_MTU = MAX_PACKET_LEN;
group-ublox 0:19aa55d66228 747
group-ublox 0:19aa55d66228 748 /*No header in PHY*/
group-ublox 0:19aa55d66228 749 device_driver.phy_header_length = 0;
group-ublox 0:19aa55d66228 750
group-ublox 0:19aa55d66228 751 /*No tail in PHY*/
group-ublox 0:19aa55d66228 752 device_driver.phy_tail_length = 0;
group-ublox 0:19aa55d66228 753
group-ublox 0:19aa55d66228 754 /*Set up driver functions*/
group-ublox 0:19aa55d66228 755 device_driver.address_write = &rf_address_write;
group-ublox 0:19aa55d66228 756 device_driver.extension = &rf_extension;
group-ublox 0:19aa55d66228 757 device_driver.state_control = &rf_interface_state_control;
group-ublox 0:19aa55d66228 758 device_driver.tx = &rf_trigger_send;
group-ublox 0:19aa55d66228 759
group-ublox 0:19aa55d66228 760 /*Set supported channel pages*/
group-ublox 0:19aa55d66228 761 device_driver.phy_channel_pages = phy_channel_pages;
group-ublox 0:19aa55d66228 762
group-ublox 0:19aa55d66228 763 //Nullify rx/tx callbacks
group-ublox 0:19aa55d66228 764 device_driver.phy_rx_cb = NULL;
group-ublox 0:19aa55d66228 765 device_driver.phy_tx_done_cb = NULL;
group-ublox 0:19aa55d66228 766 device_driver.arm_net_virtual_rx_cb = NULL;
group-ublox 0:19aa55d66228 767 device_driver.arm_net_virtual_tx_cb = NULL;
group-ublox 0:19aa55d66228 768
group-ublox 0:19aa55d66228 769 /*Register device driver*/
group-ublox 0:19aa55d66228 770 rf_radio_driver_id = arm_net_phy_register(&device_driver);
group-ublox 0:19aa55d66228 771
group-ublox 0:19aa55d66228 772 /* Release Lock */
group-ublox 0:19aa55d66228 773 rf_if_unlock();
group-ublox 0:19aa55d66228 774
group-ublox 0:19aa55d66228 775 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 776 return rf_radio_driver_id;
group-ublox 0:19aa55d66228 777 }
group-ublox 0:19aa55d66228 778
group-ublox 0:19aa55d66228 779 void NanostackRfPhySpirit1::rf_unregister()
group-ublox 0:19aa55d66228 780 {
group-ublox 0:19aa55d66228 781 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 782
group-ublox 0:19aa55d66228 783 /* Get Lock */
group-ublox 0:19aa55d66228 784 rf_if_lock();
group-ublox 0:19aa55d66228 785
group-ublox 0:19aa55d66228 786 if (rf_radio_driver_id >= 0) {
group-ublox 0:19aa55d66228 787 arm_net_phy_unregister(rf_radio_driver_id);
group-ublox 0:19aa55d66228 788 rf_radio_driver_id = -1;
group-ublox 0:19aa55d66228 789 }
group-ublox 0:19aa55d66228 790
group-ublox 0:19aa55d66228 791 /* Release Lock */
group-ublox 0:19aa55d66228 792 rf_if_unlock();
group-ublox 0:19aa55d66228 793 }
group-ublox 0:19aa55d66228 794
group-ublox 0:19aa55d66228 795 void NanostackRfPhySpirit1::get_mac_address(uint8_t *mac)
group-ublox 0:19aa55d66228 796 {
group-ublox 0:19aa55d66228 797 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 798
group-ublox 0:19aa55d66228 799 /* Get Lock */
group-ublox 0:19aa55d66228 800 rf_if_lock();
group-ublox 0:19aa55d66228 801
group-ublox 0:19aa55d66228 802 if(rf_radio_driver_id >= 0) {
group-ublox 0:19aa55d66228 803 rf_get_mac_address(mac);
group-ublox 0:19aa55d66228 804 } else {
group-ublox 0:19aa55d66228 805 error("NanostackRfPhySpirit1 must be registered to read mac address");
group-ublox 0:19aa55d66228 806 }
group-ublox 0:19aa55d66228 807
group-ublox 0:19aa55d66228 808 /* Release Lock */
group-ublox 0:19aa55d66228 809 rf_if_unlock();
group-ublox 0:19aa55d66228 810 }
group-ublox 0:19aa55d66228 811
group-ublox 0:19aa55d66228 812 void NanostackRfPhySpirit1::set_mac_address(uint8_t *mac)
group-ublox 0:19aa55d66228 813 {
group-ublox 0:19aa55d66228 814 tr_debug("%s (%d)", __func__, __LINE__);
group-ublox 0:19aa55d66228 815
group-ublox 0:19aa55d66228 816 /* Get Lock */
group-ublox 0:19aa55d66228 817 rf_if_lock();
group-ublox 0:19aa55d66228 818
group-ublox 0:19aa55d66228 819 if(rf_radio_driver_id < 0) {
group-ublox 0:19aa55d66228 820 rf_set_mac_address(mac);
group-ublox 0:19aa55d66228 821 } else {
group-ublox 0:19aa55d66228 822 error("NanostackRfPhySpirit1 cannot change mac address when running");
group-ublox 0:19aa55d66228 823 }
group-ublox 0:19aa55d66228 824
group-ublox 0:19aa55d66228 825 /* Release Lock */
group-ublox 0:19aa55d66228 826 rf_if_unlock();
group-ublox 0:19aa55d66228 827 }
group-ublox 0:19aa55d66228 828
group-ublox 0:19aa55d66228 829 #endif /* MBED_CONF_RTOS_PRESENT */