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