Пример #1
0
    def test05(self):
        # 8PSK Convergence test with static rotation
        natfreq = 0.25
        order = 8
        self.test = digital.costas_loop_cc(natfreq, order)

        rot = cmath.exp(-cmath.pi / 8.0j)  # rotate to match Costas rotation
        const = psk.psk_constellation(order)
        data = [random.randint(0, 7) for i in range(100)]
        data = [2 * rot * const.points()[d] for d in data]

        N = 40  # settling time
        expected_result = data[N:]

        rot = cmath.exp(0.1j)  # some small rotation
        data = [rot * d for d in data]

        self.src = blocks.vector_source_c(data, False)
        self.snk = blocks.vector_sink_c()

        self.tb.connect(self.src, self.test, self.snk)
        self.tb.run()

        dst_data = self.snk.data()[N:]

        # generously compare results; the loop will converge near to, but
        # not exactly on, the target data
        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 2)
Пример #2
0
    def test05(self):
        # 8PSK Convergence test with static rotation
        natfreq = 0.25
        order = 8
        self.test = digital.costas_loop_cc(natfreq, order)

        rot = cmath.exp(-cmath.pi/8.0j) # rotate to match Costas rotation
        const = psk.psk_constellation(order)
        data = [random.randint(0,7) for i in xrange(100)]
        data = [2*rot*const.points()[d] for d in data]
        
        N = 40 # settling time
        expected_result = data[N:]

        rot = cmath.exp(0.1j) # some small rotation
        data = [rot*d for d in data]

        self.src = blocks.vector_source_c(data, False)
        self.snk = blocks.vector_sink_c()

        self.tb.connect(self.src, self.test, self.snk)
        self.tb.run()

        dst_data = self.snk.data()[N:]
        
	# generously compare results; the loop will converge near to, but
        # not exactly on, the target data
        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 2)
Пример #3
0
def gen_framer_info(modulation):
    mods = {
        "bpsk": 2,
        "qpsk": 4,
        "8psk": 8,
        "qam8": 8,
        "qam16": 16,
        "qam64": 64,
        "qam256": 256
    }
    arity = mods[modulation]

    rot = 1
    if modulation == "qpsk":
        rot = (0.707 + 0.707j)

    # FIXME: pass the constellation objects instead of just the points
    if (modulation.find("psk") >= 0):
        constel = psk.psk_constellation(arity)
        rotated_const = map(lambda pt: pt * rot, constel.points())
    elif (modulation.find("qam") >= 0):
        constel = qam.qam_constellation(arity)
        rotated_const = map(lambda pt: pt * rot, constel.points())

    return rotated_const
Пример #4
0
def gen_framer_info(modulation):
    mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
    arity = mods[modulation]

    rot = 1
    if modulation == "qpsk":
        rot = (0.707+0.707j)

    # FIXME: pass the constellation objects instead of just the points
    if(modulation.find("psk") >= 0):
        constel = psk.psk_constellation(arity)
        rotated_const = map(lambda pt: pt * rot, constel.points())
    elif(modulation.find("qam") >= 0):
        constel = qam.qam_constellation(arity)
        rotated_const = map(lambda pt: pt * rot, constel.points())

    return rotated_const
Пример #5
0
    def __init__(self, options, msgq_limit=2, pad_for_usrp=True, coder=None):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

	gr.hier_block2.__init__(self, "ofdm_mod",
				gr.io_signature(0, 0, 0),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

        self.coder = coder
        self._pad_for_usrp = pad_for_usrp
        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._pkt_accum = None
        self._accumulated_pkts = 0

        win = [] #[1 for i in range(self._fft_length)]

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)
                
        padded_preambles = list()
        for pre in preambles:
            padded = self._fft_length*[0,]
            padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre
            padded_preambles.append(padded)
            
        symbol_length = options.fft_length + options.cp_length
        
        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]
        
        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)
            
        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const
        self._pkt_input = digital_swig.ofdm_mapper_bcv(rotated_const,
                                                       msgq_limit,
                                                       options.occupied_tones,
                                                       options.fft_length)
        
        self.preambles = digital_swig.ofdm_insert_preamble(self._fft_length,
                                                           padded_preambles)
        self.ifft = gr.fft_vcc(self._fft_length, False, win, True)
        self.cp_adder = digital_swig.ofdm_cyclic_prefixer(self._fft_length,
                                                          symbol_length)
        self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
        
        self.connect((self._pkt_input, 0), (self.preambles, 0))
        self.connect((self._pkt_input, 1), (self.preambles, 1))
        self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self)
        
        if options.verbose:
            self._print_verbage()

        if options.log:
            self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                       "ofdm_mapper_c.dat"))
            self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                      "ofdm_preambles.dat"))
            self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                 "ofdm_ifft_c.dat"))
            self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex,
                                                     "ofdm_cp_adder_c.dat"))
Пример #6
0
    def __init__(self, options, callback=None, coder=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
	"""
	gr.hier_block2.__init__(self, "ofdm_demod",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature


        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY
        self.coder = coder
        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)

        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(self._fft_length,
                                       self._cp_length,
                                       self._occupied_tones,
                                       self._snr, preambles,
                                       options.log)

        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]
        
        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain*phgain / 4.0
        self.ofdm_demod = digital_swig.ofdm_frame_sink(rotated_const, range(arity),
                                                       self._rcvd_pktq,
                                                       self._occupied_tones,
                                                       phgain, frgain)

        self.connect(self, self.ofdm_recv)
        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        self.connect(self.ofdm_recv.chan_filt, self)

        if options.log:
            self.connect(self.ofdm_demod,
                         gr.file_sink(gr.sizeof_gr_complex*self._occupied_tones,
                                      "ofdm_frame_sink_c.dat"))
        else:
            self.connect(self.ofdm_demod,
                         gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones))

        if options.verbose:
            self._print_verbage()
            
        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback, self.coder)
Пример #7
0
    def __init__(self, options, msgq_limit=2, pad_for_usrp=True):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

        gr.hier_block2.__init__(
            self,
            "ofdm_mod",
            gr.io_signature(0, 0, 0),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        self._pad_for_usrp = pad_for_usrp
        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._carrier_map = options.carrier_map  # linklab
        self._nc_filter = options.nc_filter  # linklab

        win = []  #[1 for i in range(self._fft_length)]

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(
            math.ceil((self._fft_length - self._occupied_tones) / 2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if ((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq, )

        padded_preambles = list()
        for pre in preambles:
            padded = self._fft_length * [
                0,
            ]
            padded[zeros_on_left:zeros_on_left + self._occupied_tones] = pre
            padded_preambles.append(padded)

# linklab, sanity check: check carrier_map
        if ((4 * len(self._carrier_map) != self._occupied_tones) &
            (self._carrier_map != 'FFFF')):
            print(
                "Error: --carrier-map size %d is no equal to # of --occupied-tones"
            ) % (4 * (len(self._carrier_map)))
            raise SystemExit
        # check occupied_tones and cp_length
        if ((self._fft_length < self._occupied_tones) |
            (self._fft_length < self._cp_length)):
            print(
                "Error: --occupied-tones or --cp-length specified must not biger than --fft-length"
            )
            raise SystemExit

        # linklab, get subcarrier allocation from carrier_map
        self.calc_carrier_map(self._carrier_map)

        symbol_length = options.fft_length + options.cp_length

        mods = {
            "bpsk": 2,
            "qpsk": 4,
            "8psk": 8,
            "qam8": 8,
            "qam16": 16,
            "qam64": 64,
            "qam256": 256
        }
        arity = mods[self._modulation]

        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707 + 0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if (self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif (self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())

        self._pkt_input = gr_papyrus.ofdm_mapper_bcv(rotated_const, msgq_limit,
                                                     options.occupied_tones,
                                                     options.fft_length,
                                                     self._carrier_map)

        self.preambles = gr_papyrus.ofdm_insert_preamble(
            self._fft_length, padded_preambles)
        if VERBOSE:
            print "%s:%s" % (os.path.basename(__file__), __name__)
            print "**** (ofdm_mod) padded_preamble", padded_preambles
        self.ifft = fft.fft_vcc(self._fft_length, False, win, True)
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length,
                                                     symbol_length)
        self.scale = blocks.multiply_const_cc(1.0 /
                                              math.sqrt(self._fft_length))

        self.connect((self._pkt_input, 0), (self.preambles, 0))
        self.connect((self._pkt_input, 1), (self.preambles, 1))
        self.connect(self.preambles, self.ifft, self.cp_adder, self.scale,
                     self)

        if options.verbose:
            self._print_verbage()

        if options.log:
            self.connect(
                self._pkt_input,
                gr.file_sink(gr.sizeof_gr_complex * options.fft_length,
                             "ofdm_mapper_c.dat"))
            self.connect(
                self.preambles,
                gr.file_sink(gr.sizeof_gr_complex * options.fft_length,
                             "ofdm_preambles.dat"))
            self.connect(
                self.ifft,
                gr.file_sink(gr.sizeof_gr_complex * options.fft_length,
                             "ofdm_ifft_c.dat"))
            self.connect(
                self.cp_adder,
                gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat"))
Пример #8
0
    def __init__(self, options, callback=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
	"""
        gr.hier_block2.__init__(
            self,
            "ofdm_demod",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        self._rcvd_pktq = gr.msg_queue()  # holds packets from the PHY

        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr
        self._carrier_map = options.carrier_map  # linklab
        self._nc_filter = options.nc_filter  # linklab

        # linklab, sanity check carrier_map
        if ((4 * len(self._carrier_map) != self._occupied_tones) &
            (self._carrier_map != 'FFFF')):
            print(
                "Error: --carrier-map size %d is no equal to # of --occupied-tones"
            ) % (4 * (len(self._carrier_map)))
            raise SystemExit
        # check occupied_tones and cp_length
        if ((self._fft_length < self._occupied_tones) |
            (self._fft_length < self._cp_length)):
            print(
                "Error: --occupied-tones or --cp-length specified must not biger than --fft-length"
            )
            raise SystemExit

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(
            math.ceil((self._fft_length - self._occupied_tones) / 2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if ((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq, )

        # linklab, get subcarrier allocation from carrier_map
        self.calc_carrier_map(self._carrier_map)

        symbol_length = self._fft_length + self._cp_length
        # linklab, add carrier_map_bin

        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(
            self._fft_length,
            self._cp_length,
            self._occupied_tones,
            self._snr,
            preambles,
            self._carrier_map_bin,
            self._nc_filter,  #linklab
            options.log)
        if VERBOSE:
            print "%s:%s" % (os.path.basename(__file__), __name__)
            print "(ofdm_demod) preambles= ", preambles

        mods = {
            "bpsk": 2,
            "qpsk": 4,
            "8psk": 8,
            "qam8": 8,
            "qam16": 16,
            "qam64": 64,
            "qam256": 256
        }
        arity = mods[self._modulation]

        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707 + 0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if (self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif (self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain * phgain / 4.0
        self.ofdm_demod = gr_papyrus.ofdm_frame_sink(
            rotated_const, range(arity), self._rcvd_pktq, self._fft_length,
            self._occupied_tones, self._carrier_map_bin_str, phgain, frgain)

        self.connect(self, self.ofdm_recv)
        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        self.connect(self.ofdm_recv.chan_filt, self)

        if options.log:
            self.connect(
                self.ofdm_demod,
                gr.file_sink(gr.sizeof_gr_complex * self._occupied_tones,
                             "ofdm_frame_sink_c.dat"))
        else:
            self.connect(
                self.ofdm_demod,
                blocks.null_sink(gr.sizeof_gr_complex * self._occupied_tones))

        if options.verbose:
            self._print_verbage()

        # linklab, add ofdm_recv to queue watcher
        #self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback),
        self._watcher = _queue_watcher_thread(self._rcvd_pktq, self.ofdm_recv,
                                              callback)
Пример #9
0
    def __init__(self, options, msgq_limit=2, pad_for_usrp=True):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        Args:
            options: pass modulation options from higher layers (fft length, occupied tones, etc.)
            msgq_limit: maximum number of messages in message queue (int)
            pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

	gr.hier_block2.__init__(self, "ofdm_mod",
				gr.io_signature(0, 0, 0),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

        self._pad_for_usrp = pad_for_usrp
        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length

        win = [] #[1 for i in range(self._fft_length)]

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)

        padded_preambles = list()
        for pre in preambles:
            padded = self._fft_length*[0,]
            padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre
            padded_preambles.append(padded)

        symbol_length = options.fft_length + options.cp_length

        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]

        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const
        self._pkt_input = digital.ofdm_mapper_bcv(rotated_const,
                                                  msgq_limit,
                                                  options.occupied_tones,
                                                  options.fft_length)

        self.preambles = digital.ofdm_insert_preamble(self._fft_length,
                                                      padded_preambles)
        self.ifft = fft.fft_vcc(self._fft_length, False, win, True)
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length,
                                                     symbol_length)
        self.scale = blocks.multiply_const_cc(1.0 / math.sqrt(self._fft_length))

        # self.connect((self._pkt_input, 0), (self.preambles, 0))
        # self.connect((self._pkt_input, 1), (self.preambles, 1))
        # self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self)

        self.nuller = blocks.null_sink(gr.sizeof_char)
        self.v2s = blocks.vector_to_stream(gr.sizeof_gr_complex*1,self._fft_length)
        self.connect((self._pkt_input, 0), self.v2s, self)
        self.connect((self._pkt_input, 1), self.nuller)


        if options.verbose:
            self._print_verbage()

        if options.log:
            self.connect(self._pkt_input, blocks.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                       "ofdm_mapper_c.dat"))
            self.connect(self.preambles, blocks.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                      "ofdm_preambles.dat"))
            self.connect(self.ifft, blocks.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                 "ofdm_ifft_c.dat"))
            self.connect(self.cp_adder, blocks.file_sink(gr.sizeof_gr_complex,
                                                     "ofdm_cp_adder_c.dat"))
Пример #10
0
    def __init__(self, options, num_channels, callback=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        Args:
            options: pass modulation options from higher layers (fft length, occupied tones, etc.)
            callback: function of two args: ok, payload (ok: bool; payload: string)
	"""

        self.rx_channels = num_channels#len(options.args.split(','))

	gr.hier_block2.__init__(self, "ofdm_demod",
				gr.io_signaturev(self.rx_channels, self.rx_channels, gen_multiple_ios(self.rx_channels,1) ), # Input signature
				gr.io_signaturev(self.rx_channels, self.rx_channels, gen_multiple_ios(self.rx_channels,options.occupied_tones) ))
                #[gr.sizeof_gr_complex*options.occupied_tones, gr.sizeof_gr_complex*options.occupied_tones])) # Output signature


        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY from all receive channels

        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)

        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(self.rx_channels, self._fft_length,
                                       self._cp_length,
                                       self._occupied_tones,
                                       self._snr, preambles,
                                       options.log)

        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]

        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain*phgain / 4.0
        # self.ofdm_demod = ofdm.ofdm_frame_sink(rotated_const, range(arity),self._rcvd_pktq,self._occupied_tones,phgain, frgain, 3)
        self.ofdm_demod = ofdm.ofdm_mrx_frame_sink(rotated_const, range(arity),self._rcvd_pktq,self._occupied_tones,phgain, frgain, self.rx_channels)

        self.mdb = blocks.message_debug()

        ############# CONNECTIONS ##############

        # Connect ofdm_receiver flag to ofdm framer flag
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 0)) # Connect flag from 1st chain only

        # Connect frame sink msg port to debugger
        self.msg_connect((self.ofdm_demod, 'packet'), (self.mdb,'print'))

        # Connect remaining data ports
        port = 0
        for c in range(self.rx_channels):

            # Connect USRP's to channel filters
            self.connect((self,c), (self.ofdm_recv,c))

            # Add null sink
            object_name_ns = 'null_sink_'+str(c)
            setattr(self, object_name_ns, blocks.null_sink(gr.sizeof_char*1))

            # Connect ofdm_receiver to ofdm framer
            self.connect((self.ofdm_recv, port), (self.ofdm_demod, c+1)) # Occupied tones

            # Connect extra port(s) to null since we dont need it now
            self.connect((self.ofdm_recv, port+1), (getattr(self,object_name_ns), 0))
            port = port + 2

            # Connect equalized signals to output
            self.connect((self.ofdm_demod, c), (self, c))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        # self.connect(self.ofdm_recv.chan_filt, (self,0))

        ############## ##############

        if options.log:
            self.connect(self.ofdm_demod,
                         blocks.file_sink(gr.sizeof_gr_complex*self._occupied_tones,
                                      "ofdm_frame_sink_c.dat"))
        else:
            self.connect(self.ofdm_demod,
                         blocks.null_sink(gr.sizeof_gr_complex*self._occupied_tones))

        if options.verbose:
            self._print_verbage()

        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
Пример #11
0
    def __init__(self, options, callback=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
	"""
        gr.hier_block2.__init__(
            self,
            "ofdm_demod",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature2(2, 2, gr.sizeof_gr_complex,
                             gr.sizeof_float))  # Output signature

        self._rcvd_pktq = gr.msg_queue()  # holds packets from the PHY

        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr
        self._use_coding = options.coding
        self._coding_block_length = options.block_length
        self._adaptive_coding_enabled = options.adaptive_coding
        self._rfcenterfreq = options.rx_freq
        self._bandwidth = options.my_bandwidth
        self._logging = lincolnlog.LincolnLog(__name__)
        self._expected_pkt_size = options.expected_pkt_size
        self._vcsthresh = options.vcsthresh

        # if backoff is negative, calculate backoff value from options.expected_pkt_size
        if options.backoff < 0:
            self._vcsbackoff = predict_pack_size(
                self._expected_pkt_size, self._use_coding, self._modulation,
                self._occupied_tones, self._cp_length, self._fft_length)

        # otherwise use the value in options.backoff
        else:
            self._vcsbackoff = options.backoff

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(
            math.ceil((self._fft_length - self._occupied_tones) / 2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if ((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq, )

        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(self._fft_length, self._cp_length,
                                       self._occupied_tones, self._snr,
                                       preambles, self._vcsthresh,
                                       self._vcsbackoff, options.log,
                                       options.coding)

        mods = {
            "bpsk": 2,
            "qpsk": 4,
            "8psk": 8,
            "qam8": 8,
            "qam16": 16,
            "qam64": 64,
            "qam256": 256
        }
        arity = mods[self._modulation]

        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707 + 0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if (self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif (self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain * phgain / 4.0
        self.ofdm_demod = digital_ll.ofdm_frame_sink(rotated_const,
                                                     range(arity),
                                                     self._rcvd_pktq,
                                                     self._occupied_tones,
                                                     phgain, frgain)

        self.nsink = gr.null_sink(gr.sizeof_float)

        self.connect(self, self.ofdm_recv)
        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))

        # Output the VCS signal so that the MAC layer knows when the
        # channel is occupied
        #self.connect((self.ofdm_recv, 2), gr.null_sink(gr.sizeof_float))
        self.connect((self.ofdm_recv, 2), (self, 1))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        self.connect(self.ofdm_recv.chan_filt, (self, 0))

        if options.log:
            self.connect(
                self.ofdm_demod,
                gr.file_sink(gr.sizeof_gr_complex * self._occupied_tones,
                             "ofdm_frame_sink_c.dat"))
        else:
            self.connect(
                self.ofdm_demod,
                gr.null_sink(gr.sizeof_gr_complex * self._occupied_tones))

        if options.verbose:
            self._print_verbage()

        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback,
                                              self._use_coding,
                                              self._coding_block_length,
                                              self._adaptive_coding_enabled,
                                              self._rfcenterfreq,
                                              self._bandwidth, self._logging)
Пример #12
0
    def __init__(self, options, msgq_limit=2, pad_for_usrp=True):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

	gr.hier_block2.__init__(self, "ofdm_mod",
				gr.io_signature(0, 0, 0),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

        self._pad_for_usrp = pad_for_usrp
        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._carrier_map = options.carrier_map # linklab
	self._nc_filter = options.nc_filter # linklab

        win = [] #[1 for i in range(self._fft_length)]

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)
                
        padded_preambles = list()
        for pre in preambles:
            padded = self._fft_length*[0,]
            padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre
            padded_preambles.append(padded)
            
	# linklab, sanity check: check carrier_map
        if ((4*len(self._carrier_map) != self._occupied_tones) & (self._carrier_map != 'FFFF')):
            print("Error: --carrier-map size %d is no equal to # of --occupied-tones") %(4*(len(self._carrier_map)))
            raise SystemExit
        # check occupied_tones and cp_length
        if ((self._fft_length < self._occupied_tones) | (self._fft_length < self._cp_length)):
            print("Error: --occupied-tones or --cp-length specified must not biger than --fft-length")
            raise SystemExit

        # linklab, get subcarrier allocation from carrier_map
        self.calc_carrier_map(self._carrier_map)


        symbol_length = options.fft_length + options.cp_length
        
        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]
        
        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)
            
        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        
        self._pkt_input = gr_papyrus.ofdm_mapper_bcv(rotated_const,
                                                       msgq_limit,
                                                       options.occupied_tones,
                                                       options.fft_length,self._carrier_map)
        
        self.preambles = gr_papyrus.ofdm_insert_preamble(self._fft_length,
                                                           padded_preambles)
        if VERBOSE:
          print "%s:%s" %(os.path.basename(__file__), __name__)
          print "**** (ofdm_mod) padded_preamble", padded_preambles
        self.ifft = fft.fft_vcc(self._fft_length, False, win, True)
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length,
                                                          symbol_length)
        self.scale = blocks.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
        
        self.connect((self._pkt_input, 0), (self.preambles, 0))
        self.connect((self._pkt_input, 1), (self.preambles, 1))
        self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self)
        
        if options.verbose:
            self._print_verbage()

        if options.log:
            self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                       "ofdm_mapper_c.dat"))
            self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                      "ofdm_preambles.dat"))
            self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
                                                 "ofdm_ifft_c.dat"))
            self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex,
                                                     "ofdm_cp_adder_c.dat"))
Пример #13
0
    def __init__(self, options, callback=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
	"""
	gr.hier_block2.__init__(self, "ofdm_demod",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

        
        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY

        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr
        self._carrier_map = options.carrier_map # linklab
        self._nc_filter = options.nc_filter # linklab
        
        # linklab, sanity check carrier_map
        if ((4*len(self._carrier_map) != self._occupied_tones) & (self._carrier_map != 'FFFF')):
            print("Error: --carrier-map size %d is no equal to # of --occupied-tones") %(4*(len(self._carrier_map)))
            raise SystemExit
        # check occupied_tones and cp_length
        if ((self._fft_length < self._occupied_tones) | (self._fft_length < self._cp_length)):
            print("Error: --occupied-tones or --cp-length specified must not biger than --fft-length")
            raise SystemExit
        
        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)
        
          # linklab, get subcarrier allocation from carrier_map
        self.calc_carrier_map(self._carrier_map)
        
        symbol_length = self._fft_length + self._cp_length
        # linklab, add carrier_map_bin
        
        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(self._fft_length,
                                       self._cp_length,
                                       self._occupied_tones,
                                       self._snr, preambles,
                                       self._carrier_map_bin,
                                       self._nc_filter, #linklab
                                       options.log)
        if VERBOSE:
          print "%s:%s" %(os.path.basename(__file__), __name__)
          print "(ofdm_demod) preambles= ", preambles

        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]
        
        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain*phgain / 4.0
        self.ofdm_demod = gr_papyrus.ofdm_frame_sink(rotated_const, range(arity),
                                                       self._rcvd_pktq,
                                                       self._fft_length,
                                                       self._occupied_tones,
                                                       self._carrier_map_bin_str,
                                                       phgain, frgain)

        
        self.connect(self, self.ofdm_recv)
        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        self.connect(self.ofdm_recv.chan_filt, self)

        if options.log:
            self.connect(self.ofdm_demod,
                         gr.file_sink(gr.sizeof_gr_complex*self._occupied_tones,
                                      "ofdm_frame_sink_c.dat"))
        else:
            self.connect(self.ofdm_demod,
                         blocks.null_sink(gr.sizeof_gr_complex*self._occupied_tones))

        if options.verbose:
            self._print_verbage()
            
        # linklab, add ofdm_recv to queue watcher
        #self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback),
        self._watcher = _queue_watcher_thread(self._rcvd_pktq, self.ofdm_recv, callback)
Пример #14
0
    def __init__(self, options, callback=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
	"""
	gr.hier_block2.__init__(self, "ofdm_demod",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature2(2, 2, gr.sizeof_gr_complex, gr.sizeof_float)) # Output signature


        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY

        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr
        self._use_coding = options.coding
        self._coding_block_length = options.block_length
        self._adaptive_coding_enabled = options.adaptive_coding
        self._rfcenterfreq = options.rx_freq
        self._bandwidth = options.my_bandwidth
        self._logging    = lincolnlog.LincolnLog(__name__)
        self._expected_pkt_size = options.expected_pkt_size
        self._vcsthresh  = options.vcsthresh
                
        # if backoff is negative, calculate backoff value from options.expected_pkt_size 
        if options.backoff < 0:
            self._vcsbackoff = predict_pack_size( self._expected_pkt_size, self._use_coding, self._modulation, self._occupied_tones, self._cp_length, self._fft_length )
        
        # otherwise use the value in options.backoff     
        else:    
            self._vcsbackoff = options.backoff

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)

        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(self._fft_length,
                                       self._cp_length,
                                       self._occupied_tones,
                                       self._snr, preambles,
                                       self._vcsthresh,
                                       self._vcsbackoff,
                                       options.log, options.coding)

        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]
        
        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain*phgain / 4.0
        self.ofdm_demod = digital_ll.ofdm_frame_sink(rotated_const, range(arity),
                                                       self._rcvd_pktq,
                                                       self._occupied_tones,
                                                       phgain, frgain)

        self.nsink = gr.null_sink(gr.sizeof_float)
        
        self.connect(self, self.ofdm_recv)
        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))
        
        # Output the VCS signal so that the MAC layer knows when the 
        # channel is occupied
        #self.connect((self.ofdm_recv, 2), gr.null_sink(gr.sizeof_float))
        self.connect((self.ofdm_recv, 2), (self, 1))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        self.connect(self.ofdm_recv.chan_filt, (self,0))

        if options.log:
            self.connect(self.ofdm_demod,
                         gr.file_sink(gr.sizeof_gr_complex*self._occupied_tones,
                                      "ofdm_frame_sink_c.dat"))
        else:
            self.connect(self.ofdm_demod,
                         gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones))

        if options.verbose:
            self._print_verbage()
            
        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback, self._use_coding, self._coding_block_length, self._adaptive_coding_enabled,
                                              self._rfcenterfreq,self._bandwidth,self._logging)