180718 HJM : 8 Count sensing data RF send, certTest, temp(cold)Test

Fork of EV-COG-AD3029LZ by JunMo Hong

Committer:
Wolfgang Betz
Date:
Mon Jul 03 14:39:01 2017 +0200
Revision:
64:28ef790e4ef7
Parent:
63:d7530f62ed93
Child:
65:a16f0064110a
Implement indications received by Kevin Bracey

Date: Mon, 3 Jul 2017 10:14:23 +0000
From: Kevin Bracey <notifications@github.com>

https://github.com/ARMmbed/mbed-os-example-client/issues/266#issuecomment-312606944

I've just spent a little while reviewing the Spirit driver code, just to see if I can see any obvious flaws. (Hard to say much without knowing the hardware, but I can look for general issues.)

I'm a bit wary about the software ack handling - can be tricky.

There is one specific problem that could be affecting performance now - it seems to me the acks are sent with a common send() routine that enables hardware CSMA-CD. An ack should be being sent 192us after transmission completion, without CSMA. Backing off the ack will greatly reduce the chance of packets being successfully acknowledged.

Other notes on ack reception - you're calling TX_DONE whenever tx_sequence == seq_number, whether you were expecting an ack or not. This could cause stack confusion in various ways (eg if you were backing off while someone else used the same sequence number). You should only process an ACK when you actually expect one (TX completed, and AR bit was set in it)

Also, while expecting an ack, it can be beneficial to report TX_FAIL and stop expecting when you receive anything other then an ack with the expected sequence number. The stack will eventually time out if it doesn't get TX_DONE, but receipt of anything else (including a wrongly-numbered ack) indicates a lack of acknowledgment, which can be reported immediately.

Who changed what in which revision?

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