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

Dependents:   HelloMQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackRfPhySpirit1.cpp Source File

NanostackRfPhySpirit1.cpp

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