1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2009 CTTC
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Nicola Baldo <nbaldo@cttc.es>
19 */
20
21
22 #include "lte-interference.h"
23 #include "lte-chunk-processor.h"
24
25 #include <ns3/simulator.h>
26 #include <ns3/log.h>
27
28
29 namespace ns3 {
30
31 NS_LOG_COMPONENT_DEFINE ("LteInterference");
32
LteInterference()33 LteInterference::LteInterference ()
34 : m_receiving (false),
35 m_lastSignalId (0),
36 m_lastSignalIdBeforeReset (0)
37 {
38 NS_LOG_FUNCTION (this);
39 }
40
~LteInterference()41 LteInterference::~LteInterference ()
42 {
43 NS_LOG_FUNCTION (this);
44 }
45
46 void
DoDispose()47 LteInterference::DoDispose ()
48 {
49 NS_LOG_FUNCTION (this);
50 m_rsPowerChunkProcessorList.clear ();
51 m_sinrChunkProcessorList.clear ();
52 m_interfChunkProcessorList.clear ();
53 m_rxSignal = 0;
54 m_allSignals = 0;
55 m_noise = 0;
56 Object::DoDispose ();
57 }
58
59
60 TypeId
GetTypeId(void)61 LteInterference::GetTypeId (void)
62 {
63 static TypeId tid = TypeId ("ns3::LteInterference")
64 .SetParent<Object> ()
65 .SetGroupName("Lte")
66 ;
67 return tid;
68 }
69
70
71 void
StartRx(Ptr<const SpectrumValue> rxPsd)72 LteInterference::StartRx (Ptr<const SpectrumValue> rxPsd)
73 {
74 NS_LOG_FUNCTION (this << *rxPsd);
75 if (m_receiving == false)
76 {
77 NS_LOG_LOGIC ("first signal");
78 m_rxSignal = rxPsd->Copy ();
79 m_lastChangeTime = Now ();
80 m_receiving = true;
81 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
82 {
83 (*it)->Start ();
84 }
85 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
86 {
87 (*it)->Start ();
88 }
89 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
90 {
91 (*it)->Start ();
92 }
93 }
94 else
95 {
96 NS_LOG_LOGIC ("additional signal" << *m_rxSignal);
97 // receiving multiple simultaneous signals, make sure they are synchronized
98 NS_ASSERT (m_lastChangeTime == Now ());
99 // make sure they use orthogonal resource blocks
100 NS_ASSERT (Sum ((*rxPsd) * (*m_rxSignal)) == 0.0);
101 (*m_rxSignal) += (*rxPsd);
102 }
103 }
104
105
106 void
EndRx()107 LteInterference::EndRx ()
108 {
109 NS_LOG_FUNCTION (this);
110 if (m_receiving != true)
111 {
112 NS_LOG_INFO ("EndRx was already evaluated or RX was aborted");
113 }
114 else
115 {
116 ConditionallyEvaluateChunk ();
117 m_receiving = false;
118 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
119 {
120 (*it)->End ();
121 }
122 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
123 {
124 (*it)->End ();
125 }
126 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
127 {
128 (*it)->End ();
129 }
130 }
131 }
132
133
134 void
AddSignal(Ptr<const SpectrumValue> spd,const Time duration)135 LteInterference::AddSignal (Ptr<const SpectrumValue> spd, const Time duration)
136 {
137 NS_LOG_FUNCTION (this << *spd << duration);
138 DoAddSignal (spd);
139 uint32_t signalId = ++m_lastSignalId;
140 if (signalId == m_lastSignalIdBeforeReset)
141 {
142 // This happens when m_lastSignalId eventually wraps around. Given that so
143 // many signals have elapsed since the last reset, we hope that by now there is
144 // no stale pending signal (i.e., a signal that was scheduled
145 // for subtraction before the reset). So we just move the
146 // boundary further.
147 m_lastSignalIdBeforeReset += 0x10000000;
148 }
149 Simulator::Schedule (duration, &LteInterference::DoSubtractSignal, this, spd, signalId);
150 }
151
152
153 void
DoAddSignal(Ptr<const SpectrumValue> spd)154 LteInterference::DoAddSignal (Ptr<const SpectrumValue> spd)
155 {
156 NS_LOG_FUNCTION (this << *spd);
157 ConditionallyEvaluateChunk ();
158 (*m_allSignals) += (*spd);
159 }
160
161 void
DoSubtractSignal(Ptr<const SpectrumValue> spd,uint32_t signalId)162 LteInterference::DoSubtractSignal (Ptr<const SpectrumValue> spd, uint32_t signalId)
163 {
164 NS_LOG_FUNCTION (this << *spd);
165 ConditionallyEvaluateChunk ();
166 int32_t deltaSignalId = signalId - m_lastSignalIdBeforeReset;
167 if (deltaSignalId > 0)
168 {
169 (*m_allSignals) -= (*spd);
170 }
171 else
172 {
173 NS_LOG_INFO ("ignoring signal scheduled for subtraction before last reset");
174 }
175 }
176
177
178 void
ConditionallyEvaluateChunk()179 LteInterference::ConditionallyEvaluateChunk ()
180 {
181 NS_LOG_FUNCTION (this);
182 if (m_receiving)
183 {
184 NS_LOG_DEBUG (this << " Receiving");
185 }
186 NS_LOG_DEBUG (this << " now " << Now () << " last " << m_lastChangeTime);
187 if (m_receiving && (Now () > m_lastChangeTime))
188 {
189 NS_LOG_LOGIC (this << " signal = " << *m_rxSignal << " allSignals = " << *m_allSignals << " noise = " << *m_noise);
190
191 SpectrumValue interf = (*m_allSignals) - (*m_rxSignal) + (*m_noise);
192
193 SpectrumValue sinr = (*m_rxSignal) / interf;
194 Time duration = Now () - m_lastChangeTime;
195 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
196 {
197 (*it)->EvaluateChunk (sinr, duration);
198 }
199 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_interfChunkProcessorList.begin (); it != m_interfChunkProcessorList.end (); ++it)
200 {
201 (*it)->EvaluateChunk (interf, duration);
202 }
203 for (std::list<Ptr<LteChunkProcessor> >::const_iterator it = m_rsPowerChunkProcessorList.begin (); it != m_rsPowerChunkProcessorList.end (); ++it)
204 {
205 (*it)->EvaluateChunk (*m_rxSignal, duration);
206 }
207 m_lastChangeTime = Now ();
208 }
209 }
210
211 void
SetNoisePowerSpectralDensity(Ptr<const SpectrumValue> noisePsd)212 LteInterference::SetNoisePowerSpectralDensity (Ptr<const SpectrumValue> noisePsd)
213 {
214 NS_LOG_FUNCTION (this << *noisePsd);
215 ConditionallyEvaluateChunk ();
216 m_noise = noisePsd;
217 // reset m_allSignals (will reset if already set previously)
218 // this is needed since this method can potentially change the SpectrumModel
219 m_allSignals = Create<SpectrumValue> (noisePsd->GetSpectrumModel ());
220 if (m_receiving == true)
221 {
222 // abort rx
223 m_receiving = false;
224 }
225 // record the last SignalId so that we can ignore all signals that
226 // were scheduled for subtraction before m_allSignal
227 m_lastSignalIdBeforeReset = m_lastSignalId;
228 }
229
230 void
AddRsPowerChunkProcessor(Ptr<LteChunkProcessor> p)231 LteInterference::AddRsPowerChunkProcessor (Ptr<LteChunkProcessor> p)
232 {
233 NS_LOG_FUNCTION (this << p);
234 m_rsPowerChunkProcessorList.push_back (p);
235 }
236
237 void
AddSinrChunkProcessor(Ptr<LteChunkProcessor> p)238 LteInterference::AddSinrChunkProcessor (Ptr<LteChunkProcessor> p)
239 {
240 NS_LOG_FUNCTION (this << p);
241 m_sinrChunkProcessorList.push_back (p);
242 }
243
244 void
AddInterferenceChunkProcessor(Ptr<LteChunkProcessor> p)245 LteInterference::AddInterferenceChunkProcessor (Ptr<LteChunkProcessor> p)
246 {
247 NS_LOG_FUNCTION (this << p);
248 m_interfChunkProcessorList.push_back (p);
249 }
250
251
252
253
254 } // namespace ns3
255
256
257