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)
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 # 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)
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(2, 2, 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._show_vector_analyzer = options.show_vector_analyzer # 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] # This fixed the bug, when the occupied tones are greater that the known symbols ksfreq = [0] * self._occupied_tones known_symbols_len = len(known_symbols_4512_3) for i in range(self._occupied_tones): ksfreq[i] = known_symbols_4512_3[i % known_symbols_len] 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 = {"qpsk": 4, "qam16": 16, "qam64": 64} arity = mods[self._modulation] rot = 1 # FIXME: pass the constellation objects instead of just the points if(self._modulation.find("qpsk") >= 0): constel = dvbt_constellations.dvbt_qpsk_constellation(arity) elif(self._modulation.find("qam16") >= 0): constel = dvbt_constellations.dvbt_16qam_constellation(arity,False,mod_codes.GRAY_CODE) elif(self._modulation.find("qam64") >= 0): constel = dvbt_constellations.dvbt_64qam_constellation(arity,False,mod_codes.GRAY_CODE) rotated_const = constel.points() print rotated_const phgain = 0.25 frgain = phgain*phgain / 4.0 #Create constellation objects for pilot signals cs_constel = dvbt_constellations.dvbt_cs_pilots() tps_constel = dvbt_constellations.dvbt_tps_pilots() self.ofdm_demod = digital_swig.dvbt_ofdm_frame_sink(rotated_const, tps_constel.points(), cs_constel.points(), 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)) # Vector analyzer output self.connect((self.ofdm_recv, 0), (self, 1)) #if(self._show_vector_analyzer == "yes"): # For qt # self.connect((self.ofdm_recv, 0), (self.ofdm_vector_analyzer_c, 0)) 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)
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)
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._bandwidth = options.bandwidth self._precoding = False #options.precoding # 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._bandwidth, self._fft_length, self._cp_length, self._occupied_tones, self._snr, preambles, options.log, options.mode) 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)) if self._precoding: self.connect((self.ofdm_recv, 2), (self.ofdm_demod, 2)) # output CFO value # 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)
def __init__(self, options, callback=None, fwd_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 # apurv++ queues # self._out_pktq = gr.msg_queue() 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 # apurv++ start # self._id = options.id self._fec_n = options.fec_n self._fec_k = options.fec_k self._batch_size = options.batch_size self._threshold = options.threshold self._size = options.size if(self._fec_n < self._fec_k): print "ERROR: K > N in FEC!\n" exit(0); # apurv++ end # # 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)) # apurv: use the preamble as a function of hop number # #ksfreq = known_symbols_4512_3[0:self._occupied_tones] start_index = (options.hop-1) * self._occupied_tones ksfreq = known_symbols_4512_3[start_index:start_index + self._occupied_tones] # allow another full preamble (no intermediate 0s for accurate channel estimate/snr measurement) preamble2_offset = 10*self._occupied_tones; ksfreq2 = known_symbols_4512_3[preamble2_offset:preamble2_offset+self._occupied_tones] ''' # inserting zeros in every other frequency bin # for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): ksfreq[i] = 0 ''' # hard-coded known symbols preambles = (ksfreq, ksfreq2) #, ksfreq2, ksfreq2, ksfreq2) # coarse_offset from 1st preamble, equalizer from the rest 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._threshold, options, options.log) mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} # apurv: support for other modulations, pass 2 constellation objects # hdr_rot = 1 hdr_arity = mods["bpsk"] hdr_constel = psk.psk_constellation(hdr_arity) hdr_rotated_const = map(lambda pt: pt * hdr_rot, hdr_constel.points()) data_rot = 1 data_arity = mods[self._modulation] if self._modulation == "qpsk": data_rot = (0.707+0.707j) if(self._modulation.find("psk") >= 0): data_constel = psk.psk_constellation(data_arity) data_rotated_const = map(lambda pt: pt * data_rot, data_constel.points()) elif(self._modulation.find("qam") >= 0): data_constel = qam.qam_constellation(data_arity) data_rotated_const = map(lambda pt: pt * data_rot, data_constel.points()) self._bits_per_symbol = int(math.log(mods[self._modulation], 2)) # just a useless parameter now # phgain = 0.25 frgain = phgain*phgain / 4.0 # preambles contains all the 'preambles' used in frame_acquisition + 1 (for snr calculation) preambles = (ksfreq, ksfreq2, ksfreq2) #, ksfreq2, ksfreq2, ksfreq2) # send the extra symbol for snr calculation self.ofdm_demod = digital_swig.ofdm_frame_sink(hdr_rotated_const, range(hdr_arity), data_rotated_const, range(data_arity), preambles, self._rcvd_pktq, self._out_pktq, self._occupied_tones, self._fft_length, options.proto, options.ack, phgain, frgain, self._id, self._batch_size, self._size, self._fec_n, self._fec_k) self.connect(self, self.ofdm_recv) manual = options.rx_manual # apurv++: manual testing flag if manual==0: self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0)) self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1)) self.connect((self.ofdm_recv, 2), (self.ofdm_demod, 2)) # apurv++, hestimates # elif manual==1: self.connect(gr.file_source(gr.sizeof_gr_complex*self._occupied_tones, "out-tx.dat"), (self.ofdm_demod, 0)) self.connect(gr.file_source(gr.sizeof_char, "out-timing.dat"), (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) ''' # sink some stuff # self.connect((self.ofdm_recv, 0), gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones)) # symbols self.connect((self.ofdm_recv, 1), gr.null_sink(gr.sizeof_char)) # timing self.connect((self.ofdm_recv, 2), gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones)) # hestimates ''' if options.verbose: self._print_verbage() self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback, self._fec_n, self._fec_k, self._bits_per_symbol, self._size) self._watcher_fwd = _queue_watcher_thread(self._out_pktq, fwd_callback) # apurv++
def __init__(self, rx_callback, options): gr.hier_block2.__init__(self, "receive_path", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(0, 0, 0)) options = copy.copy(options) # make a copy so we can destructively modify self._verbose = options.verbose self._log = options.log self._rx_callback = rx_callback # this callback is fired when there's a packet available 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 # 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)) preamble_sequence = known_symbols_4512_3[0:self._occupied_tones] training_sequence = ( known_symbols_4512_3[self._occupied_tones:self._occupied_tones*2], \ known_symbols_4512_3[self._occupied_tones*2:self._occupied_tones*3] ) for i in range(len(preamble_sequence)): if((zeros_on_left + i) & 1): preamble_sequence[i] = 0 # hard-coded known symbols preambles = (preamble_sequence,) 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, training_sequence, 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 = gtlib.ofdm_frame_sink(rotated_const, range(arity), self._rcvd_pktq, self._occupied_tones, phgain, frgain) """ # receiver self.ofdm_rx = ofdm.ofdm_demod(options, callback=self._rx_callback) """ # Carrier Sensing Blocks alpha = 0.001 thresh = 30 # in dB, will have to adjust self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) 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.probe) 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)) # Display some information about the setup if self._verbose: self._print_verbage() self._watcher = _queue_watcher_thread(self._rcvd_pktq, self._rx_callback)
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)
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)