Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2009, 2010 t. schneider tes@mit.edu 00002 // 00003 // this file is part of libamac, a medium access control for 00004 // acoustic networks. 00005 // 00006 // see the readme file within this directory for information 00007 // pertaining to usage and purpose of this script. 00008 // 00009 // This program is free software: you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation, either version 3 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // This software is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with this software. If not, see <http://www.gnu.org/licenses/>. 00021 00022 #ifndef MAC20091019H 00023 #define MAC20091019H 00024 00025 #include <boost/lexical_cast.hpp> 00026 #include <boost/function.hpp> 00027 #include <boost/foreach.hpp> 00028 #include <boost/bind.hpp> 00029 #include <boost/asio.hpp> 00030 00031 #include "goby/protobuf/modem_message.pb.h" 00032 #include "goby/protobuf/amac.pb.h" 00033 #include "goby/acomms/modem_driver.h" 00034 #include "goby/util/time.h" 00035 #include "goby/util/string.h" 00036 00037 namespace goby 00038 { 00039 namespace util 00040 { 00041 class FlexOstream; 00042 } 00043 00044 namespace acomms 00045 { 00047 00048 00053 class MACManager 00054 { 00055 00056 public: 00057 00059 00060 00061 00062 00063 MACManager(std::ostream* log = 0); 00064 ~MACManager(); 00066 00068 00069 00073 void startup(const protobuf::MACConfig& cfg); 00074 00076 void shutdown(); 00077 00079 void do_work(); 00080 00082 00083 00085 00086 00087 00088 00089 void handle_modem_all_incoming(const protobuf::ModemMsgBase& m); 00091 00092 00094 00095 00096 00097 00098 boost::signal<void (protobuf::ModemMsgBase* m)> signal_initiate_transmission; 00099 00103 boost::signal<void (protobuf::ModemRangingRequest* m)> signal_initiate_ranging; 00105 00107 00108 00109 std::map<int, protobuf::Slot>::iterator add_slot(const protobuf::Slot& s); 00113 bool remove_slot(const protobuf::Slot& s); 00114 00116 void clear_all_slots() { id2slot_.clear(); slot_order_.clear(); } 00118 00120 00121 00122 static void add_flex_groups(util::FlexOstream* tout); 00124 00125 00126 00129 00131 00132 private: 00133 void send_poll(const boost::system::error_code&); 00134 boost::posix_time::ptime next_cycle_time(); 00135 00136 void restart_timer(); 00137 void stop_timer(); 00138 00139 void expire_ids(); 00140 void process_cycle_size_change(); 00141 00142 unsigned cycle_count() { return slot_order_.size(); } 00143 unsigned cycle_length(); 00144 unsigned cycle_sum(); 00145 void position_blank(); 00146 00147 private: 00148 std::ostream* log_; 00149 00150 protobuf::MACConfig cfg_; 00151 00152 // asynchronous timer 00153 boost::asio::io_service io_; 00154 boost::asio::deadline_timer timer_; 00155 bool timer_is_running_; 00156 00157 boost::posix_time::ptime next_cycle_t_; 00158 boost::posix_time::ptime next_slot_t_; 00159 00160 // <id, last time heard from> 00161 typedef std::multimap<int, protobuf::Slot>::iterator id2slot_it; 00162 00163 id2slot_it blank_it_; 00164 std::list<id2slot_it> slot_order_; 00165 std::multimap<int, protobuf::Slot> id2slot_; 00166 00167 std::list<id2slot_it>::iterator current_slot_; 00168 00169 unsigned cycles_since_day_start_; 00170 00171 // entropy value used to determine how the "blank" slot moves around relative to the values of the modem ids. determining the proper value for this is a bit of work and i will detail when i have time. 00172 enum { ENTROPY = 5 }; 00173 00174 bool startup_done_; 00175 }; 00176 00178 namespace protobuf 00179 { 00180 00181 inline bool operator<(const std::map<int, protobuf::Slot>::iterator& a, const std::map<int, protobuf::Slot>::iterator& b) 00182 { return a->second.src() < b->second.src(); } 00183 00185 inline bool operator==(const protobuf::Slot& a, const protobuf::Slot& b) 00186 { 00187 return (a.src() == b.src() && 00188 a.dest() == b.dest() && 00189 a.rate() == b.rate() && 00190 a.type() == b.type() && 00191 a.slot_seconds() == b.slot_seconds() && 00192 a.type() == b.type()); 00193 } 00194 } 00195 } 00196 } 00197 00198 #endif