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 CONNECTOR_ISENSE_EXTENDEDTXRADIOMODEL_H 00020 #define CONNECTOR_ISENSE_EXTENDEDTXRADIOMODEL_H 00021 00022 #include "external_interface/isense/isense_types.h" 00023 #include "util/delegates/delegate.hpp" 00024 #include "config_testing.h" 00025 #include <isense/os.h> 00026 #include <isense/radio.h> 00027 #include <isense/hardware_radio.h> 00028 #include <isense/dispatcher.h> 00029 #include <isense/time.h> 00030 00031 namespace wiselib { 00032 00033 template<typename OsModel_P> 00034 class iSenseExtendedTxRadioModel 00035 : public isense::Receiver 00036 #ifdef DEBUG_ISENSE_EXTENDED_TX_RADIO 00037 , public isense::Sender 00038 #endif 00039 { 00040 public: 00041 00042 class ExtendedData { 00043 public: 00044 00045 ExtendedData() { 00046 } 00047 00048 uint16 link_metric() const { 00049 return link_metric_; 00050 }; 00051 00052 void set_link_metric(uint16 lm) { 00053 link_metric_ = lm; 00054 }; 00055 00056 private: 00057 uint16 link_metric_; 00058 }; 00059 // -------------------------------------------------------------------- 00060 typedef OsModel_P OsModel; 00061 00062 typedef iSenseExtendedTxRadioModel<OsModel> self_type; 00063 typedef self_type* self_pointer_t; 00064 00065 #ifdef ISENSE_RADIO_ADDR_TYPE 00066 typedef ISENSE_RADIO_ADDR_TYPE node_id_t; 00067 #else 00068 typedef uint16 node_id_t; 00069 #endif 00070 typedef uint8 block_data_t; 00071 typedef uint8 size_t; 00072 typedef uint8 message_id_t; 00073 00074 typedef delegate3<void, node_id_t, size_t, block_data_t*> isense_radio_delegate_t; 00075 typedef delegate4<void, node_id_t, size_t, block_data_t*, 00076 const ExtendedData&> extended_radio_delegate_t; 00077 typedef isense_radio_delegate_t radio_delegate_t; 00078 // -------------------------------------------------------------------- 00079 00080 enum ErrorCodes { 00081 SUCCESS = OsModel::SUCCESS, 00082 ERR_UNSPEC = OsModel::ERR_UNSPEC, 00083 ERR_NOTIMPL = OsModel::ERR_NOTIMPL 00084 }; 00085 // -------------------------------------------------------------------- 00086 00087 enum { 00088 MAX_INTERNAL_RECEIVERS = 10 00089 }; 00090 00091 enum { 00092 MAX_EXTENDED_RECEIVERS = MAX_INTERNAL_RECEIVERS 00093 }; 00094 // -------------------------------------------------------------------- 00095 00096 enum SpecialNodeIds { 00097 BROADCAST_ADDRESS = 0xffff, 00098 NULL_NODE_ID = 0 00099 }; 00100 // -------------------------------------------------------------------- 00101 00102 enum Restrictions { 00103 MAX_MESSAGE_LENGTH = 116 00104 }; 00105 // -------------------------------------------------------------------- 00106 class TxPower; 00107 // -------------------------------------------------------------------- 00108 00109 iSenseExtendedTxRadioModel(isense::Os& os) 00110 : os_(os) { 00111 os_.dispatcher().add_receiver(this); 00112 #ifdef ISENSE_EXTENDED_TX_RADIO_RANDOM_DELAY 00113 os_.srand(os_.id()); 00114 #endif 00115 } 00116 // -------------------------------------------------------------------- 00117 00118 int 00119 send(node_id_t id, size_t len, block_data_t *data) { 00120 #ifdef ISENSE_EXTENDED_TX_RADIO_RANDOM_DELAY 00121 uint16 ms = os().rand(ISENSE_EXTENDED_TX_RADIO_RANDOM_DELAY_MAX); 00122 isense::Time t2, t1 = os().time(); 00123 // os().debug( "Radio: delay is %d at %d", ms, t1.ms() ); 00124 do 00125 { 00126 t2 = os().time(); 00127 } while ( t2.ms() - t1.ms() < ms ); 00128 // os().debug( "Radio: fin at %d", t2.ms() ); 00129 #endif 00130 00131 #ifdef DEBUG_ISENSE_EXTENDED_TX_RADIO 00132 uint8 options = isense::Radio::ISENSE_RADIO_TX_OPTION_NONE; 00133 if ( id != BROADCAST_ADDRESS ) 00134 options |= isense::Radio::ISENSE_RADIO_TX_OPTION_ACK; 00135 os().radio().send( id, len, data, options, this ); 00136 #else 00137 os().radio().send(id, len, data, 0, 0); 00138 #endif 00139 return SUCCESS; 00140 } 00141 // -------------------------------------------------------------------- 00142 #ifdef DEBUG_ISENSE_EXTENDED_TX_RADIO 00143 00144 virtual void confirm(uint8 state, uint8 tries, isense::Time time) { 00145 // some error values: 00146 // ISENSE_RADIO_STATE_NO_ACK /**< No acknowledgement received when expected (0xE9) */ 00147 // ISENSE_RADIO_STATE_FRAME_TOO_LONG, /**< Frame too long after security processing to be sent (0xE5) */ 00148 // ISENSE_RADIO_STATE_CHANNEL_ACCESS_FAILURE /**< CSMA/CA channel access failure (0xE1) */ 00149 // ISENSE_RADIO_STATE_RADIO_NOT_ACTIVE /**< Radio switched off (0x00) */ 00150 // ISENSE_RADIO_STATE_BUFFER_OVERFLOW /**< Radio send queue full (0x01) */ 00151 00152 if (state != isense::Radio::ISENSE_RADIO_STATE_SUCCESS) 00153 os().debug("Radio: SEND FAILED at %d state %d tries %d", os().id(), state, tries); 00154 } 00155 #endif 00156 // -------------------------------------------------------------------- 00157 00158 int enable_radio() { 00159 os().radio().enable(); 00160 return SUCCESS; 00161 } 00162 00163 // -------------------------------------------------------------------- 00164 int set_channel(int channel) { 00165 if ((channel >= 11) && (channel <= 26)) { 00166 os().radio().hardware_radio().set_channel(channel); 00167 return channel; 00168 } else { 00169 return -1; 00170 } 00171 } 00172 00173 // -------------------------------------------------------------------- 00174 00175 int disable_radio() { 00176 os().radio().disable(); 00177 return SUCCESS; 00178 } 00179 // -------------------------------------------------------------------- 00180 00181 node_id_t id() { 00182 return os().id(); 00183 } 00184 // -------------------------------------------------------------------- 00185 //---------- From concept VariablePowerRadio ------------ 00186 int set_power(TxPower p); 00187 //------------------------------------------------------- 00188 TxPower power(); 00189 //------------------------------------------------------- 00190 00191 template<class T, void (T::*TMethod)(node_id_t, size_t, block_data_t*)> 00192 int reg_recv_callback(T *obj_pnt) { 00193 for (int i = 0; i < MAX_INTERNAL_RECEIVERS; i++) { 00194 if (!isense_radio_callbacks_[i]) { 00195 isense_radio_callbacks_[i] = 00196 isense_radio_delegate_t::template from_method<T, TMethod > (obj_pnt); 00197 return i; 00198 } 00199 } 00200 return -1; 00201 } 00202 // -------------------------------------------------------------------- 00203 00204 template<class T, void (T::*TMethod)(node_id_t, size_t, block_data_t*, const ExtendedData&) > 00205 int reg_recv_callback(T *obj_pnt) { 00206 for (int i = 0; i < MAX_EXTENDED_RECEIVERS; i++) { 00207 if (!isense_ext_radio_callbacks_[i]) { 00208 isense_ext_radio_callbacks_[i] = 00209 extended_radio_delegate_t::template from_method<T, TMethod > (obj_pnt); 00210 return i; 00211 } 00212 } 00213 return -1; 00214 } 00215 // -------------------------------------------------------------------- 00216 00217 int unreg_recv_callback(int idx) { 00218 // TODO: Implement unregister - thereby different ids for receive 00219 // with and without ExtendedData must be generated 00220 return ERR_NOTIMPL; 00221 } 00222 // -------------------------------------------------------------------- 00223 #ifdef ISENSE_RADIO_ADDR_TYPE 00224 virtual void receive(uint8 len, const uint8 *buf, 00225 ISENSE_RADIO_ADDR_TYPE src_addr, ISENSE_RADIO_ADDR_TYPE dest_addr, 00226 uint16 signal_strength, uint16 signal_quality, uint8 sequence_no, 00227 uint8 interface, isense::Time rx_time) 00228 #else 00229 00230 virtual void receive(uint8 len, const uint8 *buf, 00231 uint16 src_addr, uint16 dest_addr, 00232 uint16 lqi, uint8 seq_no, uint8 interface) 00233 #endif 00234 { 00235 for (int i = 0; i < MAX_INTERNAL_RECEIVERS; i++) { 00236 if (isense_radio_callbacks_[i]) 00237 isense_radio_callbacks_[i](src_addr, len, const_cast<uint8*> (buf)); 00238 } 00239 00240 ExtendedData ex; 00241 ex.set_link_metric(255 - signal_strength); 00242 for (int i = 0; i < MAX_EXTENDED_RECEIVERS; i++) { 00243 if (isense_ext_radio_callbacks_[i]) 00244 isense_ext_radio_callbacks_[i](src_addr, len, const_cast<uint8*> (buf), ex); 00245 } 00246 } 00247 00248 private: 00249 00250 isense::Os& os() { 00251 return os_; 00252 } 00253 // -------------------------------------------------------------------- 00254 isense::Os& os_; 00255 isense_radio_delegate_t isense_radio_callbacks_[MAX_INTERNAL_RECEIVERS]; 00256 extended_radio_delegate_t isense_ext_radio_callbacks_[MAX_EXTENDED_RECEIVERS]; 00257 }; 00258 // -------------------------------------------------------------------- 00259 00265 template<typename OsModel_P> 00266 class iSenseExtendedTxRadioModel<OsModel_P>::TxPower { 00267 public: 00268 TxPower(); 00269 TxPower(TxPower const &); 00270 00271 TxPower &operator=(TxPower const &); 00272 bool operator==(TxPower) const; 00273 bool operator!=(TxPower) const; 00274 bool operator<=(TxPower) const; 00275 bool operator>=(TxPower) const; 00276 bool operator<(TxPower) const; 00277 bool operator>(TxPower) const; 00278 TxPower operator++(); 00279 TxPower operator++(int); 00280 TxPower operator--(); 00281 TxPower operator--(int); 00282 00283 static TxPower from_ratio(int); 00284 void set_ratio(int); 00285 int to_ratio() const; 00286 static TxPower from_dB(int); 00287 void set_dB(int); 00288 int to_dB() const; 00289 00290 static TxPower const MIN; 00291 static TxPower const MAX; 00292 00293 private: 00294 TxPower(int); 00295 00296 int value; 00297 00298 friend class iSenseExtendedTxRadioModel<OsModel_P>; 00299 }; 00300 00301 template<typename OsModel_P> 00302 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower const iSenseExtendedTxRadioModel<OsModel_P>::TxPower::MIN = -30; 00303 00304 template<typename OsModel_P> 00305 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower const iSenseExtendedTxRadioModel<OsModel_P>::TxPower::MAX = 0; 00306 00307 template<typename OsModel_P> 00308 inline iSenseExtendedTxRadioModel<OsModel_P>::TxPower::TxPower(int v) : value(v) { 00309 } 00310 00311 template<typename OsModel_P> 00312 inline iSenseExtendedTxRadioModel<OsModel_P>::TxPower::TxPower() : value(0) { 00313 } 00314 00315 template<typename OsModel_P> 00316 inline typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower &iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator=(TxPower const &p) { 00317 value = p.value; 00318 return *this; 00319 } 00320 00321 template<typename OsModel_P> 00322 inline iSenseExtendedTxRadioModel<OsModel_P>::TxPower::TxPower(TxPower const &power) : value(power.value) { 00323 } 00324 00325 template<typename OsModel_P> 00326 inline bool iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator==(TxPower p) const { 00327 return value == p.value; 00328 } 00329 00330 template<typename OsModel_P> 00331 inline bool iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator!=(TxPower p) const { 00332 return value != p.value; 00333 } 00334 00335 template<typename OsModel_P> 00336 inline bool iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator<=(TxPower p) const { 00337 return value <= p.value; 00338 } 00339 00340 template<typename OsModel_P> 00341 inline bool iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator>=(TxPower p) const { 00342 return value >= p.value; 00343 } 00344 00345 template<typename OsModel_P> 00346 inline bool iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator<(TxPower p) const { 00347 return value < p.value; 00348 } 00349 00350 template<typename OsModel_P> 00351 inline bool iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator>(TxPower p) const { 00352 return value > p.value; 00353 } 00354 00355 template<typename OsModel_P> 00356 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator++() { 00357 value += 6; 00358 return *this; 00359 } 00360 00361 template<typename OsModel_P> 00362 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator++(int) { 00363 TxPower p = *this; 00364 value += 6; 00365 return p; 00366 } 00367 00368 template<typename OsModel_P> 00369 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator--() { 00370 value -= 6; 00371 return *this; 00372 } 00373 00374 template<typename OsModel_P> 00375 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::TxPower::operator--(int) { 00376 TxPower p = *this; 00377 value -= 6; 00378 return p; 00379 } 00380 00381 template<typename OsModel_P> 00382 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::TxPower::from_ratio(int ratio) { 00383 if (ratio <= 1) 00384 return MIN; 00385 else if (ratio <= 4) 00386 return TxPower(-24); 00387 else if (ratio <= 16) 00388 return TxPower(-18); 00389 else if (ratio <= 63) 00390 return TxPower(-12); 00391 else if (ratio <= 251) 00392 return TxPower(-6); 00393 else 00394 return MAX; 00395 } 00396 00397 template<typename OsModel_P> 00398 void iSenseExtendedTxRadioModel<OsModel_P>::TxPower::set_ratio(int ratio) { 00399 if (ratio <= 1) 00400 value = -30; 00401 else if (ratio <= 4) 00402 value = -24; 00403 else if (ratio <= 16) 00404 value = -18; 00405 else if (ratio <= 63) 00406 value = -12; 00407 else if (ratio <= 251) 00408 value = -6; 00409 else 00410 value = 0; 00411 } 00412 00413 template<typename OsModel_P> 00414 int iSenseExtendedTxRadioModel<OsModel_P>::TxPower::to_ratio() const { 00415 switch (value) { 00416 case 0: 00417 return 1000; 00418 case -6: 00419 return 251; 00420 case -12: 00421 return 63; 00422 case -18: 00423 return 16; 00424 case -24: 00425 return 4; 00426 default: 00427 return 1; 00428 } 00429 } 00430 00431 template<typename OsModel_P> 00432 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::TxPower::from_dB(int db) { 00433 if (db <= -30) 00434 return MIN; 00435 else if (db <= -24) 00436 return TxPower(-24); 00437 else if (db <= -18) 00438 return TxPower(-18); 00439 else if (db <= -12) 00440 return TxPower(-12); 00441 else if (db <= -6) 00442 return TxPower(-6); 00443 else 00444 return MAX; 00445 } 00446 00447 template<typename OsModel_P> 00448 void iSenseExtendedTxRadioModel<OsModel_P>::TxPower::set_dB(int db) { 00449 if (db <= -30) 00450 value = -30; 00451 else if (db <= -24) 00452 value = -24; 00453 else if (db <= -18) 00454 value = -18; 00455 else if (db <= -12) 00456 value = -12; 00457 else if (db <= -6) 00458 value = -6; 00459 else 00460 value = 0; 00461 //Another way: value=-(((-db)/6)*6); 00462 } 00463 00464 template<typename OsModel_P> 00465 inline int iSenseExtendedTxRadioModel<OsModel_P>::TxPower::to_dB() const { 00466 return value; 00467 } 00468 // -------------------------------------------------------------------- 00469 00470 template<typename OsModel_P> 00471 int iSenseExtendedTxRadioModel<OsModel_P>::set_power(TxPower p) { 00472 os().radio().hardware_radio().set_power(p.value); 00473 return SUCCESS; 00474 } 00475 00476 template<typename OsModel_P> 00477 typename iSenseExtendedTxRadioModel<OsModel_P>::TxPower iSenseExtendedTxRadioModel<OsModel_P>::power() { 00478 return TxPower(os().radio().hardware_radio().power()); 00479 } 00480 //------------------------------------------------------- 00481 } 00482 00483 #endif