Esempio n. 1
0
    def thermalnoise(bandwidth):
        """Compute thermal noise floor for communication systems with given
        bandwidth.

        :param bandwidth: Bandwidth of system (in Hz).
        :return: Thermal noise noise power (in dBm).

        See `Thermal Noise`_ for more on how the thermal noise floor of a
        communications system is computed in this method.

        .. _`Thermal Noise`: http://en.wikipedia.org/wiki/Thermal_noise#Noise_in_decibels
        """
        noise_dbm = -174.01 + linear2db(bandwidth)
        return noise_dbm
Esempio n. 2
0
    def rxenergy(self):
        """Calculate total receive energy of packets in `rxbuffer`.

        :return: Receive power (in dBm), or -Inf if nothing is in `rxbuffer`.

        This method uses the 'rxpower' annotation of packets in `rxbuffer` to
        determine the total receive power. Any packets that do not support this
        annotation will not contribute to the total power calculated.
        """
        tot = 0     # sum total in milliwatts
        for p in self.rxbuffer:
            if ANNO.supports(p, 'rxpower'):
                prx = p.getanno('rxpower')  # rxpower in dBm
                tot += db2linear(prx)
        tot_dbm = linear2db(tot)
        return tot_dbm
Esempio n. 3
0
    def calcper_data(self, p, **kwargs):
        """Calculate probability of error for data decoding.

        :param p: Packet being decoded.
        :param kwargs: Additional keywords arguments passed to `sinr_heap()`
                       (or `sinr()`).
        :return: PER for decoding packet payload.

        This method sets the 'dot11a-sinr' and 'dot11a-per' annotations. The
        operation of this method depends on `DOT11A_USE_PIECEWISE_PER`.
        """
        for a in ["cif-rxts", "cif-duration"]:
            errmsg = "[DOT11APHY]: calcper_data() cannot find " + "'%s' annotation!" % (a)
            assert ANNO.supports(p, a), errmsg
        # verify header parameters
        plen = len(p.payload)
        rate, length = p.rate, p.length
        assert 0 <= rate < len(DOT11A_DATARATE), "[DOT11A]: Invalid rate option (%s)!" % (rate)
        assert p.length == plen, "[DOT11A]: Header length reported " + "does not equal payload length; %s!=%s" % (
            p.length,
            plen,
        )
        # calculate PER using appropriate method
        if DOT11A_USE_PIECEWISE_PER:
            sinrheap = self.sinr_heap(p, **kwargs)
            t1 = p.getanno("cif-rxts") + p.getanno("cif-duration")
            t0 = t1 - self.calcnofdm(plen, rate) * DOT11A_TSYM
            xheap = [(max(ta, t0), min(tb, t1), sinr) for (ta, tb, sinr) in sinrheap if (ta < t1) and (tb > t0)]
            errmsg = "[DOT11APHY]: Unable to find valid data from SINR heap!"
            assert len(xheap) > 0, errmsg
            # calculate piecewise PER and average SINR
            psuccess, stot = 1.0, 0.0
            for ta, tb, sinr in xheap:
                alpha = (tb - ta) / (t1 - t0)
                dlen = plen * alpha
                stot += db2linear(sinr) * alpha
                psuccess *= 1.0 - self.calcper(dlen, rate, sinr)
            per = 1.0 - psuccess
            sinr = linear2db(stot)
        else:
            # configure modulation and coding to calculate PER
            sinr, plen = self.sinr(p, **kwargs), length
            per = self.calcper(plen, rate, sinr)
        # set annotations and return PER
        p.setanno("dot11a-sinr", sinr)
        p.setanno("dot11a-per", per)
        return per
Esempio n. 4
0
    def sinr_heap(self, p, force=True):
        """Calculate signal-to-interference-and noise ratio (SINR) for each
        partition created by `interval_heap()`.

        :param p: Packet to inspect.
        :param force: If true, recalculate interval heap, else use existing
                      annotation if it exists.
        :return: SINR heap.

        SINR heap has looks like this:

            [(t0, t1, sinr0), (t1, t2, sinr1), ... ]

        Note: This method uses the 'rxpower' and 'noisepower' annotations.
        """
        # check packet
        errmsg = "[CHANNELIF]: sinr_heap() cannot process non-Packet!"
        assert ANNO.supported(p), errmsg
        for a in ['rxpower', 'noisepower']:
            errmsg = "[CHANNELIF]: sinr_heap() cannot find '%s' annotation!"%(a)
            assert ANNO.supports(p, a), errmsg
        # get parameters
        rxpower = p.getanno('rxpower')          # in dBm
        noisepower = p.getanno('noisepower')    # in dBm
        npow = db2linear(noisepower)
        # get interval heap
        if p.hasanno('cif-iheap') and not force:
            iheap = p.getanno('cif-iheap')
        else:
            iheap = self.interval_heap(p)
        # start creating sinr heap
        sinrheap = []
        #print "%s: SINR heap for %s @ %.8f"%(self.traceid, p.traceid, now())
        for ta,tb,coll in iheap:
            ipow = 0
            for c in coll:
                errmsg = "[CHANNELIF]: sinr_heap() cannot find 'rxpower' " + \
                         "annotation in collision list!"
                assert ANNO.supports(c, 'rxpower'), errmsg
                ipow += db2linear(c.getanno('rxpower') )
            sinr = rxpower - linear2db(ipow + npow)
            sinrheap.append((ta,tb,sinr) )
            #print "  --> (%.8f, %.8f): %.3f dB, coll = %s"%(ta,tb, sinr, [c.traceid for c in coll])
        return sinrheap
Esempio n. 5
0
    def calcpathloss(cls, dist, bpdist=None, n=None, **kwargs):
        """Calculate propagation loss using breakpoint pathloss model.

        :param dist: Separation distance between transmitter and receiver.
        :param bpdist: Breakpoint distance (in meters).
        :param n: Pathloss exponent.
        :param kwargs: Additional parameters passed to `freespace()`.
        :return: Pathloss (in dB).

        The breakpoint pathloss model uses freespace propagation up to the
        breakpoint distance and the specified pathloss thereafter.
        """
        if n is None: n = cls.n
        if ((bpdist>0) and (dist>bpdist)):
            bploss = cls.freespace(bpdist, n=2.0, **kwargs)
            PL = bploss + n*linear2db(dist/(1.0*bpdist) )
        else:
            PL = cls.freespace(dist, n=2.0, **kwargs)
        return PL
Esempio n. 6
0
    def calcpathloss(cls, dist, refdist=None, refloss=None, n=None, **kwargs):
        """Calculate propagation loss using reference pathloss model.

        :param dist: Separation distance between transmitter and receiver.
        :param refdist: Reference distance (in meters).
        :param refloss: Pathloss at reference distance (in dB).
        :param n: Pathloss exponent.
        :return: Pathloss (in dB).

        If reference distance `refdist` is None, and no suitable class variable
        is defined, this method will simply return the `freespace` pathloss. If
        `refdist` is defined and `refloss` is None, this method will compute the
        reference pathloss as the freespace pathloss using loss exponent 2.
        """
        if n is None: n = cls.n
        if refdist>0:
            if refloss is None: refloss = cls.freespace(refdist, n=2, **kwargs)
            PL = refloss + n*linear2db(dist/(1.0*refdist) )
        else:
            PL = cls.freespace(dist, n=n, **kwargs)
        return PL
Esempio n. 7
0
    def calcper_header(self, p, **kwargs):
        """Calculate probability of error for header decoding.

        :param p: Packet being decoded.
        :param kwargs: Additional keywords arguments passed to `sinr_heap()`
                       (or `sinr()`).
        :return: PER for header decoding.

        This method sets the 'dot11a-sinr' and 'dot11a-per' annotations. The
        operation of this method depends on `DOT11A_USE_PIECEWISE_PER`.
        """
        for a in ["cif-rxts"]:
            errmsg = "[DOT11APHY]: calcper_header() cannot find " + "'%s' annotation!" % (a)
            assert ANNO.supports(p, a), errmsg
        # calculate PER using appropriate method
        plen = len(p.payload)
        if DOT11A_USE_PIECEWISE_PER:
            sinrheap = self.sinr_heap(p, **kwargs)
            t0 = p.getanno("cif-rxts") + DOT11A_TSHORT + DOT11A_TLONG
            t1 = t0 + DOT11A_TSIGNAL
            xheap = [(max(ta, t0), min(tb, t1), sinr) for (ta, tb, sinr) in sinrheap if (ta < t1) and (tb > t0)]
            errmsg = "[DOT11APHY]: Unable to find valid data from SINR heap!"
            assert len(xheap) > 0, errmsg
            # calculate piecewise PER and average SINR
            psuccess, stot = 1.0, 0.0
            for ta, tb, sinr in xheap:
                alpha = (tb - ta) / (t1 - t0)
                hlen = len(Dot11A()) * alpha
                stot += db2linear(sinr) * alpha
                psuccess *= 1.0 - self.calcper(hlen, 0, sinr)
            per = 1.0 - psuccess
            sinr = linear2db(stot)
        else:
            sinr, hlen = self.sinr(p, **kwargs), len(p) - plen
            # configure modulation and coding to calculate PER
            per = self.calcper(hlen, 0, sinr)
        # set annotations and return PER
        p.setanno("dot11a-sinr", sinr)
        p.setanno("dot11a-per", per)
        return per