Fork of my original MQTTGateway

Dependencies:   mbed-http

Committer:
vpcola
Date:
Sat Apr 08 14:43:14 2017 +0000
Revision:
0:a1734fe1ec4b
Initial commit

Who changed what in which revision?

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