Wiselib
|
00001 /* 00002 * File: cluster_radio.h 00003 * Author: Amaxilatis 00004 * 00005 * Created on March 11 2011 00006 */ 00007 00008 #ifndef __CLUSTER_RADIO__ 00009 #define __CLUSTER_RADIO__ 00010 00011 #include "algorithms/cluster/clustering_types.h" 00012 #include "util/base_classes/radio_base.h" 00013 00014 #undef DEBUG 00015 // Uncomment to enable Debug 00016 #define DEBUG 00017 #ifdef DEBUG 00018 //#define DEBUG_CLUSTERRADIO 00019 //#define DEBUG_CLUSTERRADIO_EXTRA 00020 //#define DEBUG_CLUSTERRADIO_RECEIVED 00021 //#define DEBUG_CLUSTERRADIO_PAYLOADS 00022 #endif 00023 00024 00025 namespace wiselib { 00026 00027 template<typename OsModel_P, typename Radio_P, typename ND_P, typename Clustering_P> 00028 class ClusterRadio 00029 : public RadioBase < OsModel_P, 00030 typename Radio_P::node_id_t, 00031 typename Radio_P::size_t, 00032 typename Radio_P::block_data_t> { 00033 public: 00034 //TYPEDEFS 00035 typedef OsModel_P OsModel; 00036 // os modules 00037 typedef Radio_P Radio; 00038 typedef typename OsModel::Timer Timer; 00039 typedef typename OsModel::Debug Debug; 00040 typedef Clustering_P Clustering; 00041 typedef ND_P ND; 00042 00043 // self type 00044 typedef ClusterRadio<OsModel_P, Radio_P, ND_P, Clustering_P> self_type; 00045 00046 // data types 00047 typedef typename Radio::node_id_t node_id_t; 00048 typedef node_id_t cluster_id_t; 00049 typedef typename Radio::size_t size_t; 00050 typedef typename Radio::block_data_t block_data_t; 00051 typedef uint16_t cluster_level_t; //quite useless within current scheme, supported for compatibility issues 00052 00053 struct RTentry { 00054 cluster_id_t dest_cluster_; 00055 size_t distance; 00056 node_id_t link; 00057 bool exists_; 00058 }; 00059 00060 enum SpecialNodeIds { 00061 BROADCAST_ADDRESS = Radio::BROADCAST_ADDRESS, 00062 NULL_NODE_ID = Radio::NULL_NODE_ID 00064 }; 00065 00066 typedef RTentry RTentry_t; 00067 00068 //typedef wiselib::vector_static<OsModel, RTentry_t, 7 > ClusterRoutingTable; 00069 //typedef typename ClusterRoutingTable::iterator ClusterRoutingTable_iterator_t; 00070 00071 struct ND_payload { 00072 cluster_id_t cluster; 00073 size_t dist; 00074 node_id_t link; 00075 }; 00076 00077 typedef ND_payload ND_payload_t; 00078 00079 enum event_ids { 00080 ADD_ROUTE = 1, 00081 REMOVE_ROUTE = 2 00082 }; 00083 00084 typedef delegate4<void, uint8_t, node_id_t, cluster_id_t, node_id_t> notify_delegate_t; 00085 #define MAX_EVENT_RECEIVERS 2 00086 typedef vector_static<OsModel, notify_delegate_t, MAX_EVENT_RECEIVERS> NotifyCallbackVector; 00087 typedef typename NotifyCallbackVector::iterator NotifyCallbackVectorIterator; 00088 00089 00090 // typedef wiselib::vector_static<OsModel, node_id_t, 30 > vector_t; 00091 00092 /* 00093 * Constructor 00094 * */ 00095 ClusterRadio() : 00096 enabled_(false)//CDOWN, enable_debug_(false) 00097 { 00098 } 00099 00100 /* 00101 * Destructor 00102 * */ 00103 ~ClusterRadio() { 00104 } 00105 00106 /* 00107 * INIT 00108 * initializes the values of radio timer and debug 00109 */ 00110 void init(Radio& radiot, Timer& timert, Debug& debugt, ND& nd, Clustering& clusteringt) { 00111 radio_ = &radiot; 00112 timer_ = &timert; 00113 debug_ = &debugt; 00114 clustering_ = &clusteringt; 00115 clustering_->template reg_state_changed_callback<self_type, &self_type::reset > (this); 00116 clustering_->template reg_notify_cradio<self_type, &self_type::notify_cradio > (this); 00117 00118 nd_ = &nd; 00119 00120 uint8_t flags = ND::NEW_PAYLOAD_BIDI | ND::DROPPED_NB | ND::LOST_NB_BIDI; 00121 //CDOWN nd_->template reg_event_callback<self_type, &self_type::nd_callback > (CLRADIO, flags, this); 00122 nd_->register_payload_space((uint8_t) CLRADIO); 00123 00124 notify_callbacks_.clear(); 00125 00126 00127 for (size_t i = 0; i < 10; i++) { 00128 rt_[i].dest_cluster_ = 0xffff; 00129 } 00130 00131 } 00132 00133 /* set functions */ 00134 00135 void reg_debug_callback() { 00136 // reg_event_callback<self_type, &self_type::debug_callback > (this); 00137 // enable_debug_ = true; 00138 } 00139 00140 00141 // -------------------------------------------------------------------- 00142 00143 template<class T, void(T::*TMethod)(uint8_t, node_id_t, cluster_id_t, node_id_t) > 00144 uint8_t reg_event_callback(T *obj_pnt) { 00145 00146 if (notify_callbacks_.empty()) 00147 notify_callbacks_.assign(MAX_EVENT_RECEIVERS, notify_delegate_t()); 00148 00149 for (NotifyCallbackVectorIterator 00150 it = notify_callbacks_.begin(); 00151 it != notify_callbacks_.end(); 00152 it++) { 00153 if ((*it) == notify_delegate_t()) { 00154 (*it) = notify_delegate_t::template from_method<T, TMethod > (obj_pnt); 00155 return 0; 00156 } 00157 } 00158 00159 /* for (unsigned int i = 0; i < notify_callbacks_.size(); ++i) { 00160 if (notify_callbacks_.at(i) == notify_delegate_t()) { 00161 notify_callbacks_.at(i) = notify_delegate_t::template from_method<T, TMethod > (obj_pnt); 00162 return i; 00163 } 00164 } 00165 */ 00166 return -1; 00167 } 00168 // -------------------------------------------------------------------- 00169 00170 int unreg_event_callback(int idx) { 00171 notify_callbacks_.at(idx) = notify_delegate_t(); 00172 return idx; 00173 } 00174 // -------------------------------------------------------------------- 00175 00176 void notify_listeners(uint8_t event, node_id_t from, cluster_id_t cluster, node_id_t link) { 00177 for (NotifyCallbackVectorIterator it = notify_callbacks_.begin(); 00178 it != notify_callbacks_.end(); ++it) { 00179 if (*it != notify_delegate_t()) (*it)(event, from, cluster, link); 00180 00181 } 00182 // debug_callback(event, from, cluster, link); 00183 } 00184 00185 void present_neighbors(void) { 00186 if (!enabled_) return; 00187 //for (ClusterRoutingTable_iterator_t it = rt_.begin(); it != rt_.end(); it++) { 00188 for (size_t i = 0; i < 10; i++) { 00189 if (rt_[i].dest_cluster_ != 0xffff) { 00190 //debug().debug("%x -> %x -> %x in %d exits:%d", radio().id(), rt_[i].link, rt_[i].dest_cluster_, rt_[i].distance, rt_[i].exists_); 00191 } 00192 } 00193 } 00194 00195 /* 00196 * Enable 00197 * enables the mbfsclustering module 00198 * enable chd it and jd modules 00199 * initializes values 00200 * registers callbacks 00201 * calls find head to start clustering 00202 * */ 00203 inline void enable() { 00204 00205 if (enabled_) 00206 return; 00207 //set as enabled 00208 enabled_ = true; 00209 gateway_connections_ = 0; 00210 00211 for (size_t i = 0; i < 10; i++) { 00212 rt_[i].dest_cluster_ = 0xffff; 00213 } 00214 #ifdef DEBUG_CLUSTERRADIO 00215 debug().debug("CLradio::Enable::%x::", radio().id()); 00216 #ifdef SHAWN 00217 debug().debug("\n"); 00218 #endif 00219 #endif 00220 // receive receive callback 00221 receive_callback_id_ = radio().template reg_recv_callback<self_type, &self_type::receive > (this); 00222 00223 timer().template set_timer<self_type, &self_type::clean_lists > ( 00224 100 * 1000, this, (void *) 0); 00225 } 00226 00227 int connections() { 00228 if (!enabled_)return 0; 00229 size_t len = 0; 00230 for (size_t i = 0; i < 10; i++) { 00231 if (rt_[i].dest_cluster_ != 0xffff) { 00232 len++; 00233 } 00234 } 00235 return len; 00236 } 00237 00238 void clean_lists(void * a) { 00239 // present_neighbors(); 00240 for (size_t i = 0; i < 10; i++) { 00241 if (rt_[i].exists_ == false) { 00242 if (rt_[i].dest_cluster_ != 0xffff) { 00243 notify_listeners(REMOVE_ROUTE, radio().id(), rt_[i].dest_cluster_, rt_[i].link); 00244 //debug().debug("CLradio::Node%x::RemoveRoute::to%x::through%x::%d::", radio().id(), rt_[i].dest_cluster_, rt_[i].link, connections()); 00245 rt_[i].dest_cluster_ = 0xffff; 00246 } 00247 } 00248 rt_[i].exists_ = false; 00249 } 00250 timer().template set_timer<self_type, &self_type::clean_lists > ( 00251 9000, this, (void *) 0); 00252 } 00253 00254 void send(cluster_id_t destination, size_t len, uint8_t * msg) { 00255 if (!enabled_) return ; 00256 00257 if (destination == Radio::BROADCAST_ADDRESS) { 00258 00259 00260 // debug().debug("CLradio::Send::from%x::to%x::", radio().id(), destination); 00261 #ifdef DEBUG_CLUSTERRADIO 00262 debug().debug("CLradio::Send::from%x::to%x::", radio().id(), destination); 00263 #ifdef SHAWN 00264 debug().debug("\n"); 00265 #endif 00266 #endif 00267 00268 //for (ClusterRoutingTable_iterator_t it = rt_.begin(); it != rt_.end(); it++) { 00269 for (size_t i = 0; i < 10; i++) { 00270 if (rt_[i].dest_cluster_ != 0xffff && rt_[i].dest_cluster_ != radio().NULL_NODE_ID) { 00271 send(rt_[i].dest_cluster_, len, msg); 00272 } 00273 } 00274 00275 } else { 00276 00277 // debug().debug("CLradio::Send::from%x::to%x::", radio().id(), destination); 00278 #ifdef DEBUG_CLUSTERRADIO 00279 debug().debug("CLradio::Send::from%x::to%x::", radio().id(), destination); 00280 #ifdef SHAWN 00281 debug().debug("\n"); 00282 #endif 00283 #endif 00284 00285 00286 node_id_t next_link = Radio::NULL_NODE_ID; 00287 00288 //for (ClusterRoutingTable_iterator_t it = rt_.begin(); it != rt_.end(); it++) { 00289 for (size_t i = 0; i < 10; i++) { 00290 if (rt_[i].dest_cluster_ != 0xffff) { 00291 if (rt_[i].dest_cluster_ == destination) { 00292 next_link = rt_[i].link; 00293 break; 00294 } 00295 } 00296 } 00297 00298 if (next_link != Radio::NULL_NODE_ID) { 00299 00300 ClusterRadioMsg<OsModel, Radio> mess; 00301 mess.set_source(clustering().cluster_id()); 00302 mess.set_destination(destination); 00303 mess.set_payload(msg, len); 00304 radio().send(next_link, mess.length(), (uint8_t*) & mess); 00305 00306 // debug().debug("CLradio::Route2KNOWN::from%x::to%x::through%x::len%d::", radio().id(), destination, next_link, len); 00307 #ifdef DEBUG_CLUSTERRADIO 00308 debug().debug("CLradio::Route2KNOWN::from%x::to%x::through%x::len%d::", radio().id(), destination, next_link, len); 00309 #ifdef SHAWN 00310 debug().debug("\n"); 00311 #endif 00312 #else 00313 // if (enable_debug_) { 00314 debug().debug("CLRS;%x;%d;%x;%x", radio().id(), mess.msg_id(), next_link,msg[0+3]); 00315 // } 00316 #endif 00317 00318 } else { 00319 00320 00321 // debug().debug("CLradio::UnknownRoute::from%x::to%x::len%x::", radio().id(), destination, len); 00322 #ifdef DEBUG_CLUSTERRADIO 00323 debug().debug("CLradio::UnknownRoute::from%x::to%x::len%x::", radio().id(), destination, len); 00324 #ifdef SHAWN 00325 debug().debug("\n"); 00326 #endif 00327 #endif 00328 } 00329 } 00330 } 00331 00332 /* 00333 * Disable 00334 * disables the bfsclustering module 00335 * unregisters callbacks 00336 * */ 00337 inline void disable(void) { 00338 // Unregister the callback 00339 radio().unreg_recv_callback(receive_callback_id_); 00340 enabled_ = false; 00341 } 00342 00343 protected: 00344 00345 void nd_callback(uint8_t event, node_id_t link, uint8_t len, uint8_t * data) { 00346 if (ND::NEW_PAYLOAD_BIDI == event) { 00347 } 00348 } 00349 00350 void notify_cradio(uint8_t event, cluster_id_t cluster, node_id_t link) { 00351 if (!enabled_) return; 00352 if (event == RESUME) { 00353 if (!routeExists(cluster)) { 00354 //debug().debug("Got a new link %x<->%x cluster %x", radio().id(), link, cluster); 00355 if (addRoute(cluster, link, 1)) { 00356 //if (clustering().is_gateway()) { 00357 notify_listeners(ADD_ROUTE, radio().id(), cluster, link); 00358 // debug().debug("CLRC;%x;%x",radio().id(),clustering().parent()); 00359 00360 // } 00361 } 00362 } 00363 //debug().debug("Reporting link!%x -> %x", radio().id(), cluster); 00364 uint8_t add[2 + sizeof (cluster_id_t) + 1]; 00365 add[0] = 90; 00366 add[1] = 90; 00367 add[1 + sizeof (cluster_id_t)] = 1; 00368 cluster_id_t toadd = cluster; 00369 memcpy(add + 2, &toadd, sizeof (cluster_id_t)); 00370 radio().send(clustering().parent(), 2 + sizeof (cluster_id_t) + 1, add); 00371 } 00372 } 00373 00374 bool routeExists(cluster_id_t cluster) { 00375 if (!enabled_) return false; 00376 for (size_t i = 0; i < 10; i++) { 00377 if (rt_[i].dest_cluster_ == cluster) { 00378 rt_[i].exists_ = true; 00379 // debug().debug("CLRC;%x;%x",radio().id(),clustering().parent()); 00380 return true; 00381 } 00382 } 00383 return false; 00384 } 00385 00386 bool addRoute(cluster_id_t cluster, node_id_t link, uint8_t dista) { 00387 if (!enabled_) return false; 00388 if (cluster == clustering().cluster_id()) { 00389 //debug().debug("Same Cluster %x -> %x -> %x", radio().id(), link, cluster); 00390 return false; 00391 } 00392 00393 for (size_t i = 0; i < 10; i++) { 00394 //if routeExists 00395 if (rt_[i].dest_cluster_ == cluster) { 00396 if (rt_[i].distance <= dista) { 00397 rt_[i].exists_ = true; 00398 00399 return false; 00400 } else { 00401 rt_[i].link = link; 00402 rt_[i].distance = dista; 00403 rt_[i].exists_ = true; 00404 return true; 00405 } 00406 } 00407 } 00408 00409 for (size_t i = 0; i < 10; i++) { 00410 if (rt_[i].dest_cluster_ == 0xffff) { 00411 rt_[i].dest_cluster_ = cluster; 00412 rt_[i].distance = dista; 00413 rt_[i].link = link; 00414 rt_[i].exists_ = true; 00415 return true; 00416 } 00417 } 00418 return false; 00419 } 00420 00421 void send2head(node_id_t destination, size_t len, uint8_t * msg) { 00422 if (!enabled_) return false; 00423 00424 ClusterRadioMsg<OsModel, Radio> mess; 00425 mess.set_destination(destination); 00426 mess.set_payload(msg, len); 00427 #ifdef DEBUG_CLUSTERRADIO 00428 debug().debug("CLradio::Sending::from%x::to%x::for%x::len%d::", radio().id(), clustering().parent(), mess.destination(), mess.length()); 00429 #ifdef SHAWN 00430 debug().debug("\n"); 00431 #endif 00432 #endif 00433 radio().send(clustering().parent(), mess.length(), (uint8_t*) & mess); 00434 debug().debug("CLRS;%x;%d;%x",radio().id(),mess.msg_id(),clustering().parent()); 00435 } 00436 00437 /* 00438 * RECEIVE 00439 * respond to the new messages received 00440 * callback from the radio 00441 * */ 00442 void receive(node_id_t from, size_t len, block_data_t * data) { 00443 00444 if (radio().id() == from) return; 00445 00446 //CDOWN uint8_t recvm[len]; 00447 //CDOWN memcpy(recvm, data, len); 00448 uint8_t *recvm = data; 00449 00450 //CDOWN uint8_t type = *recvm; 00451 00452 if (*recvm == CLRADIO_MSG) { 00453 //CDOWN 00454 ClusterRadioMsg<OsModel, Radio> *mess; 00455 mess = (ClusterRadioMsg<OsModel, Radio> *)recvm; 00456 //CDOWN memcpy(&mess, recvm, len); 00457 #ifdef DEBUG_CLUSTERRADIO_RECEIVED 00458 debug().debug("CLradio::Received::node%x::type%d::from%x::to%x::", radio().id(), mess->msg_id(), from, mess->destination()); 00459 #ifdef SHAWN 00460 debug().debug("\n"); 00461 #endif 00462 #endif 00463 if (clustering().cluster_id() == mess->destination()) { 00464 if (radio().id() == mess->destination()) { 00465 uint8_t payload[mess->payload_size()]; 00466 mess->get_payload(payload); 00467 notify_receivers(mess->source(), mess->payload_size(), payload); 00468 00469 #ifdef DEBUG_CLUSTERRADIO_RECEIVED 00470 debug().debug("CLradio::Absorb::node%x::from%x::", radio().id(), mess->source()); 00471 #ifdef SHAWN 00472 debug().debug("\n"); 00473 #endif 00474 #else 00475 // if (enable_debug_) { 00476 // debug().debug("CLradio::Absorb::node%x::from%x::", radio().id(), mess->source()); 00477 // } 00478 #endif 00479 00480 } else { 00481 #ifdef DEBUG_CLUSTERRADIO_RECEIVED 00482 debug().debug("CLradio::Route2Head::node%x::to%x::forw::", radio().id(), clustering().parent()); 00483 #ifdef SHAWN 00484 debug().debug("\n"); 00485 #endif 00486 #else 00487 // if (enable_debug_) { 00488 debug().debug("CLRS;%x;%d;%x;%x", radio().id(), CLRADIO_MSG, clustering().parent(),recvm[ClusterRadioMsg<OsModel, Radio>::PAYLOAD+3]); 00489 // } 00490 #endif 00491 00492 radio().send(clustering().parent(), len, recvm); 00493 } 00494 } else { 00495 node_id_t next_link = Radio::NULL_NODE_ID; 00496 00497 //for (ClusterRoutingTable_iterator_t it = rt_.begin(); it != rt_.end(); it++) { 00498 for (size_t i = 0; i < 10; i++) { 00499 if (rt_[i].dest_cluster_ != 0xffff) { 00500 if (rt_[i].dest_cluster_ == mess->destination()) { 00501 next_link = rt_[i].link; 00502 break; 00503 } 00504 } 00505 } 00506 00507 //drop a circling message 00508 if (mess->source() == radio().id()) return; 00509 00510 if (next_link != Radio::NULL_NODE_ID) { 00511 #ifdef DEBUG_CLUSTERRADIO 00512 00513 debug().debug("CLradio::SendNextLink::node%x::next%x::forw::", radio().id(), next_link); 00514 #ifdef SHAWN 00515 debug().debug("\n"); 00516 #endif 00517 #else 00518 // if (enable_debug_) { 00519 debug().debug("CLRS;%x;%d;%x;%x", radio().id(), CLRADIO_MSG, next_link,recvm[ClusterRadioMsg<OsModel, Radio>::PAYLOAD+3]); 00520 // } 00521 #endif 00522 radio().send(next_link, len, recvm); 00523 } else { 00524 #ifdef DEBUG_CLUSTERRADIO 00525 00526 debug().debug("CLradio::UnknownNextLink::node%x::dest%x::forw::", radio().id(), mess->destination()); 00527 #ifdef SHAWN 00528 debug().debug("\n"); 00529 #endif 00530 #endif 00531 } 00532 00533 } 00534 } else if (*recvm == 90) { 00535 if (recvm[1] == 90) { 00536 cluster_id_t cluster; 00537 uint8_t dist; 00538 memcpy(&cluster, recvm + 2, sizeof (cluster_id_t)); 00539 dist = recvm[1 + sizeof (cluster_id_t)]; 00540 if (addRoute(cluster, from, dist + 1)) { 00541 notify_listeners(ADD_ROUTE, radio().id(), cluster, from); 00542 // debug().debug("CLRC;%x;%x",radio().id(),clustering().parent()); 00543 //debug().debug("CLradio::Node%x::NewRoute::to%x::through%x::cl::%d::", radio().id(), cluster, from, connections()); 00544 } 00545 if (clustering().parent() != radio().id()) { 00546 //debug().debug("Reporting link!%x -> %x", radio().id(), cluster); 00547 uint8_t add[2 + sizeof (cluster_id_t) + 1]; 00548 add[0] = 90; 00549 add[1] = 90; 00550 add[1 + sizeof (cluster_id_t)] = dist + 1; 00551 cluster_id_t toadd = cluster; 00552 memcpy(add + 2, &toadd, sizeof (cluster_id_t)); 00553 radio().send(clustering().parent(), 2 + sizeof (cluster_id_t) + 1, add); 00554 //debug().debug("CLRC;%x;%x",radio().id(),clustering().parent()); 00555 00556 } 00557 } else if (recvm[1] == 91) { 00558 cluster_id_t cluster; 00559 memcpy(&cluster, recvm + 2, sizeof (cluster_id_t)); 00560 if (routeExists(cluster)) { 00561 for (size_t i = 0; i < 10; i++) { 00562 if (rt_[i].dest_cluster_ == cluster) { 00563 rt_[i].dest_cluster_ = 0xffff; 00564 } 00565 } 00566 radio().send(0xffff, len, recvm); 00567 debug().debug("CLRC;%x;%x",radio().id(),0xffff); 00568 00569 } 00570 } 00571 } 00572 } 00573 00574 void reset(int event) { 00575 //debug().debug("Reseting Cradio %x", radio().id()); 00576 if ((event == CLUSTER_HEAD_CHANGED) || (event == NODE_JOINED)) { 00577 //for (ClusterRoutingTable_iterator_t it = rt_.begin(); it != rt_.end(); it++) { 00578 for (size_t i = 0; i < 10; i++) { 00579 if (rt_[i].dest_cluster_ != 0xffff) { 00580 if (clustering().is_gateway()) { 00581 //notify_listeners(REMOVE_ROUTE, radio().id(), rt_[i].dest_cluster_, rt_[i].link); 00582 } 00583 //debug().debug("CLradio::Node%x::RemoveRoute::to%x::through%x::", radio().id(), rt_[i].dest_cluster_, rt_[i].link); 00584 00585 #ifdef DEBUG_CLUSTERRADIO 00586 00587 debug().debug("CLradio::Node%x::RemoveRoute::to%x::through%x::", radio().id(), rt_[i].dest_cluster_, rt_[i].link); 00588 #ifdef SHAWN 00589 debug().debug("\n"); 00590 #endif 00591 00592 #endif 00593 00594 } 00595 } 00596 00597 for (int i = 0; i < 10; i++) 00598 rt_[i].dest_cluster_ = 0xffff; 00599 00600 gateway_connections_ = 0; 00601 uint8_t payload; 00602 nd().set_payload((uint8_t) CLRADIO, (uint8_t*) & payload, 0); 00603 } 00604 } 00605 00606 00607 private: 00608 int receive_callback_id_; // receive message callback 00609 00610 bool enabled_; 00611 //CDOWN bool enable_debug_; 00612 size_t gateway_connections_; 00613 00614 00615 NotifyCallbackVector notify_callbacks_; 00616 00617 00618 Radio * radio_; // radio module 00619 Timer * timer_; // timer module 00620 Debug * debug_; // debug module 00621 00622 //ClusterRoutingTable rt_; 00623 RTentry_t rt_[10]; 00624 00625 Clustering * clustering_; 00626 ND * nd_; 00627 00628 Radio & radio() { 00629 00630 return *radio_; 00631 } 00632 00633 Timer & timer() { 00634 00635 return *timer_; 00636 } 00637 00638 Debug & debug() { 00639 #ifdef SHAWN 00640 debug_->debug("\n"); 00641 #endif 00642 return *debug_; 00643 } 00644 00645 Clustering & clustering() { 00646 00647 return *clustering_; 00648 } 00649 00650 ND & nd() { 00651 return *nd_; 00652 } 00653 00654 }; 00655 } 00656 #endif