/** * @file * @brief This file implements the MLME-SYNC.request. * * $Id: sync.c,v 1.24 2006/12/22 07:27:25 sschneid Exp $ */ /** * \author * Atmel Corporation: http://www.atmel.com * Support email: avr@atmel.com */ /* * Copyright (c) 2006, Atmel Corporation All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The name of ATMEL may not be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* === Includes ============================================================ */ #include "mac.h" #include "timer_const.h" #if APP_TYPE >= APP_L2 || defined(DOXYGEN) /* === Globals ============================================================= */ /* === Prototypes ========================================================== */ /* === Implementation ====================================================== */ /** * @brief This function implements the MLME-SYNC request. * * The MLME-SYNC.request primitive requests to synchronize with the coordinator by * acquiring and, if specified, tracking its beacons. * The MLME-SYNC.request primitive is generated by the next higher layer of a device * on a beacon-enabled PAN and issued to its MLME to synchronize with the coordinator. * * Enable receiver and search for beacons for at most an interval of * [aBaseSuperframeDuration * (2^(n) +1)] symbols where n is the value of * macBeaconOrder. If a beacon frame containing * the current PAN identifier of the device is not received, the MLME shall * repeat this search. Once the number of missed beacons reaches * aMaxLostBeacons, the MLME shall notify the next higher layer by issuing the * MLME-SYNC-LOSS.indication primitive with a loss reason of BEACON_LOSS. * * @param m Pointer to the sync request parameters */ void mlme_sync_request(uint8_t *m) { plme_set_trx_state_req_t txr; mlme_sync_req_t *syr = (mlme_sync_req_t *)m; uint8_t psr_buffer[sizeof(plme_set_req_t) + sizeof(uint8_t)]; plme_set_req_t *psr = (plme_set_req_t *)psr_buffer; if (mac_i_pan_coordinator) { return; } // We need to be in a non-transient state to be able to properly process a sync request if (!((mac_state == MAC_A) || (mac_state == MAC_Tracking_Beacon))) { mac_sync_loss(MAC_BEACON_LOSS); return; } // Stop potential timers for beacon tracking bios_stoptimer(T_bt_missedbeacon); bios_stoptimer(T_btp); // Set the channel, we'll pick up the sync in an intermediate function. psr->size = sizeof(plme_set_req_t) - sizeof(psr->size) + sizeof(uint8_t); psr->cmdcode = PLME_SET_REQUEST; psr->PIBAttribute = phyCurrentChannel; psr->data[0] = sizeof(uint8_t); psr->data[1] = syr->LogicalChannel; bios_pushback_event((uint8_t *) psr); // Turn the radio on. txr.size = sizeof(plme_set_trx_state_req_t) - sizeof(txr.size); txr.cmdcode = PLME_SET_TRX_STATE_REQUEST; txr.state = PHY_RX_ON; bios_pushback_event((uint8_t *) &txr); // Set mac_state to MAC_Tracking_Beacon. This will cause the FSM to pick // up beacon processing in data_ind.c when a beacon is received. // Record a global track beacon by setting the mac_state and mac_trackBeacons. if(syr->TrackBeacon) { mac_trackBeacons = SYNC_CONTINUOUSLY; mac_state = MAC_Tracking_Beacon; } else { mac_trackBeacons = SYNC_ONCE; // we need to restore mac state from continuous beacon tracking to associated state // or we will keep tracking forever mac_state = MAC_A; } mac_missed_beacons = 0; if (!bios_starttimer(T_bt_missedbeacon, MAC_CALCULATE_SYMBOL_TIME_BEACONINTERVAL(mac_pib_macBeaconOrder))) { // Scan timer that checks whether we are actually receiving beacon frames could not be started // Indicate sync loss indication mac_sync_loss(MAC_BEACON_LOSS); mac_trackBeacons = SYNC_NEVER; mac_state = MAC_A; } } /** * @brief Timer function after sync request to wake up radio at beacon time * * This function implements the RX timer service function during sync and enables the receiver before * the next beacon reception is expected. */ void mac_t_tracking_beacons(void) { plme_set_trx_state_req_t txr; if(mac_trackBeacons != SYNC_NEVER) { bios_stoptimer(T_btp); } // Turn the radio on. txr.size = sizeof(plme_set_trx_state_req_t) - sizeof(txr.size); txr.cmdcode = PLME_SET_TRX_STATE_REQUEST; txr.state = PHY_RX_ON; bios_pushback_event((uint8_t *) &txr); } /** * @brief Timer function after sync request to count missed beacon frames * * This function implements the counting of missed beacon frames during sync. */ void mac_t_missed_beacons(void) { if (mac_state == MAC_W) { // have been disassociated meanwhile and are in idle state mac_sync_loss(MAC_BEACON_LOSS); mac_trackBeacons = SYNC_NEVER; } if(mac_trackBeacons != SYNC_NEVER) { mac_missed_beacons++; if (mac_missed_beacons >= aMaxLostBeacons) { mac_sync_loss(MAC_BEACON_LOSS); mac_trackBeacons = SYNC_NEVER; mac_state = MAC_A; } else { uint32_t duration = MAC_CALCULATE_SYMBOL_TIME_BEACONINTERVAL(mac_pib_macBeaconOrder); /* Wait a bit longer, duration = beacon interval * 1.25 */ if (!bios_starttimer(T_bt_missedbeacon, duration + (duration >> 2))) { // Scan timer that checks whether we are actually receiving beacon frames could not be started // Indicate sync loss indication mac_sync_loss(MAC_BEACON_LOSS); mac_trackBeacons = SYNC_NEVER; mac_state = MAC_A; } } } } /** * @brief Function to initiate a MLME-SYNC-LOSS.indication to the higher layer * * @param uint8_t loss_reason LossReason to be indicated within the primitive */ void mac_sync_loss(uint8_t loss_reason) { mlme_sync_loss_ind_t msli; msli.size = sizeof(mlme_sync_loss_ind_t) - sizeof(msli.size); msli.cmdcode = MLME_SYNC_LOSS_INDICATION; msli.LossReason = loss_reason; bios_pushback_event(&msli); } #endif // APP_TYPE >= APP_L2 || defined(DOXYGEN) /* EOF */