Wiselib
wiselib.testing/algorithms/synchronization/rbs/rbs_synchronization.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  ** This file is part of the generic algorithm library Wiselib.           **
00003  ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project.      **
00004  **                                                                       **
00005  ** The Wiselib is free software: you can redistribute it and/or modify   **
00006  ** it under the terms of the GNU Lesser General Public License as        **
00007  ** published by the Free Software Foundation, either version 3 of the    **
00008  ** License, or (at your option) any later version.                       **
00009  **                                                                       **
00010  ** The Wiselib is distributed in the hope that it will be useful,        **
00011  ** but WITHOUT ANY WARRANTY; without even the implied warranty of        **
00012  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
00013  ** GNU Lesser General Public License for more details.                   **
00014  **                                                                       **
00015  ** You should have received a copy of the GNU Lesser General Public      **
00016  ** License along with the Wiselib.                                       **
00017  ** If not, see <http://www.gnu.org/licenses/>.                           **
00018  ***************************************************************************/
00019 #ifndef __ALGORITHMS_SYNCHRONIZATION_RDP_H__
00020 #define __ALGORITHMS_SYNCHRONIZATION_RDP_H__
00021 
00022 #include "algorithms/synchronization/rbs/rbs_synchronization_message.h"
00023 #include "util/pstl/vector_static.h"
00024 
00025 #define DEBUG_RBS_SYNCHRONIZATION
00026 
00027 namespace wiselib {
00028 
00034     template<typename OsModel_P,
00035     typename Radio_P,
00036     typename Debug_P,
00037     typename Clock_P>
00038     class rbs {
00039     public:
00040         typedef OsModel_P OsModel;
00041         typedef Radio_P Radio;
00042         typedef Clock_P Clock;
00043         typedef Debug_P Debug;
00044 
00045         typedef typename OsModel_P::Timer Timer;
00046         typedef typename Timer::millis_t millis_t;
00047         typedef typename Clock::time_t time_t;
00048         typedef typename Radio::node_id_t node_id_t;
00049         typedef typename Radio::size_t size_t;
00050         typedef typename Radio::block_data_t block_data_t;
00051         typedef uint8_t message_id_t;
00052 
00053         typedef rbs<OsModel, Radio, Debug, Clock> self_type;
00054         typedef rbsReceiverLocalTimeMessage<OsModel, Radio, Clock> rbsSynchronizationMessage_t;
00055 
00056         typedef vector_static<OsModel, time_t, 10 > receiversLocalTime_t;
00057         typedef typename receiversLocalTime_t::iterator rlt_iterator;
00058 
00061         rbs(bool);
00062         ~rbs();
00064 
00065         void enable(void);
00066 
00067         void disable(void);
00068 
00071         void timer_elapsed(void *userdata);
00074 
00075         void receive(node_id_t from, size_t len, block_data_t *data);
00076 
00077         void init( Radio& radio, Timer& timer, Debug& debug, Clock& clock ) {
00078          radio_ = &radio;
00079          timer_ = &timer;
00080          debug_ = &debug;
00081          clock_ = &clock;
00082       }
00083       
00084       void destruct() {
00085       }
00086         
00087     private:
00088         Radio& radio()
00089         { return *radio_; }
00090         
00091         Timer& timer()
00092         { return *timer_; }
00093         
00094         Debug& debug()
00095         { return *debug_; }
00096         
00097         Clock& clock()
00098         { return *clock_; }
00099         
00100         Radio * radio_;
00101         Timer * timer_;
00102         Debug * debug_;
00103         Clock * clock_;  
00104       
00105         inline void send_referenceBroadcast();
00106 
00107         inline void send_localTime();
00108 
00109         enum rbsSynchronizationMsgIds {
00110             RbsReferenceBroadcast = 150,
00111             RbsReceiversLocalTime = 151,
00112         };
00113 
00114         rbsSynchronizationMessage_t *rbsLocalTimeMessage;
00115         rbsSynchronizationMessage_t *rbsReferenceBroadCastMessage;
00116 
00117         receiversLocalTime_t receiversLocalTime;
00118 
00119         millis_t startup_time_;
00120         millis_t resynch_period_;
00121         millis_t receiver_wait_time_;
00122 
00123         bool reference_node_;
00124         bool synchronized_;
00125     };
00126 
00127     template<typename OsModel_P,
00128     typename Radio_P,
00129     typename Debug_P,
00130     typename Clock_P>
00131     rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00132     rbs(bool isBroadcaster = false)
00133     : startup_time_(1000),
00134     resynch_period_(10000),
00135     receiver_wait_time_(1000),
00136     reference_node_(isBroadcaster),
00137     synchronized_(false) {
00138     }
00139 
00140 
00141     // -----------------------------------------------------------------------
00142     // -----------------------------------------------------------------------
00143 
00144     template<typename OsModel_P,
00145     typename Radio_P,
00146     typename Debug_P,
00147     typename Clock_P>
00148     rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00149     ~rbs() {
00150 
00151     }
00152     // -----------------------------------------------------------------------
00153 
00154     template<typename OsModel_P,
00155     typename Radio_P,
00156     typename Debug_P,
00157     typename Clock_P>
00158     void rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00159     enable(void) {
00160         radio().enable_radio();
00161         radio().template reg_recv_callback<self_type, &self_type::receive > (this);
00162 
00163         if (reference_node_) {
00164 #ifdef DEBUG_RBS_SYNCHRONIZATION
00165             debug().debug("%i: RbsSynchronization boots as reference node\n", radio().id());
00166 #endif          
00167             timer().template set_timer<self_type, &self_type::timer_elapsed > (
00168                     startup_time_, this, 0);
00169         } else {
00170 
00171 #ifdef DEBUG_RBS_SYNCHRONIZATION
00172             debug().debug("%i: RbsSynchronization boots as receiver node\n", radio().id());
00173 #endif
00174         }
00175 
00176         rbsLocalTimeMessage = new rbsSynchronizationMessage_t(RbsReceiversLocalTime);
00177         rbsReferenceBroadCastMessage = new rbsSynchronizationMessage_t(RbsReferenceBroadcast);
00178     }
00179     // -----------------------------------------------------------------------
00180 
00181     template<typename OsModel_P,
00182     typename Radio_P,
00183     typename Debug_P,
00184     typename Clock_P>
00185     void rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00186     disable(void) {
00187 
00188     }
00189 
00190     template<typename OsModel_P,
00191     typename Radio_P,
00192     typename Debug_P,
00193     typename Clock_P>
00194     void rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00195     timer_elapsed(void *userdata) {
00196         
00197         if (reference_node_) {
00198 #ifdef DEBUG_RBS_SYNCHRONIZATION
00199             debug().debug("%i: RbsSynchronization sending reference broadcast\n", radio().id());
00200 #endif
00201             send_referenceBroadcast();
00202             timer().template set_timer<self_type, &self_type::timer_elapsed > (
00203                     resynch_period_, this, 0);
00204         } else {
00205 
00206 #ifdef DEBUG_RBS_SYNCHRONIZATION
00207             debug().debug("%i: RbsSynchronization synchronizing node using %d receivers\n", radio().id(), receiversLocalTime.size() - 1);
00208 #endif
00209             // Do not attemp to synchronize if we received
00210             // to few replays form receivers
00211             if (receiversLocalTime.size() < 2)
00212                 return;
00213 
00214             time_t offset = 0;
00215 
00216             rlt_iterator it = receiversLocalTime.begin();
00217             time_t local_time = it[0];
00218 
00219             for (uint8_t i = 1; i < receiversLocalTime.size(); i++)
00220                 offset = offset + (local_time - it[i]);
00221 
00222             clock().set_time(clock().time() + offset);
00223             receiversLocalTime.clear();
00224             synchronized_ = true;
00225 #ifdef DEBUG_RBS_SYNCHRONIZATION
00226             debug().debug("synchronized!\n");
00227 #endif
00228 
00229         }
00230     }
00231 
00232 
00233     // -----------------------------------------------------------------------
00234 
00235     template<typename OsModel_P,
00236     typename Radio_P,
00237     typename Debug_P,
00238     typename Clock_P>
00239     void rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00240     send_referenceBroadcast() {
00241 
00242         radio().send(radio().BROADCAST_ADDRESS, rbsReferenceBroadCastMessage->buffer_size(), (uint8_t*) rbsReferenceBroadCastMessage);
00243     }
00244 
00245     template<typename OsModel_P,
00246     typename Radio_P,
00247     typename Debug_P,
00248     typename Clock_P>
00249     void rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00250     send_localTime() {
00251         
00252         time_t now = clock().time();
00253         rbsLocalTimeMessage->set_time(now);
00254         radio().send(radio().BROADCAST_ADDRESS, rbsLocalTimeMessage->buffer_size(), (uint8_t*) rbsLocalTimeMessage);
00255         receiversLocalTime.push_back(now);
00256     }
00257 
00258     // -----------------------------------------------------------------------
00259 
00260     template<typename OsModel_P,
00261     typename Radio_P,
00262     typename Debug_P,
00263     typename Clock_P>
00264     void rbs<OsModel_P, Radio_P, Debug_P, Clock_P>::
00265     receive(node_id_t from, size_t len, block_data_t *data) {
00266         
00267         if (from == radio().id())
00268             return;
00269 
00270         uint8_t msg_id = *data;
00271         if ((msg_id == RbsReferenceBroadcast) && !reference_node_) {
00272 #ifdef DEBUG_RBS_SYNCHRONIZATION
00273             debug().debug("%i: RbsSynchronization received Reference Broadcast from node %i\n",radio().id() ,from);
00274 #endif
00275 
00276             synchronized_ = false;
00277             send_localTime();
00278         } else if (msg_id == RbsReceiversLocalTime && !reference_node_) {
00279 #ifdef DEBUG_RBS_SYNCHRONIZATION
00280             debug().debug("%i: RbsSynchronization received local time from node %i\n",radio().id() ,from);
00281 #endif
00282             
00283             rbsSynchronizationMessage_t *msg = (rbsSynchronizationMessage_t *) data;
00284 
00285             if (receiversLocalTime.size() == 0)
00286                 timer().template set_timer<self_type, &self_type::timer_elapsed > (
00287                     receiver_wait_time_, this, 0);
00288 
00289             receiversLocalTime.push_back(msg->time());
00290         }
00291 
00292     }
00293 
00294 }
00295 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines