Statistics
| Branch: | Revision:

root / src / sim / cdataratechannel.cc @ e26d3d25

History | View | Annotate | Download (4.88 KB)

1 01873262 Georg Kunz
//========================================================================
2
//  CDATARATECHANNEL.CC - part of
3
//
4
//                 OMNeT++/OMNEST
5
//              Discrete System Simulation in C++
6
//
7
//========================================================================
8
9
/*--------------------------------------------------------------*
10
  Copyright (C) 1992-2008 Andras Varga
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16
17
#include "cdataratechannel.h"
18
#include "cmessage.h"
19
#include "cmodule.h"
20
#include "cenvir.h"
21
#include "random.h"
22
#include "distrib.h"
23
#include "csimulation.h"
24
#include "globals.h"
25
#include "cgate.h"
26
#include "cexception.h"
27
#include "ctimestampedvalue.h"
28
29
#ifdef WITH_PARSIM
30
#include "ccommbuffer.h"
31
#endif
32
33
USING_NAMESPACE
34
35
using std::ostream;
36
37
Register_Class(cDatarateChannel);
38
39
simsignal_t cDatarateChannel::channelBusySignal;
40
simsignal_t cDatarateChannel::messageSentSignal;
41
simsignal_t cDatarateChannel::messageDiscardedSignal;
42
43
cDatarateChannel::cDatarateChannel(const char *name) : cChannel(name)
44
{
45
    txfinishtime = 0;
46
    delay = 0;
47
    datarate = 0;
48
    ber = 0;
49
    per = 0;
50
}
51
52
cDatarateChannel::~cDatarateChannel()
53
{
54
}
55
56
cDatarateChannel *cDatarateChannel::create(const char *name)
57
{
58
    return dynamic_cast<cDatarateChannel *>(cChannelType::getDatarateChannelType()->create(name));
59
}
60
61
std::string cDatarateChannel::info() const
62
{
63
    return cChannel::info();
64
}
65
66
void cDatarateChannel::initialize()
67
{
68
    channelBusySignal = registerSignal("channelBusy");
69
    messageSentSignal = registerSignal("messageSent");
70
    messageDiscardedSignal = registerSignal("messageDiscarded");
71
72
    emit(channelBusySignal, 0);
73
}
74
75
void cDatarateChannel::rereadPars()
76
{
77
    delay = par("delay");
78
    datarate = par("datarate");
79
    ber = par("ber");
80
    per = par("per");
81
82
    if (delay < 0)
83
        throw cRuntimeError(this, "negative delay %s", SIMTIME_STR(delay));
84
    if (datarate < 0)
85
        throw cRuntimeError(this, "negative datarate %g", datarate);
86
    if (ber < 0 || ber > 1)
87
        throw cRuntimeError(this, "wrong bit error rate %g", ber);
88
    if (per < 0 || per > 1)
89
        throw cRuntimeError(this, "wrong packet error rate %g", per);
90
91
    setFlag(FL_ISDISABLED, par("disabled"));
92
    setFlag(FL_DELAY_NONZERO, delay!=0);
93
    setFlag(FL_DATARATE_NONZERO, datarate!=0);
94
    setFlag(FL_BER_NONZERO, ber!=0);
95
    setFlag(FL_PER_NONZERO, per!=0);
96
}
97
98
void cDatarateChannel::handleParameterChange(const char *)
99
{
100
    rereadPars();
101
}
102
103
void cDatarateChannel::setDelay(double d)
104
{
105
    par("delay").setDoubleValue(d);
106
}
107
108
void cDatarateChannel::setDatarate(double d)
109
{
110
    par("datarate").setDoubleValue(d);
111
}
112
113
void cDatarateChannel::setBitErrorRate(double d)
114
{
115
    par("ber").setDoubleValue(d);
116
}
117
118
void cDatarateChannel::setPacketErrorRate(double d)
119
{
120
    par("per").setDoubleValue(d);
121
}
122
123
void cDatarateChannel::setDisabled(bool d)
124
{
125
    par("disabled").setBoolValue(d);
126
}
127
128
simtime_t cDatarateChannel::calculateDuration(cMessage *msg) const
129
{
130
    if (flags & FL_DATARATE_NONZERO && msg->isPacket())
131
        return ((cPacket *)msg)->getBitLength() / datarate;
132
    else
133
        return SIMTIME_ZERO;
134
}
135
136
void cDatarateChannel::processMessage(cMessage *msg, simtime_t t, result_t& result)
137
{
138
    // if channel is disabled, signal that message should be deleted
139
    if (flags & FL_ISDISABLED)
140
    {
141
        result.discard = true;
142
        cTimestampedValue tmp(t, msg);
143
        emit(messageDiscardedSignal, &tmp);
144
        return;
145
    }
146
147
    // datarate modeling
148
    if ((flags & FL_DATARATE_NONZERO) && msg->isPacket())
149
    {
150
        cPacket *pkt = (cPacket *)msg;
151
        simtime_t duration = pkt->getBitLength() / datarate;
152
        result.duration = duration;
153
        txfinishtime = t + duration;
154
    }
155
    else {
156
        txfinishtime = t;
157
    }
158
159
    // propagation delay modeling
160
    result.delay = delay;
161
162
    // bit error modeling
163
    if ((flags & (FL_BER_NONZERO | FL_PER_NONZERO)) && msg->isPacket())
164
    {
165
        cPacket *pkt = (cPacket *)msg;
166
        if (flags & FL_BER_NONZERO)
167
            if (dblrand() < 1.0 - pow(1.0-ber, (double)pkt->getBitLength()))
168
                pkt->setBitError(true);
169
        if (flags & FL_PER_NONZERO)
170
            if (dblrand() < per)
171
                pkt->setBitError(true);
172
    }
173
174
    // emit signals
175
    if (mayHaveListeners(messageSentSignal))
176
    {
177
        MessageSentSignalValue tmp(t, msg, &result);
178
        emit(messageSentSignal, &tmp);
179
    }
180
    if (mayHaveListeners(channelBusySignal))
181
    {
182
        cTimestampedValue tmp(t, 1L);
183
        emit(channelBusySignal, &tmp);
184
185
        tmp.timestamp = txfinishtime; tmp.l = 0L;
186
        emit(channelBusySignal, &tmp);
187
    }
188
}
189
190
void cDatarateChannel::forceTransmissionFinishTime(simtime_t t)
191
{
192
    //TODO record this into the eventlog so that it can be visualized in the sequence chart
193
    txfinishtime = t;
194
}