TTEthernet Model for INET Framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
TTEScheduler.cc
Go to the documentation of this file.
1 //
2 // This program is free software: you can redistribute it and/or modify
3 // it under the terms of the GNU Lesser General Public License as published by
4 // the Free Software Foundation, either version 3 of the License, or
5 // (at your option) any later version.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public License
13 // along with this program. If not, see http://www.gnu.org/licenses/.
14 //
15 
16 #include "TTEScheduler.h"
17 
18 #include <SchedulerMessage_m.h>
19 
20 namespace TTEthernetModel {
21 
22 Define_Module( TTEScheduler);
23 
24 simsignal_t TTEScheduler::currentDrift = SIMSIGNAL_NULL;
25 simsignal_t TTEScheduler::newCycle = SIMSIGNAL_NULL;
26 
28 {
29  return 1;
30 }
31 
32 void TTEScheduler::initialize(int stage)
33 {
34  if(stage==0){
35  currentDrift = registerSignal("currentDrift");
36  newCycle = registerSignal("newCycle");
37  cycles = 0;
38 
39  //Start Timer
40  scheduleAt(simTime(), new SchedulerEvent("NEW_CYCLE", NEW_CYCLE));
41 
42  lastCycleStart = simTime();
43  lastNewCycleMessage = simTime();
44  lastCycleTicks = 0;
45  }
46 }
47 
49 #ifdef DEBUG
50  Enter_Method("registerEvent(SchedulerEvent %s)",event->getName());
51 #else
52  Enter_Method_Silent();
53 #endif
54 
55  if (event->getKind() == ACTION_TIME_EVENT)
56  {
57  return registerEvent(dynamic_cast<SchedulerActionTimeEvent*>(event), false);
58  }
59  else if (event->getKind() == TIMER_EVENT)
60  {
61  take(event);
62  registredEvents.push_back(event);
63  SchedulerTimerEvent *timerEvent = (SchedulerTimerEvent*) event;
64  scheduleAt(simTime() + currentTick * timerEvent->getTimer(), event);
65  }
66  return true;
67 }
68 
69 
70 bool TTEScheduler::registerEvent(SchedulerActionTimeEvent *actionTimeEvent, bool forceNextCycle)
71 {
72 #ifdef DEBUG
73  Enter_Method("registerEvent(SchedulerEvent %s, forceNextCycle %d)",event->getName(), forceNextCycle);
74 #else
75  Enter_Method_Silent();
76 #endif
77 
78  take(actionTimeEvent);
79  registredEvents.push_back(actionTimeEvent);
80 
81  //Check whether event is in cycle
82  if(actionTimeEvent->getAction_time()>cycleTicks){
83  bubble("Schedule contains out of cycle events!");
84  return false;
85  }
86 
87  if ((actionTimeEvent->getAction_time() <= getTicks()) || forceNextCycle)
88  {
89  scheduleAt(lastCycleStart
90  + currentTick
91  * (actionTimeEvent->getAction_time() + cycleTicks),
92  actionTimeEvent);
93  }
94  else
95  {
96 
97  scheduleAt(lastCycleStart + currentTick * (actionTimeEvent->getAction_time()),
98  actionTimeEvent);
99  }
100  return true;
101 }
102 
104  if(event->isScheduled()){
105  cancelEvent(event);
106  registredEvents.remove(event);
107  }
108 
109 }
110 
111 void TTEScheduler::handleMessage(cMessage *msg)
112 {
113  if (msg->isSelfMessage() && (msg->getKind() == ACTION_TIME_EVENT || msg->getKind() == TIMER_EVENT))
114  {
115  SchedulerEvent *event = (SchedulerEvent*) msg;
116  registredEvents.remove(event);
117  sendDirect(event, event->getDestinationGate());
118  }
119  else if (msg->isSelfMessage() && msg->getKind() == NEW_CYCLE)
120  {
121  //First the precision is changed for the next cycle
122  changeDrift();
123 
124  emit(newCycle, 1L);
125  cycles++;
126  lastCycleStart = simTime();
127  lastNewCycleMessage = simTime();
129  scheduleAt(lastCycleStart + currentTick * cycleTicks, msg);
130  newCyclemsg = msg;
131 
132  correctEvents();
133  }
134 }
135 
137 
138  simtime_t newDriftChange = uniform(-maxDriftChange,maxDriftChange);
139  simtime_t newTick = currentTick+newDriftChange;
140  if((newTick-tick)>maxDrift)
141  par("current_tick").setDoubleValue((tick+maxDrift).dbl());
142  else if((newTick-tick)<-maxDrift)
143  par("current_tick").setDoubleValue((tick-maxDrift).dbl());
144  else
145  par("current_tick").setDoubleValue(newTick.dbl());
146  emit(currentDrift, par("current_tick").doubleValue()-tick);
147 }
148 
150  for(std::list<SchedulerEvent*>::const_iterator registredEvent = registredEvents.begin(); registredEvent != registredEvents.end(); registredEvent++){
151  if((*registredEvent)->getKind() == ACTION_TIME_EVENT){
152  SchedulerActionTimeEvent *actionTimeEvent = (SchedulerActionTimeEvent*)*registredEvent;
153  cancelEvent(actionTimeEvent);
154  //TODO lots of improvements!
155  if (actionTimeEvent->getAction_time() > getTicks())
156  {
157  scheduleAt(lastCycleStart + currentTick * actionTimeEvent->getAction_time(),
158  actionTimeEvent);
159  }
160  else if (actionTimeEvent->getAction_time() == getTicks())
161  {
162  scheduleAt(simTime(), actionTimeEvent);
163  }
164  else
165  {
166  if(lastCycleStart>simTime()){
167  scheduleAt(lastCycleStart
168  + currentTick
169  * (actionTimeEvent->getAction_time()),
170  actionTimeEvent);
171  }
172  else{
173  scheduleAt(lastCycleStart
174  + currentTick
175  * (actionTimeEvent->getAction_time() + cycleTicks),
176  actionTimeEvent);
177  }
178  }
179  }
180  }
181 }
182 
183 void TTEScheduler::handleParameterChange(const char* parname){
184  maxDriftChange = SimTime(par("max_drift_change").doubleValue());
185  maxDrift = SimTime(par("max_drift").doubleValue());
186  currentTick = SimTime(par("current_tick").doubleValue());
187  tick = SimTime(par("tick").doubleValue());
188  cycleTicks = par("cycle_ticks").longValue();
189 }
190 
191 void TTEScheduler::clockCorrection(int32_t ticks){
192  Enter_Method("clock correction %d ticks",ticks);
193 
195 
196  //Now correct the new cylce time
197  cancelEvent(newCyclemsg);
198  scheduleAt(simTime()-(simTime()-lastCycleStart) + currentTick * cycleTicks, newCyclemsg);
199  //Now correct the events
200  correctEvents();
201 }
202 
204 {
205  if(simTime() >= lastCycleStart){
206  return floor((simTime() - lastCycleStart) / currentTick);
207  }
208  else{
209  return cycleTicks - floor((lastCycleStart - simTime()) / currentTick);
210  }
211 }
212 
214 {
215  return lastCycleTicks + floor((simTime() - lastNewCycleMessage) / currentTick);
216 }
217 
219 {
220  return cycles;
221 }
222 
223 } //namespace