40 double dRxSensitivityMilliWatt):
41 totalWindowBins_{maxDuration/bin},
42 totalWheelBins_{(maxOffset + maxPropagation + 2 * maxDuration)/bin},
43 binSizeMicroseconds_{bin.count()},
44 wheel_{
static_cast<std::size_t
>(totalWheelBins_)},
45 dRxSensitivityMilliWatt_{dRxSensitivityMilliWatt},
46 maxEndOfReceptionBin_{},
47 minStartOfReceptionBin_{}
50 std::pair<EMANE::TimePoint,EMANE::TimePoint>
57 const std::vector<NEMId> & transmitters)
59 auto startOfReception = txTime + offset + propagation;
61 auto endOfReception = startOfReception + duration;
63 auto reportedStartOfReceptionBin = timepointToBin(startOfReception);
65 auto endOfReceptionBin = timepointToBin(endOfReception,
true);
67 Microseconds::rep startOfReceptionBin{reportedStartOfReceptionBin};
69 Microseconds::rep maxEoRBin{};
74 for(
const auto & transmitter : transmitters)
76 const auto iter = nemEoRBinMap_.find(transmitter);
78 if(iter != nemEoRBinMap_.end())
80 maxEoRBin = std::max(iter->second,maxEoRBin);
86 if(maxEoRBin >= reportedStartOfReceptionBin)
88 startOfReceptionBin = maxEoRBin + 1;
92 if(startOfReceptionBin <= endOfReceptionBin)
94 auto nowBin = timepointToBin(now);
96 auto durationBinCount = endOfReceptionBin - startOfReceptionBin + 1;
98 auto startIndex = startOfReceptionBin % totalWheelBins_;
100 if(nowBin - maxEndOfReceptionBin_ > totalWheelBins_)
104 maxEndOfReceptionBin_ = 0;
109 minStartOfReceptionBin_ = 0;
112 if(!maxEndOfReceptionBin_ && !minStartOfReceptionBin_)
115 wheel_.
set(startIndex,durationBinCount,dRxPower);
117 minStartOfReceptionBin_ = startOfReceptionBin;
119 maxEndOfReceptionBin_ = endOfReceptionBin;
123 Microseconds::rep beforeDurationCount{};
124 Microseconds::rep afterDurationCount{};
127 if(startOfReceptionBin < minStartOfReceptionBin_)
129 beforeDurationCount =
130 std::min(minStartOfReceptionBin_ - startOfReceptionBin,durationBinCount);
132 wheel_.
set(startIndex,beforeDurationCount,dRxPower);
136 if(endOfReceptionBin > maxEndOfReceptionBin_)
139 std::min(endOfReceptionBin - maxEndOfReceptionBin_,durationBinCount);
141 wheel_.
set((startIndex + durationBinCount - afterDurationCount) % totalWheelBins_, afterDurationCount,dRxPower);
144 auto remainderBinCount = durationBinCount - (beforeDurationCount + afterDurationCount);
146 if(remainderBinCount)
149 wheel_.
add((startIndex + beforeDurationCount) % totalWheelBins_,
156 if(beforeDurationCount)
158 wheel_.
set((startIndex + durationBinCount) % totalWheelBins_,
159 minStartOfReceptionBin_ - endOfReceptionBin - 1,
164 wheel_.
set((maxEndOfReceptionBin_ + 1) % totalWheelBins_,
165 startOfReceptionBin - maxEndOfReceptionBin_ - 1,
170 if(beforeDurationCount)
172 minStartOfReceptionBin_ = startOfReceptionBin;
175 if(afterDurationCount)
177 maxEndOfReceptionBin_ = endOfReceptionBin;
182 for(
const auto & transmitter : transmitters)
184 nemEoRBinMap_[transmitter] = endOfReceptionBin;
189 return {startOfReception,endOfReception};
198 auto nowBin = timepointToBin(now,
true);
200 auto minStartOfWindowTime =
203 auto validStartTime = startTime;
205 auto validDuration = duration;
208 if(validStartTime == TimePoint::min())
210 validStartTime = minStartOfWindowTime;
212 else if(validStartTime < minStartOfWindowTime)
214 throw makeException<SpectrumServiceException>(
"window start time too far in the past");
216 else if(validStartTime > now)
218 throw makeException<SpectrumServiceException>(
"window start time in the future");
221 auto startTimeBin = timepointToBin(validStartTime);
225 if(validDuration != Microseconds::zero())
227 endTime = validStartTime + validDuration;
231 throw makeException<SpectrumServiceException>(
"window end time in the future");
235 auto endTimeBin = timepointToBin(endTime,
true);
237 auto durationBinCount = endTimeBin - startTimeBin + 1;
239 std::vector<double> window;
241 window.reserve(durationBinCount);
244 auto startOfWindowTime =
247 if(startOfWindowTime >= minStartOfWindowTime)
249 if(maxEndOfReceptionBin_ && minStartOfReceptionBin_)
253 Microseconds::rep beforeDurationCount{};
254 Microseconds::rep afterDurationCount{};
256 if(endTimeBin > maxEndOfReceptionBin_)
259 std::min(endTimeBin - maxEndOfReceptionBin_,durationBinCount);
262 if(startTimeBin < minStartOfReceptionBin_)
264 beforeDurationCount =
265 std::min(minStartOfReceptionBin_ - startTimeBin,durationBinCount);
268 auto remainderBinCount =
269 durationBinCount - (beforeDurationCount + afterDurationCount);
271 if(remainderBinCount)
273 window = wheel_.
get((endTimeBin - afterDurationCount) % totalWheelBins_,remainderBinCount);
276 window.insert(window.begin(),beforeDurationCount,0);
277 window.insert(window.end(),afterDurationCount,0);
281 throw makeException<SpectrumServiceException>(
"window internal access error");
287 window.insert(window.begin(),durationBinCount,0);
292 throw makeException<SpectrumServiceException>(
"window start time invalid");
295 return std::make_pair(std::move(window),startOfWindowTime);
300 return wheel_.
dump();
303 EMANE::Microseconds::rep EMANE::NoiseRecorder::timepointToBin(
const TimePoint & tp,
bool bAdjust)
306 std::chrono::duration_cast<
Microseconds>(tp.time_since_epoch()).count();
310 return count == 0 ? 0 : count / binSizeMicroseconds_ - (bAdjust && (count % binSizeMicroseconds_ == 0));
void set(std::size_t begin, std::size_t slots, T value)
NoiseRecorder(const Microseconds &bin, const Microseconds &maxOffset, const Microseconds &maxPropagation, const Microseconds &maxDuration, double dRxSensitivityMilliWatt_)
std::vector< T > get(std::size_t begin, std::size_t slots)
std::pair< std::vector< double >, TimePoint > get(const TimePoint &now, const Microseconds &duration=Microseconds::zero(), const TimePoint &startTime=TimePoint::min())
void add(std::size_t begin, std::size_t slots, T value)
std::chrono::microseconds Microseconds
const std::vector< T > & dump() const
std::pair< TimePoint, TimePoint > update(const TimePoint &now, const TimePoint &txTime, const Microseconds &offset, const Microseconds &propagation, const Microseconds &duration, double dRxPower, const std::vector< NEMId > &transmitters)
Clock::time_point TimePoint
std::vector< double > dump() const