Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackRfPhySpirit1.cpp Source File

NanostackRfPhySpirit1.cpp

00001 #include "NanostackRfPhySpirit1.h"
00002 
00003 #ifdef MBED_CONF_NANOSTACK_CONFIGURATION
00004 #if MBED_CONF_RTOS_PRESENT
00005 
00006 #include "SimpleSpirit1.h"
00007 #include "nanostack/platform/arm_hal_phy.h"
00008 #include "platform/arm_hal_interrupt.h"
00009 
00010 #include "mbed_trace.h"
00011 #define TRACE_GROUP  "SPIRIT"
00012 
00013 /* Define beyond macro if you want to perform heavy debug tracing (includes tracing in IRQ context) */
00014 // #define HEAVY_TRACING
00015 
00016 static phy_device_driver_s device_driver;
00017 static int8_t rf_radio_driver_id = -1;
00018 
00019 const phy_rf_channel_configuration_s phy_subghz = {868000000, 1000000, 250000, 11, M_GFSK};
00020 
00021 static phy_device_channel_page_s phy_channel_pages[] = {
00022         {CHANNEL_PAGE_2, &phy_subghz},
00023         {CHANNEL_PAGE_0, NULL}
00024 };
00025 
00026 static uint8_t tx_sequence = 0xff;
00027 static uint8_t mac_tx_handle = 0;
00028 
00029 static SimpleSpirit1 *rf_device = NULL;
00030 static uint8_t rf_rx_buf[MAX_PACKET_LEN];
00031 
00032 static uint16_t stored_short_adr;
00033 static uint16_t stored_pan_id;
00034 static uint8_t stored_mac_address[8] = MBED_CONF_SPIRIT1_MAC_ADDRESS;
00035 
00036 #define RF_SIG_ACK_NEEDED (1<<0)
00037 #define RF_SIG_CB_TX_DONE (1<<1)
00038 #define RF_SIG_CB_RX_RCVD (1<<2)
00039 static Thread rf_ack_sender(osPriorityRealtime);
00040 static volatile uint8_t rf_rx_sequence;
00041 static volatile bool rf_ack_sent = false;
00042 static volatile bool expecting_ack = false;
00043 static volatile bool need_ack = false;
00044 
00045 /* MAC frame helper macros */
00046 #define MAC_FCF_FRAME_TYPE_MASK         0x0007
00047 #define MAC_FCF_FRAME_TYPE_SHIFT        0
00048 #define MAC_FCF_SECURITY_BIT_MASK       0x0008
00049 #define MAC_FCF_SECURITY_BIT_SHIFT      3
00050 #define MAC_FCF_PENDING_BIT_MASK        0x0010
00051 #define MAC_FCF_PENDING_BIT_SHIFT       4
00052 #define MAC_FCF_ACK_REQ_BIT_MASK        0x0020
00053 #define MAC_FCF_ACK_REQ_BIT_SHIFT       5
00054 #define MAC_FCF_INTRA_PANID_MASK        0x0040
00055 #define MAC_FCF_INTRA_PANID_SHIFT       6
00056 #define MAC_FCF_DST_ADDR_MASK           0x0c00
00057 #define MAC_FCF_DST_ADDR_SHIFT          10
00058 #define MAC_FCF_VERSION_MASK            0x3000
00059 #define MAC_FCF_VERSION_SHIFT           12
00060 #define MAC_FCF_SRC_ADDR_MASK           0xc000
00061 #define MAC_FCF_SRC_ADDR_SHIFT          14
00062 
00063 /* MAC supported frame types */
00064 #define FC_BEACON_FRAME         0x00
00065 #define FC_DATA_FRAME           0x01
00066 #define FC_ACK_FRAME            0x02
00067 #define FC_CMD_FRAME            0x03
00068 
00069 static inline void rf_if_lock(void)
00070 {
00071     platform_enter_critical();
00072 }
00073 
00074 static inline void rf_if_unlock(void)
00075 {
00076     platform_exit_critical();
00077 }
00078 
00079 static inline uint16_t rf_read_16_bit(uint8_t *data_ptr) { // little-endian
00080     uint16_t ret;
00081 
00082     ret = ((uint16_t)data_ptr[0]) + (((uint16_t)data_ptr[1]) << 8);
00083     return ret;
00084 }
00085 
00086 /* Note: we are in IRQ context */
00087 static inline void rf_send_signal(int32_t signal) {
00088 #ifdef HEAVY_TRACING
00089     tr_info("%s (%d): %d", __func__, __LINE__, signal);
00090 #endif
00091     rf_ack_sender.signal_set(signal);
00092 }
00093 
00094 static volatile phy_link_tx_status_e phy_status;
00095 /* Note: we are in IRQ context */
00096 static void rf_handle_ack(uint8_t seq_number)
00097 {
00098     /*Received ACK sequence must be equal with transmitted packet sequence*/
00099     if(tx_sequence == seq_number)
00100     {
00101 #ifdef HEAVY_TRACING
00102         tr_info("%s (%d)", __func__, __LINE__);
00103 #endif
00104 
00105         /*Call PHY TX Done API*/
00106         if(device_driver.phy_tx_done_cb){
00107             phy_status = PHY_LINK_TX_DONE;
00108             rf_send_signal(RF_SIG_CB_TX_DONE);
00109         }
00110     } else {
00111 #ifdef HEAVY_TRACING
00112         tr_info("%s (%d)", __func__, __LINE__);
00113 #endif
00114 
00115         /*Call PHY TX Done API*/
00116         if(device_driver.phy_tx_done_cb){
00117             phy_status = PHY_LINK_TX_FAIL;
00118             rf_send_signal(RF_SIG_CB_TX_DONE);
00119         }
00120     }
00121 }
00122 
00123 /* Note: we are in IRQ context */
00124 static inline bool rf_check_mac_address(uint8_t *dest) {
00125     for(int i = 0; i < 8; i++) {
00126         if(dest[i] != stored_mac_address[7-i]) {
00127 #ifdef HEAVY_TRACING
00128             tr_debug("%s (%d): i=%d, dest=%x, stored=%x",
00129                     __func__, __LINE__,
00130                     i, dest[i], stored_mac_address[7-i]);
00131 #endif
00132             return false;
00133         }
00134     }
00135     return true;
00136 }
00137 
00138 /* Note: we are in IRQ context */
00139 /* Returns true if packet should be accepted */
00140 static bool rf_check_destination(int len, uint8_t *ack_requested) {
00141     uint8_t frame_type;
00142     uint16_t dst_pan_id;
00143     uint16_t dst_short_adr;
00144     uint8_t dst_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
00145     uint8_t src_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
00146     uint8_t min_size = 3; // FCF & SeqNr
00147     bool ret = false;
00148 #if defined(HEAVY_TRACING)
00149     bool panid_compr = false;
00150 #endif
00151 
00152     if(len < 3) {
00153         tr_debug("%s (%d)", __func__, __LINE__);
00154         return false;
00155     }
00156 
00157     uint16_t fcf = rf_read_16_bit(rf_rx_buf);
00158     frame_type = ((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT);
00159     (*ack_requested) = ((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT);
00160     dst_addr_mode = ((fcf & MAC_FCF_DST_ADDR_MASK) >> MAC_FCF_DST_ADDR_SHIFT);
00161     src_addr_mode = ((fcf & MAC_FCF_SRC_ADDR_MASK) >> MAC_FCF_SRC_ADDR_SHIFT);
00162 #if defined(HEAVY_TRACING)
00163     panid_compr = ((fcf & MAC_FCF_INTRA_PANID_MASK) >> MAC_FCF_INTRA_PANID_SHIFT);
00164 #endif
00165 
00166 #ifdef HEAVY_TRACING
00167     tr_info("%s (%d): len=%d, ftype=%x, snr=%x, ack=%d, dst=%x, src=%x, intra=%d", __func__, __LINE__, len, frame_type,
00168             rf_rx_buf[2], (*ack_requested), dst_addr_mode, src_addr_mode, panid_compr);
00169 #endif
00170 
00171     if(frame_type == FC_ACK_FRAME) { // betzw: we support up to two different forms of ACK frames!
00172         if((len == 3) && (dst_addr_mode == 0x0) && (src_addr_mode == 0x0)) {
00173             ret = true;
00174         }
00175 
00176 #ifdef HEAVY_TRACING
00177         tr_info("%s (%d): ret=%d", __func__, __LINE__, ret);
00178 #endif
00179         (*ack_requested) = 0;  // Never acknowledge ACK frames
00180         return ret;
00181     }
00182 
00183     switch(dst_addr_mode) {
00184         case 0x00:
00185             ret = true; // no check possible;
00186             break;
00187 
00188         case 0x02:
00189             min_size += 4; // pan id + short dest adr
00190 
00191             if(len < 5) {
00192 #ifdef HEAVY_TRACING
00193                 tr_debug("%s (%d)", __func__, __LINE__);
00194 #endif
00195                 return false;
00196             }
00197 
00198             dst_pan_id = rf_read_16_bit(&rf_rx_buf[3]);
00199             if((dst_pan_id != stored_pan_id) && (dst_pan_id != 0xFFFF)) {
00200 #ifdef HEAVY_TRACING
00201                 tr_debug("%s (%d)", __func__, __LINE__);
00202 #endif
00203                 return false;
00204             }
00205 
00206             if(len < 7) {
00207 #ifdef HEAVY_TRACING
00208                 tr_debug("%s (%d)", __func__, __LINE__);
00209 #endif
00210                 return false;
00211             }
00212 
00213             dst_short_adr = rf_read_16_bit(&rf_rx_buf[5]);
00214             if((dst_short_adr != stored_short_adr) && (dst_short_adr != 0xFFFF)) {
00215 #ifdef HEAVY_TRACING
00216                 tr_debug("%s (%d): %d!=%d", __func__, __LINE__, dst_short_adr, stored_short_adr);
00217 #endif
00218                 return false;
00219             }
00220 
00221             ret = true;
00222             break;
00223 
00224         case 0x03:
00225             min_size += 10; // pan id + dest mac addr
00226 
00227             if(len < 5) {
00228 #ifdef HEAVY_TRACING
00229                 tr_debug("%s (%d)", __func__, __LINE__);
00230 #endif
00231                 return false;
00232             }
00233 
00234             dst_pan_id = rf_read_16_bit(&rf_rx_buf[3]);
00235             if((dst_pan_id != stored_pan_id) && (dst_pan_id != 0xFFFF)) {
00236 #ifdef HEAVY_TRACING
00237                 tr_debug("%s (%d)", __func__, __LINE__);
00238 #endif
00239                 return false;
00240             }
00241 
00242             if(len < 13) {
00243 #ifdef HEAVY_TRACING
00244                 tr_debug("%s (%d)", __func__, __LINE__);
00245 #endif
00246                 return false;
00247             }
00248 
00249             ret = rf_check_mac_address(&rf_rx_buf[5]);
00250 
00251             if(!ret) {
00252 #ifdef HEAVY_TRACING
00253                 tr_debug("%s (%d)", __func__, __LINE__);
00254 #endif
00255                 return false;
00256             }
00257 
00258             break;
00259 
00260         default:
00261             /* not supported */
00262 #ifdef HEAVY_TRACING
00263             tr_debug("%s (%d)", __func__, __LINE__);
00264 #endif
00265             return false;
00266     }
00267 
00268     if(ret && (*ack_requested)) {
00269         rf_rx_sequence = rf_rx_buf[2];
00270     }
00271 
00272 #ifdef HEAVY_TRACING
00273     tr_info("%s (%d), ret=%d, ack=%d", __func__, __LINE__, ret, (*ack_requested));
00274 #endif
00275     return ret;
00276 }
00277 
00278 static uint16_t rf_buffer_len = 0;
00279 static uint8_t rf_sqi;
00280 static int8_t rf_rssi;
00281 /* Note: we are in IRQ context */
00282 static inline void rf_handle_rx_end(void)
00283 {
00284     uint8_t ack_requested = 0;
00285 
00286     /* Get received data */
00287     rf_buffer_len = rf_device->read(rf_rx_buf, MAX_PACKET_LEN);
00288     if(!rf_buffer_len)
00289         return;
00290 
00291 #ifdef HEAVY_TRACING
00292     tr_debug("%s (%d)", __func__, __LINE__);
00293 #endif
00294 
00295     /* Check if packet should be accepted */
00296     if(!rf_check_destination(rf_buffer_len, &ack_requested)) {
00297 #ifdef HEAVY_TRACING
00298         tr_debug("%s (%d)", __func__, __LINE__);
00299 #endif
00300         return;
00301     }
00302 
00303     /* If waiting for ACK, check here if the packet is an ACK to a message previously sent */
00304     if(expecting_ack) {
00305         uint16_t fcf = rf_read_16_bit(rf_rx_buf);
00306         expecting_ack = false;
00307 
00308         if(((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT) == FC_ACK_FRAME) {
00309             /*Send sequence number in ACK handler*/
00310 #ifdef HEAVY_TRACING
00311             tr_debug("%s (%d), len=%u", __func__, __LINE__, (unsigned int)rf_buffer_len);
00312 #endif
00313             rf_handle_ack(rf_rx_buf[2]);
00314             return;
00315         } else {
00316             /*Call PHY TX Done API*/
00317             if(device_driver.phy_tx_done_cb){
00318                 phy_status = PHY_LINK_TX_FAIL;
00319                 rf_send_signal(RF_SIG_CB_TX_DONE);
00320             }
00321         }
00322     }
00323 
00324     /* Kick off ACK sending */
00325     if(ack_requested) {
00326 #ifdef HEAVY_TRACING
00327         tr_debug("%s (%d), len=%u", __func__, __LINE__, (unsigned int)rf_buffer_len);
00328 #endif
00329         rf_send_signal(RF_SIG_ACK_NEEDED);
00330     }
00331 
00332     /* Get link information */
00333     rf_rssi = (int8_t)rf_device->get_last_rssi_dbm();
00334     rf_sqi = (uint8_t)rf_device->get_last_sqi(); // use SQI as link quality
00335 
00336     /* Note: Checksum of the packet must be checked and removed before entering here */
00337     /* TODO - betzw: what to do? */
00338 
00339 #ifdef HEAVY_TRACING
00340     tr_debug("%s (%d)", __func__, __LINE__);
00341 #endif
00342 
00343     /* Send received data and link information to the network stack */
00344     if( device_driver.phy_rx_cb ){
00345         rf_send_signal(RF_SIG_CB_RX_RCVD);
00346     }
00347 }
00348 
00349 /* Note: we are in IRQ context */
00350 static inline void rf_handle_tx_end(void)
00351 {
00352     /* Check if this is an ACK sending which is still pending */
00353     if(rf_ack_sent) {
00354         rf_ack_sent = false;
00355 #ifdef HEAVY_TRACING
00356         tr_debug("%s (%d)", __func__, __LINE__);
00357 #endif
00358         return; // no need to inform stack
00359     }
00360 
00361     /* Transform `need_ack` in `expecting_ack` */
00362     if(need_ack) {
00363         need_ack = false;
00364         expecting_ack = true;
00365     }
00366 
00367     /*Call PHY TX Done API*/
00368     if(device_driver.phy_tx_done_cb){
00369         phy_status = PHY_LINK_TX_SUCCESS;
00370         rf_send_signal(RF_SIG_CB_TX_DONE);
00371     }
00372 }
00373 
00374 /* Note: we might be in IRQ context */
00375 static inline void rf_handle_tx_err(phy_link_tx_status_e phy_val = PHY_LINK_TX_FAIL) {
00376     /*Call PHY TX Done API*/
00377     if(device_driver.phy_tx_done_cb){
00378         need_ack = false;
00379         phy_status = phy_val;
00380         rf_send_signal(RF_SIG_CB_TX_DONE);
00381     }
00382 }
00383 
00384 /* Note: we are in IRQ context */
00385 static void rf_callback_func(int event) {
00386     switch(event) {
00387         case SimpleSpirit1::RX_DONE:
00388             rf_handle_rx_end();
00389             break;
00390         case SimpleSpirit1::TX_DONE:
00391             rf_handle_tx_end();
00392             break;
00393         case SimpleSpirit1::TX_ERR:
00394 #ifdef HEAVY_TRACING
00395             tr_debug("%s (%d): TX_ERR!!!", __func__, __LINE__);
00396 #endif
00397             rf_handle_tx_err();
00398             break;
00399     }
00400 }
00401 
00402 static int8_t rf_trigger_send(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol)
00403 {
00404 #ifndef NDEBUG
00405     debug_if(!(data_length >= 3), "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__);
00406 #endif
00407 
00408     /* Give 'rf_ack_sender' a better chance to run */
00409     Thread::yield();
00410 
00411     /* Get Lock */
00412     rf_if_lock();
00413 
00414     /*Check if transmitter is busy*/
00415     if(rf_device->is_receiving()) { /* betzw - WAS: (rf_device->channel_clear() != 0)), do NOT use this but rather study and enable automatic CCA */
00416 #ifdef HEAVY_TRACING
00417         tr_debug("%s (%d)", __func__, __LINE__);
00418 #endif
00419 
00420         /* Release Lock */
00421         rf_if_unlock();
00422 
00423         /*Return busy*/
00424         return -1;
00425     } else {
00426         uint16_t fcf = rf_read_16_bit(data_ptr);
00427 
00428         /*Check if transmitted data needs to be acked*/
00429         if((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT)
00430             need_ack = true;
00431         else
00432             need_ack = false;
00433 
00434         /*Store the sequence number for ACK handling*/
00435         tx_sequence = *(data_ptr + 2);
00436 
00437         /*Store TX handle*/
00438         mac_tx_handle = tx_handle;
00439 
00440 #ifdef HEAVY_TRACING
00441         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__,
00442                 data_length, tx_handle, tx_sequence, need_ack,
00443                 data_ptr[3], data_ptr[4], data_ptr[5], data_ptr[6],
00444                 data_ptr[7], data_ptr[8], data_ptr[9], data_ptr[10]);
00445 #endif
00446 
00447         /*Send the packet*/
00448         int ret = rf_device->send(data_ptr, data_length);
00449         if(ret != RADIO_TX_OK) {
00450             rf_handle_tx_err(PHY_LINK_CCA_FAIL);
00451         }
00452 
00453         /* Release Lock */
00454         rf_if_unlock();
00455     }
00456 
00457     /*Return success*/
00458     return 0;
00459 }
00460 
00461 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
00462 {
00463     int8_t ret_val = 0;
00464     switch (new_state)
00465     {
00466         /*Reset PHY driver and set to idle*/
00467         case PHY_INTERFACE_RESET:
00468             tr_debug("%s (%d)", __func__, __LINE__);
00469             rf_device->reset_board();
00470             break;
00471             /*Disable PHY Interface driver*/
00472         case PHY_INTERFACE_DOWN:
00473             tr_debug("%s (%d)", __func__, __LINE__);
00474             ret_val = rf_device->off();
00475             if(ret_val != 0) ret_val = -1;
00476             break;
00477             /*Enable PHY Interface driver*/
00478         case PHY_INTERFACE_UP:
00479             ret_val = rf_device->on();
00480             if(ret_val != 0) {
00481                 tr_debug("%s (%d)", __func__, __LINE__);
00482                 ret_val = -1;
00483                 break;
00484             }
00485             tr_debug("%s (%d) - channel: %d", __func__, __LINE__, (int)rf_channel);
00486             rf_device->set_channel(rf_channel);
00487             break;
00488             /*Enable wireless interface ED scan mode*/
00489         case PHY_INTERFACE_RX_ENERGY_STATE:
00490             tr_debug("%s (%d)", __func__, __LINE__);
00491             break;
00492             /*Enable Sniffer state*/
00493         case PHY_INTERFACE_SNIFFER_STATE:
00494             // TODO - if we really need this - WAS: rf_setup_sniffer(rf_channel);
00495             tr_debug("%s (%d)", __func__, __LINE__);
00496             ret_val = -1;
00497             break;
00498         default:
00499             tr_debug("%s (%d)", __func__, __LINE__);
00500             break;
00501     }
00502     return ret_val;
00503 }
00504 
00505 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
00506 {
00507     switch (extension_type)
00508     {
00509         /*Control MAC pending bit for Indirect data transmission*/
00510         case PHY_EXTENSION_CTRL_PENDING_BIT:
00511             tr_debug("%s (%d)", __func__, __LINE__);
00512             break;
00513 
00514             /*Return frame pending status*/
00515         case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
00516             tr_debug("%s (%d)", __func__, __LINE__);
00517             *data_ptr = 0;
00518             break;
00519 
00520             /*Set channel, used for setting channel for energy scan*/
00521         case PHY_EXTENSION_SET_CHANNEL:
00522             tr_debug("%s (%d)", __func__, __LINE__);
00523             break;
00524 
00525             /*Read energy on the channel*/
00526         case PHY_EXTENSION_READ_CHANNEL_ENERGY:
00527             // TODO: *data_ptr = rf_get_channel_energy();
00528             tr_debug("%s (%d)", __func__, __LINE__);
00529             *data_ptr = (int8_t)rf_device->get_last_rssi_dbm();
00530             break;
00531 
00532             /*Read status of the link*/
00533         case PHY_EXTENSION_READ_LINK_STATUS:
00534             // TODO: *data_ptr = rf_get_link_status();
00535             tr_debug("%s (%d)", __func__, __LINE__);
00536             *data_ptr = rf_device->get_last_sqi(); // use SQI as link quality
00537             break;
00538 
00539         default:
00540             tr_debug("%s (%d)", __func__, __LINE__);
00541             break;
00542     }
00543     return 0;
00544 }
00545 
00546 static inline void rf_set_mac_address(uint8_t *ptr) {
00547     tr_debug("%s (%d), adr0=%x, adr1=%x, adr2=%x, adr3=%x, adr4=%x, adr5=%x, adr6=%x, adr7=%x",
00548              __func__, __LINE__,
00549              ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
00550     for(int i = 0; i < 8; i++) {
00551         stored_mac_address[i] = ptr[i];
00552     }
00553 }
00554 
00555 static inline void rf_get_mac_address(uint8_t *ptr) {
00556     for(int i = 0; i < 8; i++) {
00557         ptr[i] = stored_mac_address[i];
00558     }
00559     tr_debug("%s (%d), adr0=%x, adr1=%x, adr2=%x, adr3=%x, adr4=%x, adr5=%x, adr6=%x, adr7=%x",
00560              __func__, __LINE__,
00561              ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
00562 }
00563 
00564 static inline void rf_set_short_adr(uint8_t *ptr) {
00565     stored_short_adr = (ptr[0] << 8) + ptr[1]; // big-endian
00566     tr_debug("%s (%d), adr0=%x, adr1=%x, val=%d",
00567              __func__, __LINE__,
00568              ptr[0], ptr[1], stored_short_adr);
00569 }
00570 
00571 static inline void rf_set_pan_id(uint8_t *ptr) {
00572     stored_pan_id = (ptr[0] << 8) + ptr[1]; // big-endian
00573     tr_debug("%s (%d), adr0=%x, adr1=%x, val=%d",
00574             __func__, __LINE__,
00575             ptr[0], ptr[1], stored_pan_id);
00576 }
00577 
00578 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
00579 {
00580     switch (address_type)
00581     {
00582         /*Set 48-bit address*/
00583         case PHY_MAC_48BIT:
00584             /* Not used in this example */
00585             // betzw - WAS: rf_set_mac_48bit(address_ptr);
00586             break;
00587             /*Set 64-bit address*/
00588         case PHY_MAC_64BIT:
00589             rf_set_mac_address(address_ptr);
00590             break;
00591             /*Set 16-bit address*/
00592         case PHY_MAC_16BIT:
00593             rf_set_short_adr(address_ptr);
00594             break;
00595             /*Set PAN Id*/
00596         case PHY_MAC_PANID:
00597             rf_set_pan_id(address_ptr);
00598             break;
00599     }
00600 
00601     return 0;
00602 }
00603 
00604 static void rf_ack_loop(void) {
00605     static uint16_t buffer[2] = {
00606             (FC_ACK_FRAME << MAC_FCF_FRAME_TYPE_SHIFT),
00607             0x0
00608     };
00609 
00610     tr_debug("%s (%d)", __func__, __LINE__);
00611 
00612     do {
00613         /* Wait for signal */
00614         osEvent event = rf_ack_sender.signal_wait(0);
00615 
00616         if(event.status != osEventSignal) {
00617 #ifdef HEAVY_TRACING
00618             tr_debug("%s (%d)", __func__, __LINE__);
00619 #endif
00620             continue;
00621         }
00622 
00623         int32_t signals = event.value.signals;
00624 
00625 #ifdef HEAVY_TRACING
00626         tr_debug("%s (%d)", __func__, __LINE__);
00627 #endif
00628 
00629         /* Get Lock */
00630         rf_if_lock();
00631 
00632         if(signals & RF_SIG_ACK_NEEDED) {
00633 #ifdef HEAVY_TRACING
00634             tr_debug("%s (%d)", __func__, __LINE__);
00635 #endif
00636 
00637             /* Prepare payload */
00638             uint8_t *ptr = (uint8_t*)&buffer[1];
00639             ptr[0] = rf_rx_sequence;   // Sequence number
00640 
00641             /* Wait for device not receiving */
00642             while(rf_device->is_receiving()) {
00643 #ifdef HEAVY_TRACING
00644                 tr_info("%s (%d)", __func__, __LINE__);
00645 #endif
00646                 wait_us(10);
00647             }
00648 
00649 #ifdef HEAVY_TRACING
00650             tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]);
00651 #endif
00652 
00653             /* Set information that we have sent an ACK */
00654             rf_ack_sent = true;
00655 
00656             /*Send the packet*/
00657             rf_device->send((uint8_t*)buffer, 3, false);
00658 
00659 #ifdef HEAVY_TRACING
00660             tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]);
00661 #endif
00662         }
00663 
00664         if(signals & RF_SIG_CB_TX_DONE) {
00665             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status,
00666                                          (phy_status == PHY_LINK_CCA_FAIL) ? 0xFF : 0, 0);
00667 #ifdef HEAVY_TRACING
00668             tr_debug("%s (%d)", __func__, __LINE__);
00669 #endif
00670         }
00671 
00672         if(signals & RF_SIG_CB_RX_RCVD) {
00673             device_driver.phy_rx_cb(rf_rx_buf, rf_buffer_len, rf_sqi, rf_rssi, rf_radio_driver_id);
00674 #ifdef HEAVY_TRACING
00675             tr_debug("%s (%d)", __func__, __LINE__);
00676 #endif
00677         }
00678 
00679         /* Release Lock */
00680         rf_if_unlock();
00681 
00682 #ifdef HEAVY_TRACING
00683         tr_debug("%s (%d)", __func__, __LINE__);
00684 #endif
00685     } while(true);
00686 }
00687 
00688 void NanostackRfPhySpirit1::rf_init(void) {
00689 #ifndef NDEBUG
00690     osStatus ret;
00691 #endif
00692 
00693     if(rf_device == NULL) {
00694         rf_device = &SimpleSpirit1::CreateInstance(_spi_mosi, _spi_miso, _spi_sclk, _dev_irq, _dev_cs, _dev_sdn, _brd_led);
00695         rf_device->attach_irq_callback(rf_callback_func);
00696 
00697 #ifndef NDEBUG
00698         ret =
00699 #endif
00700                 rf_ack_sender.start(rf_ack_loop);
00701 
00702 #ifndef NDEBUG
00703         debug_if(!(ret == osOK), "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__);
00704 #endif
00705     }
00706 }
00707 
00708 NanostackRfPhySpirit1::NanostackRfPhySpirit1(PinName spi_mosi, PinName spi_miso, PinName spi_sclk,
00709                                              PinName dev_irq,  PinName dev_cs, PinName dev_sdn, PinName brd_led) :
00710     _spi_mosi(spi_mosi),
00711     _spi_miso(spi_miso),
00712     _spi_sclk(spi_sclk),
00713     _dev_irq(dev_irq),
00714     _dev_cs(dev_cs),
00715     _dev_sdn(dev_sdn),
00716     _brd_led(brd_led)
00717 {
00718     /* Nothing to do */
00719     tr_debug("%s (%d)", __func__, __LINE__);
00720 }
00721 
00722 NanostackRfPhySpirit1::~NanostackRfPhySpirit1()
00723 {
00724     /* Nothing to do */
00725     tr_debug("%s (%d)", __func__, __LINE__);
00726 }
00727 
00728 int8_t NanostackRfPhySpirit1::rf_register()
00729 {
00730     tr_debug("%s (%d)", __func__, __LINE__);
00731 
00732     /* Get Lock */
00733     rf_if_lock();
00734 
00735     /* Do some initialization */
00736     rf_init();
00737 
00738     /* Set pointer to MAC address */
00739     device_driver.PHY_MAC = stored_mac_address;
00740 
00741     /* Set driver Name */
00742     device_driver.driver_description = (char*)"Spirit1 Sub-GHz RF";
00743 
00744     /*Type of RF PHY is SubGHz*/
00745     device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
00746 
00747     /*Maximum size of payload*/
00748     device_driver.phy_MTU = MAX_PACKET_LEN;
00749 
00750     /*No header in PHY*/
00751     device_driver.phy_header_length = 0;
00752 
00753     /*No tail in PHY*/
00754     device_driver.phy_tail_length = 0;
00755 
00756     /*Set up driver functions*/
00757     device_driver.address_write = &rf_address_write;
00758     device_driver.extension = &rf_extension;
00759     device_driver.state_control = &rf_interface_state_control;
00760     device_driver.tx = &rf_trigger_send;
00761 
00762     /*Set supported channel pages*/
00763     device_driver.phy_channel_pages = phy_channel_pages;
00764 
00765     //Nullify rx/tx callbacks
00766     device_driver.phy_rx_cb = NULL;
00767     device_driver.phy_tx_done_cb = NULL;
00768     device_driver.arm_net_virtual_rx_cb = NULL;
00769     device_driver.arm_net_virtual_tx_cb = NULL;
00770 
00771     /*Register device driver*/
00772     rf_radio_driver_id = arm_net_phy_register(&device_driver);
00773 
00774     /* Release Lock */
00775     rf_if_unlock();
00776 
00777     tr_debug("%s (%d)", __func__, __LINE__);
00778     return rf_radio_driver_id;
00779 }
00780 
00781 void NanostackRfPhySpirit1::rf_unregister()
00782 {
00783     tr_debug("%s (%d)", __func__, __LINE__);
00784 
00785     /* Get Lock */
00786     rf_if_lock();
00787 
00788     if (rf_radio_driver_id >= 0) {
00789         arm_net_phy_unregister(rf_radio_driver_id);
00790         rf_radio_driver_id = -1;
00791     }
00792 
00793     /* Release Lock */
00794     rf_if_unlock();
00795 }
00796 
00797 void NanostackRfPhySpirit1::get_mac_address(uint8_t *mac)
00798 {
00799     tr_debug("%s (%d)", __func__, __LINE__);
00800 
00801     /* Get Lock */
00802     rf_if_lock();
00803 
00804     if(rf_radio_driver_id >= 0) {
00805         rf_get_mac_address(mac);
00806     } else {
00807         error("NanostackRfPhySpirit1 must be registered to read mac address");
00808     }
00809 
00810     /* Release Lock */
00811     rf_if_unlock();
00812 }
00813 
00814 void NanostackRfPhySpirit1::set_mac_address(uint8_t *mac)
00815 {
00816     tr_debug("%s (%d)", __func__, __LINE__);
00817 
00818     /* Get Lock */
00819     rf_if_lock();
00820 
00821     if(rf_radio_driver_id < 0) {
00822         rf_set_mac_address(mac);
00823     } else {
00824         error("NanostackRfPhySpirit1 cannot change mac address when running");
00825     }
00826 
00827     /* Release Lock */
00828     rf_if_unlock();
00829 }
00830 
00831 #endif /* MBED_CONF_RTOS_PRESENT */
00832 #endif /* MBED_CONF_NANOSTACK_CONFIGURATION */