PhyLayerBattery.cc

00001 //
00002 // This program is free software: you can redistribute it and/or modify
00003 // it under the terms of the GNU Lesser General Public License as published by
00004 // the Free Software Foundation, either version 3 of the License, or
00005 // (at your option) any later version.
00006 //
00007 // This program is distributed in the hope that it will be useful,
00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 // GNU Lesser General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU Lesser General Public License
00013 // along with this program.  If not, see http://www.gnu.org/licenses/.
00014 //
00015 
00016 #include "PhyLayerBattery.h"
00017 #include "Decider80211MultiChannel.h"
00018 
00019 Define_Module(PhyLayerBattery);
00020 
00021 void PhyLayerBattery::initialize(int stage) {
00022   PhyLayer::initialize(stage);
00023   if (stage == 0) {
00024     numActivities = hasPar("numActivities") ? par("numActivities").longValue() : 5;
00025 
00026     /* parameters belong to the NIC, not just phy layer
00027      *
00028      * if/when variable transmit power is supported, txCurrent
00029      * should be specified as an xml table of available transmit
00030      * power levels and corresponding txCurrent */
00031     sleepCurrent = rxCurrent = decodingCurrentDelta = txCurrent = 0;
00032     setupRxCurrent = setupTxCurrent = rxTxCurrent = txRxCurrent = 0;
00033     sleepCurrent = getParentModule()->par( "sleepCurrent" );
00034     rxCurrent = getParentModule()->par( "rxCurrent" );
00035     decodingCurrentDelta = getParentModule()->par( "decodingCurrentDelta" );
00036     txCurrent = getParentModule()->par( "txCurrent" );
00037     setupRxCurrent = getParentModule()->par( "setupRxCurrent" );
00038     setupTxCurrent = getParentModule()->par( "setupTxCurrent" );
00039     rxTxCurrent = getParentModule()->par( "rxTxCurrent" );
00040     txRxCurrent = getParentModule()->par( "txRxCurrent" );
00041   } else {
00042     registerWithBattery("physical layer", numActivities);
00043     setRadioCurrent(radio->getCurrentState());
00044     //BatteryAccess::drawCurrent(rxCurrent, RX_ACCT);
00045   }
00046 }
00047 
00048 Decider* PhyLayerBattery::getDeciderFromName(std::string name, ParameterMap& params) {
00049   if(name == "Decider80211Battery") {
00050     return initializeDecider80211Battery(params);
00051   }
00052   else if(name == "Decider80211MultiChannel") {
00053     return initializeDecider80211MultiChannel(params);
00054   }
00055 
00056   return PhyLayer::getDeciderFromName(name, params);
00057 }
00058 
00059 Decider* PhyLayerBattery::initializeDecider80211Battery(ParameterMap& params) {
00060   double threshold = params["threshold"];
00061   return new Decider80211Battery(this,
00062                    threshold,
00063                    sensitivity,
00064                    radio->getCurrentChannel(),
00065                    decodingCurrentDelta,
00066                    findHost()->getIndex(),
00067                    coreDebug);
00068 }
00069 
00070 Decider* PhyLayerBattery
00071 			::initializeDecider80211MultiChannel(ParameterMap& params)
00072 {
00073   double threshold = params["threshold"];
00074   return new Decider80211MultiChannel(this,
00075                    threshold,
00076                    sensitivity,
00077                    decodingCurrentDelta,
00078                    radio->getCurrentChannel(),
00079                    findHost()->getIndex(),
00080                    coreDebug);
00081 }
00082 
00083 void PhyLayerBattery::drawCurrent(double amount, int activity) {
00084   if(radio->getCurrentState() == Radio::RX) {
00085     if(amount != 0.0) {
00086       BatteryAccess::drawCurrent(rxCurrent + amount, DECIDER_ACCT + activity);
00087     } else {
00088       BatteryAccess::drawCurrent(rxCurrent, RX_ACCT);
00089     }
00090   } else {
00091     opp_warning("Decider wanted to change power consumption while radio not in state RX.");
00092   }
00093 }
00094 
00095 void PhyLayerBattery::handleUpperMessage(cMessage* msg) {
00096   if (utility->getHostState().get() == HostState::FAILED) {
00097     coreEV<< "host has FAILED, dropping msg " << msg->getName() << endl;
00098     delete msg;
00099     return;
00100   }
00101 
00102   MacPkt* pkt = static_cast<MacPkt*>(msg);
00103   MacToPhyControlInfo* cInfo = static_cast<MacToPhyControlInfo*>(pkt->getControlInfo());
00104 
00105   double current = calcTXCurrentForPacket(pkt, cInfo);
00106 
00107   if(current > 0) {
00108     BatteryAccess::drawCurrent(current, TX_ACCT);
00109   }
00110 
00111   PhyLayer::handleUpperMessage(msg);
00112 }
00113 
00114 void PhyLayerBattery::handleAirFrame(cMessage* msg) {
00115   if (utility->getHostState().get() == HostState::FAILED) {
00116     coreEV<< "host has FAILED, dropping msg " << msg->getName() << endl;
00117     delete msg;
00118     return;
00119   }
00120 
00121   PhyLayer::handleAirFrame(msg);
00122 
00123 
00124 }
00125 
00126 void PhyLayerBattery::handleHostState(const HostState& state) {
00127   // handles only battery consumption
00128 
00129   HostState::States hostState = state.get();
00130 
00131   switch (hostState) {
00132   case HostState::FAILED:
00133     EV<< "t = " << simTime() << " host state FAILED" << endl;
00134     // it would be good to create a radioState OFF, as well
00135     break;
00136   default:
00137     break;
00138   }
00139 }
00140 
00141 void PhyLayerBattery::finishRadioSwitching() {
00142   PhyLayer::finishRadioSwitching();
00143 
00144   setRadioCurrent(radio->getCurrentState());
00145 }
00146 
00147 void PhyLayerBattery::setSwitchingCurrent(int from, int to) {
00148   int act = SWITCHING_ACCT;
00149   double current = 0;
00150 
00151   switch(from) {
00152   case Radio::RX:
00153     switch(to) {
00154     case Radio::SLEEP:
00155       current = rxCurrent;
00156       break;
00157     case Radio::TX:
00158       current = rxTxCurrent;
00159       break;
00160     default:
00161       opp_error("Unknown radio switch! From RX to %d", to);
00162     }
00163     break;
00164 
00165   case Radio::TX:
00166     switch(to) {
00167     case Radio::SLEEP:
00168       current = txCurrent;
00169       break;
00170     case Radio::RX:
00171       current = txRxCurrent;
00172       break;
00173     default:
00174       opp_error("Unknown radio switch! From TX to %d", to);
00175     }
00176     break;
00177 
00178   case Radio::SLEEP:
00179     switch(to) {
00180     case Radio::TX:
00181       current = setupTxCurrent;
00182       break;
00183     case Radio::RX:
00184       current = setupRxCurrent;
00185       break;
00186     default:
00187       opp_error("Unknown radio switch! From SLEEP to %d", to);
00188     }
00189     break;
00190 
00191   default:
00192     opp_error("Unknown radio state: %d", from);
00193   }
00194 
00195   BatteryAccess::drawCurrent(current, act);
00196 }
00197 
00198 void PhyLayerBattery::setRadioCurrent(int rs) {
00199   switch(rs) {
00200   case Radio::RX:
00201     BatteryAccess::drawCurrent(rxCurrent, RX_ACCT);
00202     break;
00203   case Radio::TX:
00204     BatteryAccess::drawCurrent(txCurrent, TX_ACCT);
00205     break;
00206   case Radio::SLEEP:
00207     BatteryAccess::drawCurrent(sleepCurrent, SLEEP_ACCT);
00208     break;
00209   default:
00210     opp_error("Unknown radio state: %d", rs);
00211     break;
00212   }
00213 }
00214 
00215 simtime_t PhyLayerBattery::setRadioState(int rs) {
00216   Enter_Method_Silent();
00217   int prevState = radio->getCurrentState();
00218 
00219   simtime_t endSwitch = PhyLayer::setRadioState(rs);
00220 
00221   if(endSwitch > 0) {
00222 
00223     if(radio->getCurrentState() == Radio::SWITCHING) {
00224       setSwitchingCurrent(prevState, rs);
00225     } else {
00226       setRadioCurrent(radio->getCurrentState());
00227     }
00228   }
00229 
00230   return endSwitch;
00231 }