Fork of my MQTTGateway

Dependencies:   mbed-http

Committer:
vpcola
Date:
Sat Apr 08 14:45:51 2017 +0000
Revision:
0:f1d3878b8dd9
Initial commit

Who changed what in which revision?

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