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_TPSN_SYNCHRONIZATION_H__ 00020 #define __ALGORITHMS_SYNCHRONIZATION_TPSN_SYNCHRONIZATION_H__ 00021 00022 #include "algorithms/synchronization/hrts/hrts_synchronization_message.h" 00023 #include "algorithms/neighborhood_discovery/echo.h" 00024 #include "util/pstl/vector_static.h" 00025 00026 #define DEBUG_TPSN_SYNCHRONIZATION 00027 #define DEBUG_TPSN_SYNCHRONIZATION_ISENSE 00028 // #define DEBUG_TPSN_SYNCHRONIZATION_SHAWN 00029 00030 namespace wiselib 00031 { 00032 00038 template<typename OsModel_P, 00039 typename Radio_P = typename OsModel_P::Radio, 00040 typename Debug_P = typename OsModel_P::Debug, 00041 typename Clock_P = typename OsModel_P::Clock, 00042 uint16_t MAX_NODES = 32> 00043 class TpsnSynchronization 00044 { 00045 public: 00046 typedef OsModel_P OsModel; 00047 typedef Radio_P Radio; 00048 typedef Debug_P Debug; 00049 typedef Clock_P Clock; 00050 00051 typedef typename OsModel_P::Timer Timer; 00052 typedef Echo<OsModel, Radio, Timer, Debug> Neighborhood; 00053 00054 typedef TpsnSynchronization<OsModel, Radio, Debug, Clock, MAX_NODES> self_type; 00055 typedef TpsnSynchronizationMessage<OsModel, Radio, Clock> SynchronizationMessage; 00056 00057 typedef typename Radio::node_id_t node_id_t; 00058 typedef typename Radio::size_t size_t; 00059 typedef typename Radio::block_data_t block_data_t; 00060 static const uint8_t NODE_ID_SIZE = sizeof( node_id_t ); 00061 00062 typedef typename Timer::millis_t millis_t; 00063 00064 typedef typename Clock::time_t time_t; 00065 static const uint8_t TIME_SIZE = sizeof( time_t ); 00066 00070 00073 TpsnSynchronization(); 00074 ~TpsnSynchronization(); 00076 00079 void enable( void ); 00080 void disable( void ); 00081 inline void set_root( void ) 00082 { level_ = 0; } 00084 00087 void timer_elapsed( void *userdata ); 00089 00092 void receive( node_id_t from, size_t len, block_data_t *data ); 00094 00095 inline void set_root_startup_time( millis_t root_startup_time ) 00096 { root_startup_time_ = root_startup_time; }; 00097 00098 inline void set_tree_construction_time( millis_t tree_construction_time ) 00099 { tree_construction_time_ = tree_construction_time; }; 00100 00101 inline void set_random_interval_time( millis_t random_interval_time ) 00102 { random_interval_time_ = random_interval_time; }; 00103 00104 void init( Radio& radio, Timer& timer, Debug& debug, Clock& clock ) { 00105 radio_ = &radio; 00106 timer_ = &timer; 00107 debug_ = &debug; 00108 clock_ = &clock; 00109 neighborhood_.init(radio_, clock_, timer_, debug_); 00110 } 00111 00112 void destruct() { 00113 } 00114 00115 private: 00116 Radio& radio() 00117 { return *radio_; } 00118 00119 Timer& timer() 00120 { return *timer_; } 00121 00122 Debug& debug() 00123 { return *debug_; } 00124 00125 Clock& clock() 00126 { return *clock_; } 00127 00128 Radio * radio_; 00129 Timer * timer_; 00130 Debug * debug_; 00131 Clock * clock_; 00132 00133 void send_sync_pulse(); 00134 00137 // TODO: standarize msg ids 00138 enum TpsnSynchronizationMsgIds { 00139 TpsnMsgIdBeginSync = 230, 00140 TpsnMsgIdReply = 231, 00141 TpsnMsgIdDiffSync = 232, 00142 }; 00143 00144 SynchronizationMessage message; 00145 Neighborhood neighborhood_; 00146 00147 int8_t level_; 00148 bool built_tree_; 00149 time_t t1_; 00150 millis_t timeout_; 00151 bool propagated_; 00152 }; 00153 // ----------------------------------------------------------------------- 00154 // ----------------------------------------------------------------------- 00155 // ----------------------------------------------------------------------- 00156 template<typename OsModel_P, 00157 typename Radio_P, 00158 typename Debug_P, 00159 typename Clock_P, 00160 uint16_t MAX_NODES> 00161 TpsnSynchronization<OsModel_P, Radio_P, Debug_P, Clock_P, MAX_NODES>:: 00162 TpsnSynchronization() 00163 : level_ ( -1 ), 00164 timeout_ ( 1000 ), 00165 propagated_ ( false ) 00166 {}; 00167 // ----------------------------------------------------------------------- 00168 template<typename OsModel_P, 00169 typename Radio_P, 00170 typename Debug_P, 00171 typename Clock_P, 00172 uint16_t MAX_NODES> 00173 TpsnSynchronization<OsModel_P, Radio_P, Debug_P, Clock_P, MAX_NODES>:: 00174 ~TpsnSynchronization() 00175 { 00176 #ifdef DEBUG_TPSN_SYNCHRONIZATION 00177 debug().debug( "TpsnSynchronization Destroyed\n" ); 00178 #endif 00179 }; 00180 // ----------------------------------------------------------------------- 00181 template<typename OsModel_P, 00182 typename Radio_P, 00183 typename Debug_P, 00184 typename Clock_P, 00185 uint16_t MAX_NODES> 00186 void 00187 TpsnSynchronization<OsModel_P, Radio_P, Debug_P, Clock_P, MAX_NODES>:: 00188 enable( void ) 00189 { 00190 neighborhood_.enable(); 00191 if ( level_ != -1 and not propagated_ ) 00192 { 00193 #ifdef DEBUG_TPSN_SYNCHRONIZATION 00194 debug().debug( "%i: TpsnSynchronization Boots as Root\n", radio().id() ); 00195 #endif 00196 start_propagation(); 00197 timer().template set_timer<self_type, &self_type::enable>( 00198 timeout_, this, 0 ); 00199 } 00200 } 00201 // ----------------------------------------------------------------------- 00202 template<typename OsModel_P, 00203 typename Radio_P, 00204 typename Debug_P, 00205 typename Clock_P, 00206 uint16_t MAX_NODES> 00207 void 00208 TpsnSynchronization<OsModel_P, Radio_P, Debug_P, Clock_P, MAX_NODES>:: 00209 disable( void ) 00210 { 00211 #ifdef DEBUG_TPSN_SYNCHRONIZATION 00212 debug().debug( "%i: Called TpsnSynchronization::disable\n", radio().id() ); 00213 #endif 00214 } 00215 // ----------------------------------------------------------------------- 00216 template<typename OsModel_P, 00217 typename Radio_P, 00218 typename Debug_P, 00219 typename Clock_P, 00220 uint16_t MAX_NODES> 00221 void 00222 TpsnSynchronization<OsModel_P, Radio_P, Debug_P, Clock_P, MAX_NODES>:: 00223 receive( node_id_t from, size_t len, block_data_t *data ) 00224 { 00225 time_t t = clock().time(); 00226 if ( from == radio().id() ) 00227 return; 00228 uint8_t msg_id = *data; 00229 message = *((Synchronization *) data); 00230 #ifdef DEBUG_TPSN_SYNCHRONIZATION 00231 debug().debug( "%i: Received message from %i and msg_id is %d\n", radio().id(), from, msg_id ); 00232 #endif 00233 if ( msg_id == TpsnMsgIdBeginSync ) 00234 { 00235 uint8_t level = *data; 00236 if ( level_ != -1 and level_ > message.level ) 00237 return; 00238 t1 = message.t1(); 00239 if (message.receiver == radio().id()) { 00240 message.set_msg_id(TpsnMsgIdReply); 00241 message.set_t1(t); 00242 message.set_t2(clock().time()); 00243 radio().send( from, sizeof( SynchronizationMessage ), (uint8_t*)&message ); 00244 } 00245 } 00246 else if ( msg_id == TpsnMsgIdReply ) 00247 { 00248 time_t d2 = ((message.t1() - t1) - (t - message.t2()))/2; 00249 message.set_msg_id(TpsnMsgIdDiffSync); 00250 message.set_t1(message.t1()); 00251 message.set_t2(d2); 00252 radio().send( radio().BROADCAST_ADDRESS, sizeof( SynchronizationMessage ), (uint8_t*)&message ); 00253 } 00254 else if ( msg_id == TpsnMsgIdDiffSync ) 00255 { 00256 clock().set_time(clock_time()+message.t2()+message.t1()-t1); 00257 } 00258 } 00259 // ----------------------------------------------------------------------- 00260 template<typename OsModel_P, 00261 typename Radio_P, 00262 typename Debug_P, 00263 typename Clock_P, 00264 uint16_t MAX_NODES> 00265 void 00266 TpsnSynchronization<OsModel_P, Radio_P, Debug_P, Clock_P, MAX_NODES>:: 00267 start_propagation( ) 00268 { 00269 if (neighborhood_.neighbors_.empty()) 00270 propagated_ = true; 00271 else { 00272 message.set_msg_id(TpsnMsgIdBeginSync); 00273 message.set_receiver(neighborhood_.neighbors_[0]); 00274 t1 = clock().time(); 00275 message.set_t1( t1 ); 00276 radio().send( radio().BROADCAST_ADDRESS, sizeof( SynchronizationMessage ), (uint8_t*)&message ); 00277 } 00278 } 00279 } 00280 #endif