Wiselib
|
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