コード例 #1
0
ファイル: iris_py.py プロジェクト: renew-wireless/RENEWLab
    def config_sdr_tdd(self,
                       is_bs=True,
                       tdd_sched="G",
                       prefix_len=0,
                       max_frames=1):
        '''Configure the TDD schedule and functionality when unchained. Set up the correlator.'''
        global corr_threshold, beacon
        coe = cfloat2uint32(np.conj(beacon), order='QI')
        self.tdd_sched = tdd_sched
        self.max_frames = int(max_frames)
        if bool(is_bs):
            conf_str = {
                "tdd_enabled": True,
                "frame_mode": "free_running",
                "symbol_size": self.n_samp,
                "max_frame": max_frames,
                "beacon_start": prefix_len,
                "beacon_stop": prefix_len + len(beacon),
                "frames": [self.tdd_sched]
            }
            self.sdr.writeSetting("TDD_CONFIG", json.dumps(conf_str))
            print("TDD schedule of BS node {}: {}".format(
                self.serial_id, tdd_sched))
        else:
            conf_str = {
                "tdd_enabled": True,
                "frame_mode": "triggered",
                "symbol_size": self.n_samp,
                "frames": [self.tdd_sched]
            }
            self.sdr.writeSetting("TDD_CONFIG", json.dumps(conf_str))

            #Correlator stuff:
            corr_conf = {
                "corr_enabled": True,
                "corr_threshold": corr_threshold
            }
            self.sdr.writeSetting("CORR_CONFIG", json.dumps(corr_conf))
            if coe is not None:
                self.sdr.writeRegisters("CORR_COE", 0, coe.tolist())
            else:
                print("No coe was passed into config_sdr_tdd() \n")

            # DEV: ueTrigTime = 153 (prefix_length=0), CBRS: ueTrigTime = 235 (prefix_length=82), tx_advance=prefix_length, corr delay is 17 cycles
            ueTrigTime = len(beacon) + 200
            sf_start = int(ueTrigTime // (self.n_samp))
            sp_start = int(ueTrigTime % (self.n_samp))
            print(
                "config_sdr_tdd: UE starting symbol and sample count (%d, %d)"
                % (sf_start, sp_start))
            # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."
            self.sdr.setHardwareTime(
                SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start,
                                       self.sample_rate), "TRIGGER")
            print("TDD schedule of UE node {}: {}".format(
                self.serial_id, tdd_sched))

        self.sdr.writeSetting("TX_SW_DELAY", str(30))
        self.sdr.writeSetting("TDD_MODE", "true")
コード例 #2
0
    def config_sdr_tdd(self, tdd_sched=None, is_bs=True):
        '''Configure the TDD schedule and functionality when unchained. Set up the correlator.'''
        global tx_advance, corr_threshold, beacon
        len_beacon_zpad = len(beacon) + self.n_zpad_samp
        coe = cfloat2uint32(np.conj(beacon), order='QI')
        if tdd_sched is not None:
            self.tdd_sched = tdd_sched
        else:
            self.tdd_sched = "G"
        print(tdd_sched)
        max_frames = self.max_frames
        if bool(is_bs):
            conf_str = {
                "tdd_enabled": True,
                "frame_mode": "free_running",
                "symbol_size": self.n_samp,
                "max_frame": max_frames,
                "frames": [self.tdd_sched]
            }
            self.sdr.writeSetting("TDD_CONFIG", json.dumps(conf_str))
        else:
            conf_str = {
                "tdd_enabled": True,
                "frame_mode": "triggered",
                "symbol_size": self.n_samp,
                "frames": [self.tdd_sched]
            }
            self.sdr.writeSetting("TDD_CONFIG", json.dumps(conf_str))

            #Correlator stuff:
            self.sdr.writeRegister("IRIS30", CORR_CONF, int(
                "00004001", 16))  # enable the correlator, with zeros as inputs
            for i in range(128):
                self.sdr.writeRegister("ARGCOE", i * 4, 0)
            time.sleep(0.1)
            self.sdr.writeRegister("IRIS30", CORR_RST, 0x1)  # reset corr
            self.sdr.writeRegister("IRIS30", CORR_RST, 0x0)  # unrst corr
            self.sdr.writeRegister("IRIS30", CORR_THRESHOLD,
                                   int(corr_threshold))
            if coe is not None:
                for i in range(128):
                    self.sdr.writeRegister("ARGCOE", i * 4, int(coe[i]))
            else:
                print("No coe was passed into config_sdr_tdd() \n")

            # DEV: ueTrigTime = 153 (prefix_length=0), CBRS: ueTrigTime = 235 (prefix_length=82), tx_advance=prefix_length, corr delay is 17 cycles
            ueTrigTime = 17 + tx_advance + len_beacon_zpad
            sf_start = int(ueTrigTime // (self.n_samp))
            sp_start = int(ueTrigTime % (self.n_samp))
            print(
                "config_sdr_tdd: UE starting symbol and sample count (%d, %d)"
                % (sf_start, sp_start))
            self.sdr.setHardwareTime(
                SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start,
                                       self.sample_rate), "TRIGGER"
            )  # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."

        self.sdr.writeSetting("TX_SW_DELAY", str(30))
        self.sdr.writeSetting("TDD_MODE", "true")
コード例 #3
0
ファイル: SISO.py プロジェクト: GavinMegson/MIMO-projects
    def rx(self, nsamps, rx_delay=57, delay=10000000, ts=None):
        '''Receive nsamps on rxsdr at timestamp ts, if provided, otherwise waits delay ns.'''
        if self.rxsdr is None:
            print('Error: No RX SDR provided!')
            return
        nsamps = int(nsamps)
        rx_delay_ns = SoapySDR.ticksToTimeNs(rx_delay, self.rate)
        hw_time = self.trig_sdr.getHardwareTime()
        ts = hw_time + delay + rx_delay_ns if ts is None else ts + rx_delay_ns
        sampsRecv = np.empty(nsamps, dtype=np.complex64)
        rxFlags = SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST
        # GM note: if nsamps is greater than some threshold, an error will print to terminal
        self.rxsdr.activateStream(self.rxStream, rxFlags, ts, nsamps)

        # GM uncommented these added first line
        print(
            "hwtime, delay, rx_delay_ns, ts \n [sdr.getHardwareTime() for sdr in self.sdrs]"
        )
        print(hw_time, delay, rx_delay_ns, ts)
        print([sdr.getHardwareTime() for sdr in self.sdrs])
        #time.sleep((ts - hw_time)/1e9)

        # GM documentation on device.readStream is not great,
        # can't find a function definition anywhere beyond an error code, not on github
        sr = self.rxsdr.readStream(self.rxStream, [sampsRecv],
                                   nsamps,
                                   timeoutUs=int(1e6))
        if sr.ret != nsamps:
            print("Bad read!!!")
            # GM
            print("nsamps, sr.ret, [sampsRecv]")
            print(nsamps)
            print(sr.ret)
        # GM print as list, so it all prints
        #print(sampsRecv.tolist()[:150])
        # GM attempting to invert signal back into integers
        # for reference (from below):
        # sig = np.exp(s_time_vals*1j*2*np.pi*s_freq).astype(np.complex64)*.5

        decoded = np.log(
            sampsRecv[:150] * 2) / 1j / 2 / np.pi / 500e3  # s_freq = 500e3
        #		decoded = np.log((sampsRecv*2).astype(float)) /1j /2 /np.pi /500e3 # s_freq = 500e3

        ints = np.arange(150)
        ints = ints - 100  #samp buff

        #GM estimating CSI
        csi = decoded / ints
        #		csi = sampsRecv[:150] / ints

        # GM print expected, raw data from buffer, inverted function
        for i in range(150):
            print("expected: ", ints[i], "\nraw: ", sampsRecv[i], "\nval: ",
                  decoded[i], "\nCSI: ", csi[i])

        return sampsRecv
コード例 #4
0
def Process_RxActivate_WriteFlagToRxStream_UseHasTime(self, rx_delay=57):
    rx_delay_ns = SoapySDR.ticksToTimeNs(rx_delay,
                                         self.rate) if rx_delay != 0 else 0
    ts = self.ts + rx_delay_ns  # rx is a bit after tx
    flags = SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST
    # activate all receive stream
    for r, rxStream in enumerate(self.rxStreams):
        serial_ant = self.rx_serials_ant[r]
        serial, ant = Format_SplitSerialAnt(serial_ant)
        sdr = self.sdrs[serial]
        sdr.activateStream(rxStream, flags, ts, len(self.sampsRecv[r][0]))
コード例 #5
0
	def rx(self, nsamps, rx_delay=57, delay=10000000, ts=None):
		'''Receive nsamps on rxsdr at timestamp ts, if provided, otherwise waits delay ns.'''
		if self.rxsdr is None:
			print('Error: No RX SDR provided!')
			return
		nsamps = int(nsamps)
		rx_delay_ns = SoapySDR.ticksToTimeNs(rx_delay,self.rate)
		hw_time = self.trig_sdr.getHardwareTime()
		ts = hw_time + delay + rx_delay_ns if ts is None else ts + rx_delay_ns
		sampsRecv = np.empty(nsamps, dtype=np.complex64)
		rxFlags = SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST
		self.rxsdr.activateStream(self.rxStream, rxFlags, ts, nsamps)
		
		#print(hw_time,delay,rx_delay_ns,ts)
		#print([sdr.getHardwareTime() for sdr in self.sdrs])
		time.sleep((ts - hw_time)/1e9)		
		
		sr = self.rxsdr.readStream(self.rxStream, [sampsRecv], nsamps, timeoutUs=int(1e6))
		if sr.ret != nsamps:
			print("Bad read!!!")
		return sampsRecv
コード例 #6
0
def setupUE(args, serial, rate, freq, txgain, rxgain, numSamps, numSyms, pilotSymbol, txSymbol, txSymNum, threshold, tx_advance, prefix_length, postfix_length, cp, calibrate, both_channels, wait_trigger, auto_tx_gain):
    global msdr, txStreamM, rxStreamM
    msdr = SoapySDR.Device(dict(serial=serial))

    #some default sample rates
    for sdr in [msdr]:
        info = sdr.getHardwareInfo();
        print("%s settings" % info["frontend"])
        for ch in [0,1]:
            sdr.setSampleRate(SOAPY_SDR_TX, ch, rate)
            sdr.setSampleRate(SOAPY_SDR_RX, ch, rate)
            #sdr.setFrequency(SOAPY_SDR_TX, ch, freq)
            #sdr.setFrequency(SOAPY_SDR_RX, ch, freq)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'RF', freq-.75*rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'RF', freq-.75*rate)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'BB', .75*rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'BB', .75*rate)
            if ("CBRS" in info["frontend"]):
                sdr.setGain(SOAPY_SDR_TX, ch, 'ATTN', 0) #[-18,0] by 3
                sdr.setGain(SOAPY_SDR_TX, ch, 'PA1', 15) #[0|15]
                sdr.setGain(SOAPY_SDR_TX, ch, 'PA2', 0) #[0|15]
                sdr.setGain(SOAPY_SDR_TX, ch, 'PA3', 30) #[0|30]
            if ("UHF" in info["frontend"]):
                sdr.setGain(SOAPY_SDR_TX, ch, 'ATTN', 0) #[-18,0] by 3
            sdr.setGain(SOAPY_SDR_TX, ch, 'IAMP', 0) #[0,12]
            sdr.setGain(SOAPY_SDR_TX, ch, 'PAD', txgain) #[0,52]

            if ("CBRS" in info["frontend"]):
                sdr.setGain(SOAPY_SDR_RX, ch, 'ATTN', 0) #[-18,0]
                sdr.setGain(SOAPY_SDR_RX, ch, 'LNA1', 30) #[0,33]
                sdr.setGain(SOAPY_SDR_RX, ch, 'LNA2', 17) #[0,17]
            if ("UHF" in info["frontend"]):
                sdr.setGain(SOAPY_SDR_RX, ch, 'ATTN1', -6) #[-18,0]
                sdr.setGain(SOAPY_SDR_RX, ch, 'ATTN2', -12) #[-18,0]
            sdr.setGain(SOAPY_SDR_RX, ch, 'LNA', rxgain) #[0,30]
            sdr.setGain(SOAPY_SDR_RX, ch, 'TIA', 0) #[0,12]
            sdr.setGain(SOAPY_SDR_RX, ch, 'PGA', 0) #[-12,19]
            sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX")
            #sdr.setBandwidth(SOAPY_SDR_TX, ch, 30e6)
            #sdr.setBandwidth(SOAPY_SDR_RX, ch, 30e6)
            sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True)
        if calibrate:
            for ch in [0,1]:
                sdr.writeSetting(SOAPY_SDR_RX, ch, "CALIBRATE", 'SKLK')
                sdr.writeSetting(SOAPY_SDR_TX, ch, "CALIBRATE", 'SKLK')
        #if not both_channels:
        #    sdr.writeSetting("SPI_TDD_MODE", "SISO")
        #    sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false')
        #    sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false')
        #else:
        #    sdr.writeSetting("SPI_TDD_MODE", "MIMO")

        sdr.writeRegister("IRIS30", RF_RST_REG, (1<<29) | 0x1)
        sdr.writeRegister("IRIS30", RF_RST_REG, (1<<29))
        sdr.writeRegister("IRIS30", RF_RST_REG, 0)
    msdr.writeRegister("ARGCOR", CORR_RST, 0x1) # reset corr
    msdr.writeRegister("IRIS30", TX_GAIN_CTRL, 0) 
    minfo = msdr.getHardwareInfo()
    #packet size
    symSamp = numSamps + prefix_length + postfix_length
    print("symSamp = %d"%symSamp)
    print("txSymNum = %d"%txSymNum)

    upsample = 1
    # preambles to be sent from BS and correlated against in UE
    preambles_bs, highest_peak_to_second_ratio_bs = Preambles.getPreambles('gold_ifft', 128, 0, upsample=1) #the base station may upsample, but the mobiles won't
    preambles = preambles_bs[:,::upsample] #the correlators can run at lower rates, so we only need the downsampled signal.
    
    beacon = preambles[0,:]*.25
    coe = cfloat2uint32(np.conj(beacon), order='QI') # FPGA correlator takes coefficients in QI order
    ltsSym = lts.genLTS(upsample=upsample,cp=1 if cp else 0)  
    pad1 = np.array([0]*(prefix_length), np.complex64) # to comprensate for front-end group delay
    pad2 = np.array([0]*(postfix_length), np.complex64) # to comprensate for rf path delay
    wb_pilot = np.tile(ltsSym,numSamps/len(ltsSym)).astype(np.complex64)*.5
    wbz = np.array([0]*(symSamp), np.complex64)
    wb_pilot1 = np.concatenate([pad1,wb_pilot,pad2]) 
    wb_pilot2 = wb_pilot1 if both_channels else wbz
    
    Ts = 1/rate
    s_freq = 1e6
    s_time_vals = np.array(np.arange(0,symSamp)).transpose()*Ts
    nb_data = np.exp(s_time_vals*1j*2*np.pi*s_freq).astype(np.complex64)*.25

    rand_data = [1,0,1,1,0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, \
				0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, \
				0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0 ,1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, \
				0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1 ,0, 1, 0, 0, \
				0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, \
				0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, \
				0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1]
    #data_16qam = genDATA(np.random.randint(2, size=64*4),0)
    data_16qam = ofdm.genDATAQPSK(rand_data,0)
    if not cp: data_16qam[16:]
    wb_data = np.tile(data_16qam,numSamps/len(data_16qam)).astype(np.complex64)*.5
    wb_data = np.concatenate([pad1,wb_data,pad2])

    if txSymNum > 0:
        txStreamM = msdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CF32, [0, 1])  
        rxStreamM = msdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1]) 
 
    msdr.writeRegister("IRIS30", CORR_CONF, int("00004001", 16)) # enable the correlator, with zeros as inputs 
    for i in range(128):
        msdr.writeRegister("ARGCOE", i*4, 0)
    time.sleep(0.1)
    msdr.writeRegister("ARGCOR", CORR_THRESHOLD, int(threshold))
    msdr.writeRegister("ARGCOR", CORR_RST, 0x1) # reset corr
    msdr.writeRegister("ARGCOR", CORR_RST, 0x0) # unrst corr 
    for i in range(128):
        msdr.writeRegister( "ARGCOE", i*4, int(coe[i]))
    if auto_tx_gain:
        max_gain = int(txgain)
        min_gain = max(0, max_gain-15)
        gain_reg = 0xF000 | (max_gain & 0x3F) << 6 | (min_gain & 0x3F)
        print("gain reg 0x%X" % gain_reg)
        msdr.writeRegister("IRIS30", TX_GAIN_CTRL, gain_reg) # [15] en, [14] mode, [13:12] step, [11:6] stop, [5:0] start 
    
    if both_channels:
        pilotSymNum = 2
        msched = ''.join("G"*(pilotSymbol-2))+"PP"
    else:
        pilotSymNum = 1
        msched = ''.join("G"*(pilotSymbol-2))+"P"
    if txSymNum > 0:
        msched += ''.join("G"*(txSymbol-pilotSymbol-pilotSymNum))+''.join("T"*txSymNum)+''.join("G"*(numSyms-txSymNum-txSymbol))
        msched = "GR" + msched
    else:
        msched += ''.join("G"*(numSyms-pilotSymbol-pilotSymNum))
        msched = "GG" + msched
    print("Client schedule %s " % msched)
    mconf = {"tdd_enabled": True, "trigger_out": True, "wait_trigger": True, "dual_pilot": both_channels, "symbol_size" : symSamp, "frames": [msched]}
    msdr.writeSetting("TDD_CONFIG", json.dumps(mconf))

    # DEV: ueTrigTime = 153 (prefix_length=0), CBRS: ueTrigTime = 235 (prefix_length=82), tx_advance=prefix_length
    ueTrigTime = prefix_length + len(beacon) + postfix_length + 17 + tx_advance 
    sf_start = ueTrigTime/symSamp
    sp_start = ueTrigTime%symSamp
    print("UE starting symbol and sample count (%d, %d)" % (sf_start, sp_start))
    msdr.setHardwareTime(SoapySDR.ticksToTimeNs((sf_start<<16) | sp_start, rate),"TRIGGER") # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."

    for sdr in [msdr]:
        sdr.writeSetting("TX_SW_DELAY", str(30))
    msdr.writeSetting("TDD_MODE", "true")

    replay_addr = 0
    if both_channels:
        msdr.writeRegisters("TX_RAM_A", replay_addr+(pilotSymbol%2)*2048, cfloat2uint32(wb_pilot1, order='QI').tolist())
        msdr.writeRegisters("TX_RAM_B", replay_addr+((pilotSymbol+1)%2)*2048, cfloat2uint32(wb_pilot1, order='QI').tolist())
    else:
        msdr.writeRegisters("TX_RAM_A", replay_addr, cfloat2uint32(wb_pilot1, order='QI').tolist())
        msdr.writeRegisters("TX_RAM_B", replay_addr, cfloat2uint32(wb_pilot2, order='QI').tolist())

    #pdb.set_trace()
    msdr.writeRegister("IRIS30", CORR_CONF, int("00004011", 16)) # enable the correlator, with inputs from adc
    signal.signal(signal.SIGINT, partial(signal_handler, rate, numSyms, txSymNum))
    if txSymNum>0:
        txth = threading.Thread(target=tx_thread, args=(msdr, rate, txStreamM, rxStreamM, wb_data, symSamp, numSyms, txSymNum, txSymbol))
        txth.start()
    #signal.pause()
    num_trig = 0
    while True:
        time.sleep(0.25)
        t = SoapySDR.timeNsToTicks(msdr.getHardwareTime(""),rate) >> 32 #trigger count is top 32 bits.
        print("%d new triggers, %d total" % (t - num_trig, t))
        num_trig = t
コード例 #7
0
def siso_sounder(serial1, serial2, rate, freq, txgain, rxgain, bw, numSamps,
                 numSyms, txSymNum, threshold, tx_advance, prefix_length,
                 postfix_length, both_channels, wait_trigger, calibrate,
                 record, use_trig, auto_tx_gain):
    global bsdr, msdr, txStreamM, rxStreamB
    print("setting %s as eNB and %s as UE" % (serial1, serial2))
    bsdr = SoapySDR.Device(dict(serial=serial1))
    msdr = SoapySDR.Device(dict(serial=serial2))

    #some default sample rates
    for i, sdr in enumerate([bsdr, msdr]):
        info = sdr.getHardwareInfo()
        print("%s settings on device %d" % (info["frontend"], i))
        for ch in [0, 1]:
            sdr.setSampleRate(SOAPY_SDR_TX, ch, rate)
            sdr.setSampleRate(SOAPY_SDR_RX, ch, rate)
            #sdr.setFrequency(SOAPY_SDR_TX, ch, freq)
            #sdr.setFrequency(SOAPY_SDR_RX, ch, freq)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'RF', freq - .75 * rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'RF', freq - .75 * rate)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'BB', .75 * rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'BB', .75 * rate)
            if ("CBRS" in info["frontend"]):
                sdr.setGain(SOAPY_SDR_TX, ch, 'ATTN', 0)  #[-18,0] by 3
                sdr.setGain(SOAPY_SDR_TX, ch, 'PA1', 15)  #[0,15]
                sdr.setGain(SOAPY_SDR_TX, ch, 'PA2', 0)  #[0,15]
                sdr.setGain(SOAPY_SDR_TX, ch, 'PA3', 30)  #[0,30]
            sdr.setGain(SOAPY_SDR_TX, ch, 'IAMP', 12)  #[0,12]
            sdr.setGain(SOAPY_SDR_TX, ch, 'PAD', txgain)  #[-52,0]

            if ("CBRS" in info["frontend"]):
                sdr.setGain(SOAPY_SDR_RX, ch, 'ATTN', 0)  #[-18,0]
                sdr.setGain(SOAPY_SDR_RX, ch, 'LNA1', 30)  #[0,33]
                sdr.setGain(SOAPY_SDR_RX, ch, 'LNA2', 17)  #[0,17]
            sdr.setGain(SOAPY_SDR_RX, ch, 'LNA', rxgain)  #[0,30]
            sdr.setGain(SOAPY_SDR_RX, ch, 'TIA', 0)  #[0,12]
            sdr.setGain(SOAPY_SDR_RX, ch, 'PGA', 0)  #[-12,19]
            sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX")
            #sdr.setBandwidth(SOAPY_SDR_RX, ch, bw)
            #sdr.setBandwidth(SOAPY_SDR_TX, ch, bw)
            sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True)
        for ch in [0, 1]:
            if calibrate:
                sdr.writeSetting(SOAPY_SDR_RX, ch, "CALIBRATE", 'SKLK')
                sdr.writeSetting(SOAPY_SDR_TX, ch, "CALIBRATE", '')

        sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1)
        sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29))
        sdr.writeRegister("IRIS30", RF_RST_REG, 0)
        if not both_channels:
            sdr.writeSetting("SPI_TDD_MODE", "SISO")
            sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false')
            sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false')
        else:
            sdr.writeSetting("SPI_TDD_MODE", "MIMO")
    #pdb.set_trace()
    msdr.writeRegister("IRIS30", TX_GAIN_CTRL, 0)
    if use_trig:
        bsdr.writeSetting("SYNC_DELAYS", "")
        #bsdr.writeSetting("FPGA_DIQ_MODE", "PATTERN")
    else:
        msdr.writeRegister("ARGCOR", CORR_RST, 0x1)  # reset corr
    #packet size
    symSamp = numSamps + prefix_length + postfix_length
    print("numSamps = %d" % symSamp)
    print("txSymNum = %d" % txSymNum)
    upsample = 1
    Ts = 1 / rate
    s_freq = 1e6
    s_time_vals = np.array(np.arange(0, numSamps)).transpose() * Ts
    nb_data = np.exp(s_time_vals * 1j * 2 * np.pi * s_freq).astype(
        np.complex64) * .25

    #create streams
    rxStreamM = msdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1])
    txStreamM = msdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CF32, [0, 1])
    if record:
        rxStreamB = bsdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1])

    # preambles to be sent from BS and correlated against in UE
    preambles_bs, highest_peak_to_second_ratio_bs = Preambles.getPreambles(
        'gold_ifft', 128, 0,
        upsample=1)  #the base station may upsample, but the mobiles won't
    preambles = preambles_bs[:, ::
                             upsample]  #the correlators can run at lower rates, so we only need the downsampled signal.

    beacon = preambles[0, :] * .25
    coe = cfloat2uint32(
        np.conj(beacon),
        order='QI')  # FPGA correlator takes coefficients in QI order
    ltsSym = lts.genLTS(upsample=1, cp=0)
    pad1 = np.array([0] * (prefix_length),
                    np.complex64)  # to comprensate for front-end group delay
    pad2 = np.array([0] * (postfix_length),
                    np.complex64)  # to comprensate for rf path delay
    wb_pilot = np.tile(ltsSym, numSamps / len(ltsSym)).astype(
        np.complex64) * .5
    wbz = np.array([0] * (symSamp), np.complex64)
    wb_pilot1 = np.concatenate([pad1, wb_pilot, pad2])
    wb_pilot2 = wbz  #wb_pilot1 if both_channels else wbz
    bcnz = np.array([0] * (symSamp - prefix_length - len(beacon)),
                    np.complex64)
    beacon1 = np.concatenate([pad1, beacon, bcnz])
    beacon2 = wbz  #beacon1 if both_channels else wbz

    bsched = "PGR" + ''.join("G" * (numSyms - txSymNum - 4)) + ''.join(
        "R" * txSymNum) + "G"
    msched = "GGP" + ''.join("G" * (numSyms - txSymNum - 4)) + ''.join(
        "T" * txSymNum) + "G"
    if both_channels:
        bsched = "PGRR" + ''.join("G" * (numSyms - txSymNum - 5)) + ''.join(
            "R" * txSymNum) + "G"
        msched = "GGPP" + ''.join("G" * (numSyms - txSymNum - 5)) + ''.join(
            "T" * txSymNum) + "G"
    print("Node 1 schedule %s " % bsched)
    print("Node 2 schedule %s " % msched)
    bconf = {
        "tdd_enabled": True,
        "trigger_out": False,
        "symbol_size": symSamp,
        "frames": [bsched]
    }
    mconf = {
        "tdd_enabled": True,
        "trigger_out": not use_trig,
        "wait_trigger": wait_trigger,
        "dual_pilot": both_channels,
        "symbol_size": symSamp,
        "frames": [msched]
    }
    #mconf = {"tdd_enabled": True, "trigger_out": not use_trig, "wait_trigger": True, "symbol_size" : symSamp, "frames": [msched]}
    bsdr.writeSetting("TDD_CONFIG", json.dumps(bconf))
    msdr.writeSetting("TDD_CONFIG", json.dumps(mconf))

    for sdr in [bsdr, msdr]:
        sdr.writeSetting("TX_SW_DELAY", str(30))

    if not use_trig:
        msdr.writeRegister("IRIS30", CORR_CONF, int(
            "00004001", 16))  # enable the correlator, with zeros as inputs
        for i in range(128):
            msdr.writeRegister("ARGCOE", i * 4, 0)
        time.sleep(0.1)
        msdr.writeRegister("ARGCOR", CORR_THRESHOLD, int(threshold))
        msdr.writeRegister("ARGCOR", CORR_RST, 0x1)  # reset corr
        msdr.writeRegister("ARGCOR", CORR_RST, 0x0)  # unrst corr
        for i in range(128):
            msdr.writeRegister("ARGCOE", i * 4, int(coe[i]))
        if auto_tx_gain:
            max_gain = int(txgain)
            min_gain = max(0, max_gain - 15)
            gain_reg = 0xF000 | (max_gain & 0x3F) << 6 | (min_gain & 0x3F)
            print("gain reg 0x%X" % gain_reg)
            msdr.writeRegister(
                "IRIS30", TX_GAIN_CTRL, gain_reg
            )  # [15] en, [14] mode, [13:12] step, [11:6] stop, [5:0] start

        # DEV: ueTrigTime = 153 (prefix_length=0), CBRS: ueTrigTime = 235 (prefix_length=82), tx_advance=prefix_length, corr delay is 17 cycles
        ueTrigTime = prefix_length + len(
            beacon) + postfix_length + 17 + tx_advance
        sf_start = ueTrigTime / symSamp
        sp_start = ueTrigTime % symSamp
        print("UE starting symbol and sample count (%d, %d)" %
              (sf_start, sp_start))
        msdr.setHardwareTime(
            SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start,
                                   rate), "TRIGGER"
        )  # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."

    msdr.writeSetting("TDD_MODE", "true")
    bsdr.writeSetting("TDD_MODE", "true")

    replay_addr = 0
    bsdr.writeRegisters("TX_RAM_A", replay_addr,
                        cfloat2uint32(beacon1, order='IQ').tolist())
    bsdr.writeRegisters("TX_RAM_B", replay_addr,
                        cfloat2uint32(beacon2, order='IQ').tolist())

    msdr.writeRegisters("TX_RAM_A", replay_addr,
                        cfloat2uint32(wb_pilot1, order='IQ').tolist())
    msdr.writeRegisters("TX_RAM_B", replay_addr,
                        cfloat2uint32(wbz, order='IQ').tolist())
    if both_channels:
        msdr.writeRegisters("TX_RAM_A", replay_addr + 2048,
                            cfloat2uint32(wbz, order='IQ').tolist())
        msdr.writeRegisters("TX_RAM_B", replay_addr + 2048,
                            cfloat2uint32(wb_pilot2, order='IQ').tolist())

    if not use_trig:
        msdr.writeRegister("IRIS30", CORR_CONF, int(
            "00004011", 16))  # enable the correlator, with inputs from adc
    signal.signal(signal.SIGINT, partial(signal_handler, rate, numSyms))
    bsdr.writeSetting("TRIGGER_GEN", "")
    txth = threading.Thread(target=tx_thread,
                            args=(msdr, rate, txStreamM, rxStreamM, nb_data,
                                  symSamp, numSyms, txSymNum,
                                  numSyms - txSymNum - 1))
    txth.start()
    if record:
        rxth = threading.Thread(target=rx_thread,
                                args=(bsdr, rxStreamB, symSamp, txSymNum,
                                      both_channels))
        rxth.start()
    signal.pause()
コード例 #8
0
ファイル: SOUNDER_TXRX.py プロジェクト: Ankit298/RENEWLab
def siso_sounder(hub, serial1, serial2, rate, freq, txgain, rxgain, numSamps, numSyms, txSymNum, threshold, tx_advance,
                 prefix_length, postfix_length, both_channels, wait_trigger, calibrate, record, use_trig, tx_power_loop, agc_en):
    global bsdr, msdr, txStreamM, rxStreamB

    print("setting %s as eNB and %s as UE" % (serial1, serial2))
    bsdr = SoapySDR.Device(dict(serial=serial1))
    msdr = SoapySDR.Device(dict(serial=serial2))
    if hub != "":
        trig_dev = SoapySDR.Device(dict(serial=hub, driver="remote"))
    else:
        trig_dev = bsdr

    # Some default sample rates
    for i, sdr in enumerate([bsdr, msdr]):
        info = sdr.getHardwareInfo()
        print("%s settings on device %d" % (info["frontend"], i))
        for ch in [0, 1]:
            sdr.setBandwidth(SOAPY_SDR_TX, ch, 2.5*rate)
            sdr.setBandwidth(SOAPY_SDR_RX, ch, 2.5*rate)
            sdr.setSampleRate(SOAPY_SDR_TX, ch, rate)
            sdr.setSampleRate(SOAPY_SDR_RX, ch, rate)
            #sdr.setFrequency(SOAPY_SDR_TX, ch, freq)
            #sdr.setFrequency(SOAPY_SDR_RX, ch, freq)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'RF', freq-.75*rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'RF', freq-.75*rate)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'BB', .75*rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'BB', .75*rate)
            sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX")
            sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True)

            if "CBRS" in info["frontend"]:
                # Set gains to high val (initially)
                if agc_en: rxgain = 100
                sdr.setGain(SOAPY_SDR_TX, ch, txgain)
                sdr.setGain(SOAPY_SDR_RX, ch, rxgain)
            else:
                # No CBRS board gains, only changing LMS7 gains
                # AGC only supported for CBRS boards
                agc_en = False
                sdr.setGain(SOAPY_SDR_TX, ch, "PAD", txgain)    # [0:1:42]
                sdr.setGain(SOAPY_SDR_TX, ch, "IAMP", 0)        # [-12:1:3]
                sdr.setGain(SOAPY_SDR_RX, ch, "LNA", rxgain)    # [0:1:30]
                sdr.setGain(SOAPY_SDR_RX, ch, "TIA", 0)         # [0, 3, 9, 12]
                sdr.setGain(SOAPY_SDR_RX, ch, "PGA", -10)       # [-12:1:19]

            # Read initial gain settings
            readLNA = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA')
            readTIA = sdr.getGain(SOAPY_SDR_RX, 0, 'TIA')
            readPGA = sdr.getGain(SOAPY_SDR_RX, 0, 'PGA')
            print("INITIAL GAIN - LNA: {}, \t TIA:{}, \t PGA:{}".format(readLNA, readTIA, readPGA))

        for ch in [0, 1]:
            if calibrate:
                sdr.writeSetting(SOAPY_SDR_RX, ch, "CALIBRATE", 'SKLK')

        sdr.writeSetting("RESET_DATA_LOGIC", "")

    # pdb.set_trace()
    if use_trig:
        trig_dev.writeSetting("SYNC_DELAYS", "")

    # Packet size
    symSamp = numSamps + prefix_length + postfix_length
    print("numSamps = %d" % symSamp)
    print("txSymNum = %d" % txSymNum)
    upsample = 1
    Ts = 1/rate
    s_freq = 1e6
    s_time_vals = np.array(np.arange(0, numSamps)).transpose()*Ts
    nb_data = np.exp(s_time_vals*1j*2*np.pi*s_freq).astype(np.complex64)*.25

    # Create streams
    rxStreamM = msdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1])  
    txStreamM = msdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CF32, [0, 1])  
    if record:
        rxStreamB = bsdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1])

    tpc_conf = {"tpc_enabled" : False}
    msdr.writeSetting("TPC_CONFIG", json.dumps(tpc_conf))
    agc_conf = {"agc_enabled" : agc_en}
    msdr.writeSetting("AGC_CONFIG", json.dumps(agc_conf))

    # preambles to be sent from BS and correlated against in UE
    # the base station may upsample, but the mobiles won't
    preambles_bs = generate_training_seq(preamble_type='gold_ifft', seq_length=128, cp=0, upsample=1)
    # the correlators can run at lower rates, so we only need the downsampled signal.
    preambles = preambles_bs[:, ::upsample]

    ampl = 0.5
    beacon = preambles[0, :]
    coe = cfloat2uint32(np.conj(beacon), order='QI')     # FPGA correlator takes coefficients in QI order
    ltsSym, lts_f = generate_training_seq(preamble_type='lts', cp=32, upsample=1)
    # ltsSym = lts.genLTS(upsample=1, cp=0)
    pad1 = np.array([0]*(prefix_length), np.complex64)   # to comprensate for front-end group delay
    pad2 = np.array([0]*(postfix_length), np.complex64)  # to comprensate for rf path delay
    wb_pilot = np.tile(ltsSym, numSamps//len(ltsSym)).astype(np.complex64)*ampl
    wbz = np.array([0]*(symSamp), np.complex64)
    wb_pilot1 = np.concatenate([pad1, wb_pilot, pad2])
    wb_pilot2 = wbz  # wb_pilot1 if both_channels else wbz
    bcnz = np.array([0]*(symSamp-prefix_length-len(beacon)), np.complex64)

    if both_channels:
        beacon_weights = hadamard(2)
    else:
        beacon_weights = np.eye(2, dtype=np.uint32)
    beacon_weights = beacon_weights.astype(np.uint32)

    bsched = "BGR"+''.join("G"*(numSyms-txSymNum-4))+''.join("R"*txSymNum)+"G"
    msched = "GGP"+''.join("G"*(numSyms-txSymNum-4))+''.join("T"*txSymNum)+"G"
    if both_channels:
        bsched = "BGRR"+''.join("G"*(numSyms-txSymNum-5))+''.join("R"*txSymNum)+"G"
        msched = "GGPP"+''.join("G"*(numSyms-txSymNum-5))+''.join("T"*txSymNum)+"G"

    print("Iris 1 schedule %s " % bsched) 
    print("Iris 2 schedule %s " % msched)

    bconf = {"tdd_enabled": True,
             "frame_mode": "free_running",
             "symbol_size": symSamp,
             "frames": [bsched],
             "beacon_start" : prefix_length,
             "beacon_stop" : prefix_length+len(beacon),
             "max_frame" : 0}
    mconf = {"tdd_enabled": True,
             "frame_mode": "free_running" if use_trig else "triggered" if wait_trigger else "continuous_resync",
             "dual_pilot": both_channels,
             "symbol_size" : symSamp,
             "frames": [msched],
             "max_frame" : 0}

    bsdr.writeSetting("TDD_CONFIG", json.dumps(bconf))
    msdr.writeSetting("TDD_CONFIG", json.dumps(mconf))

    bsdr.writeRegisters("BEACON_RAM", 0, cfloat2uint32(beacon, order='QI').tolist())
    bsdr.writeRegisters("BEACON_RAM_WGT_A", 0, beacon_weights[0].tolist())
    bsdr.writeRegisters("BEACON_RAM_WGT_B", 0, beacon_weights[1].tolist())
    numAnt = 2 if both_channels else 1
    bsdr.writeSetting("BEACON_START", str(numAnt))

    for sdr in [bsdr, msdr]:
        sdr.writeSetting("TX_SW_DELAY", str(30))
        sdr.writeSetting("TDD_MODE", "true")

    if not use_trig:
        corr_conf = {"corr_enabled" : True, "corr_threshold" : threshold}
        msdr.writeSetting("CORR_CONFIG", json.dumps(corr_conf))
        msdr.writeRegisters("CORR_COE", 0, coe.tolist())

        # DEV: ueTrigTime = 153 (prefix_length=0), CBRS: ueTrigTime = 235 (prefix_length=82), tx_advance=prefix_length,
        # corr delay is 17 cycles
        ueTrigTime = len(beacon) + 200 # prefix_length + len(beacon) + postfix_length + 17 + tx_advance + 150
        sf_start = ueTrigTime // symSamp
        sp_start = ueTrigTime % symSamp
        print("UE starting symbol and sample count (%d, %d)" % (sf_start, sp_start))
        # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."
        msdr.setHardwareTime(SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start, rate), "TRIGGER")

    if tx_power_loop:
        tcp_conf = {"tpc_enabled" : True,
                    "max_gain" : int(tx_gain),
                    "min_gain" : max(0, max_gain-12)}
        msdr.writeSetting("TPC_CONFIG", json.dumps(tpc_conf))

    msdr.writeRegisters("TX_RAM_A", 0, cfloat2uint32(wb_pilot1, order='QI').tolist())
    if both_channels:
        msdr.writeRegisters("TX_RAM_B", 0, cfloat2uint32(wb_pilot2, order='QI').tolist())

    if not use_trig:
        msdr.writeSetting("CORR_START", "A")

    signal.signal(signal.SIGINT, partial(signal_handler, rate, numSyms, use_trig))
    trig_dev.writeSetting("TRIGGER_GEN", "")
    txth = threading.Thread(target=tx_thread, args=(msdr, rate, txStreamM, rxStreamM, nb_data, symSamp, numSyms, txSymNum, numSyms-txSymNum-1))
    txth.start()
    if record:
        rxth = threading.Thread(target=rx_thread, args=(bsdr, rxStreamB, symSamp, txSymNum, both_channels))
        rxth.start()
    num_trig = 0
    while True:
        time.sleep(1)
        t = SoapySDR.timeNsToTicks(msdr.getHardwareTime(""),rate) >> 32 #trigger count is top 32 bits.
        print("%d new triggers, %d total" % (t - num_trig, t))
        num_trig = t
コード例 #9
0
def init(hub, bnodes, cnodes, ref_ant, ampl, rate, freq, txgain, rxgain, cp, plotter, numSamps, prefix_length, postfix_length, tx_advance, mod_order, threshold, use_trig):
    if hub != "": hub_dev = SoapySDR.Device(dict(driver="remote", serial = hub)) # device that triggers bnodes and ref_node
    bsdrs = [SoapySDR.Device(dict(driver="iris", serial = serial)) for serial in bnodes] # base station sdrs
    csdrs = [SoapySDR.Device(dict(driver="iris", serial = serial)) for serial in cnodes] # client sdrs
    # assume trig_sdr is part of the master nodes
    trig_dev = None
    if hub != "":
        trig_dev = hub_dev
    else:
        trig_dev = bsdrs[0]

    #set params on both channels
    for sdr in bsdrs+csdrs:
        info = sdr.getHardwareInfo()
        print("%s settings on device" % (info["frontend"]))
        for ch in [0, 1]:
            sdr.setBandwidth(SOAPY_SDR_TX, ch, 2.5*rate)
            sdr.setBandwidth(SOAPY_SDR_RX, ch, 2.5*rate)
            sdr.setSampleRate(SOAPY_SDR_TX, ch, rate)
            sdr.setSampleRate(SOAPY_SDR_RX, ch, rate)
            # sdr.setFrequency(SOAPY_SDR_TX, ch, freq)
            # sdr.setFrequency(SOAPY_SDR_RX, ch, freq)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'RF', freq-.75*rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'RF', freq-.75*rate)
            sdr.setFrequency(SOAPY_SDR_TX, ch, 'BB', .75*rate)
            sdr.setFrequency(SOAPY_SDR_RX, ch, 'BB', .75*rate)
            sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX")
            sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True)

            sdr.setGain(SOAPY_SDR_TX, ch, 'PAD', txgain)
            sdr.setGain(SOAPY_SDR_RX, ch, 'LNA', rxgain)

            if "CBRS" in info["frontend"]:
                sdr.setGain(SOAPY_SDR_TX, ch, 'ATTN', -6)
                sdr.setGain(SOAPY_SDR_RX, ch, 'LNA2', 14)
                if freq < 3e9:
                    sdr.setGain(SOAPY_SDR_RX, ch, 'ATTN', -12)
                else:
                    sdr.setGain(SOAPY_SDR_RX, ch, 'ATTN', 0)

            # Read initial gain settings
            readLNA = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA')
            readTIA = sdr.getGain(SOAPY_SDR_RX, 0, 'TIA')
            readPGA = sdr.getGain(SOAPY_SDR_RX, 0, 'PGA')
            print("INITIAL GAIN - LNA: {}, \t TIA:{}, \t PGA:{}".format(readLNA, readTIA, readPGA))

        sdr.writeSetting("RESET_DATA_LOGIC", "")
        sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false')
        sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false')

    trig_dev.writeSetting("SYNC_DELAYS", "")

    sym_samps = numSamps + prefix_length + postfix_length
    print("numSamps = %d"%sym_samps)
    M = len(bsdrs)
    K = len(csdrs)
    N = 64
    D = 1 # number of downlink symbols

    pad1 = np.array([0]*(prefix_length), np.complex64) # to comprensate for front-end group delay
    pad2 = np.array([0]*(postfix_length), np.complex64) # to comprensate for rf path delay
    wbz = np.array([0]*(sym_samps), np.complex64)
    # OFDM object
    ofdm_obj = ofdmTxRx()


    #### Generate Pilot
    cp_len = 32 if cp else 0
    ofdm_len = 2*N + cp_len
    lts_rep = numSamps//(ofdm_len)
    zeros = np.array([0]*(numSamps-ofdm_len))
    lts_sym, lts_f = generate_training_seq(preamble_type='lts', cp=cp_len, upsample=1)
    pilot = np.concatenate((lts_sym, zeros))
    wb_pilot = ampl * pilot
    wb_pilot1 = np.concatenate([pad1, wb_pilot, pad2])
    lts_t = lts_sym[-64:]
    lts_t_cp = np.concatenate((lts_t[len(lts_t) - 16:], lts_t))

    #### Generate Beacon and hadamard weights
    upsample = 1
    preambles_bs = generate_training_seq(preamble_type='gold_ifft', seq_length=128, cp=0, upsample=upsample)
    preambles = preambles_bs[:,::upsample]
    beacon = preambles[0,:]
    coe = cfloat2uint32(np.conj(beacon), order='QI')
    bcnz = np.array([0]*(sym_samps-prefix_length-len(beacon)), np.complex64)  
    beacon1 = np.concatenate([pad1,beacon*.5,bcnz])
    beacon2 = wbz  

    possible_dim = []
    possible_dim.append(2**(np.ceil(np.log2(M))))
    h_dim = min(possible_dim)
    hadamard_matrix = hadamard(h_dim)
    beacon_weights = hadamard_matrix[0:M, 0:M]
    beacon_weights = beacon_weights.astype(np.uint32)

    #### Generate Data
    data_cp_len = 16 if cp else 0
    data_ofdm_len = N + data_cp_len
    n_ofdm_syms = (numSamps // data_ofdm_len)
    sig_t, data_const, tx_data, sc_idx_all, pilots_matrix = \
        ofdm_obj.generate_data(n_ofdm_syms - 2, mod_order, cp_length=data_cp_len)
    data_sc = sc_idx_all[0]
    pilot_sc = sc_idx_all[1]
    tx_dl_data = np.zeros((N, n_ofdm_syms, K)).astype(complex)
    for k in range(K):
        tx_dl_data[data_sc, 2:, k] = data_const
        tx_dl_data[pilot_sc, 2:, k] = pilots_matrix
        tx_dl_data[:, 0, k] = lts_f
        tx_dl_data[:, 1, k] = lts_f
    tx_dl_ifft = np.zeros((M, n_ofdm_syms, N)).astype(complex)
    print("n_ofdm_syms %d, data_ofdm_len %d"%(n_ofdm_syms, data_ofdm_len))

    # received data params 
    lts_thresh = 0.8
    n_data_ofdm_syms = n_ofdm_syms - 2
    payload_len = n_data_ofdm_syms * data_ofdm_len
    lts_len = 2 * data_ofdm_len
    fft_offset = 0

    #### Configure tdd mode
    guardSize = (len(csdrs)) % 2 + 1
    frameLen = len(csdrs) + len(bsdrs)*2 + 4 + guardSize

    # BS frame config
    for i,sdr in enumerate(bsdrs):
        beacon_sch = "BG"
        if i == ref_ant:
            ref_ul_pilot_sch = "PG"
            ref_dl_pilot_sch = ''.join("RG" * (M - 1))
            ul_pilot_sch = ''.join("R" * K)
        else:
            ref_ul_pilot_sch = "RG"
            new_i = i - (i > ref_ant)
            ref_dl_pilot_sch = ''.join("GG" * new_i) + "PG" + ''.join("GG" * (M-(new_i+2)))
            ul_pilot_sch = ''.join("R" * K)

        frame_sch1 = beacon_sch + ref_ul_pilot_sch + ref_dl_pilot_sch + ul_pilot_sch + 'G' 

        dl_data_sch = "PG" + ''.join("G" * (2 * M + K - (2 * D)))
        frame_sch2 = beacon_sch + dl_data_sch + 'G'

        print("BS node %d frame schedule (%s, %s)" % (i, frame_sch1, frame_sch2))
        bconf = {"tdd_enabled": True, 
                "frame_mode": "triggered", 
                "symbol_size" : sym_samps, 
                "frames": [frame_sch1, frame_sch2],
                "beacon_start" : prefix_length,
                "beacon_stop" : prefix_length+len(beacon),
                "max_frame" : 2}
        sdr.writeSetting("TDD_CONFIG", json.dumps(bconf))
        sdr.writeSetting("TDD_MODE", "true")

    # Client frame config
    for i, sdr in enumerate(csdrs):
        det_sch = "GG"
        ref_pilot_sch = ''.join("GG" * M)
        ul_pilot_sch = ''.join("G" * i) + "P" + ''.join("G" * (K-(i+1)))
        frame_sch1 = det_sch + ref_pilot_sch + ul_pilot_sch + 'G'

        dl_data_sch = "RG" * D + ''.join("G" * (2 * M + K - (2 * D)))
        frame_sch2 = det_sch + dl_data_sch + 'G'

        print("Client %d frame schedule  (%s, %s)"%(i, frame_sch1, frame_sch2))
        cconf = {"tdd_enabled": True,
                 "frame_mode": "triggered",
                 "symbol_size" : sym_samps,
                 "frames": [frame_sch1, frame_sch2],
                 "max_frame" : 0}
        sdr.writeSetting("TDD_CONFIG", json.dumps(cconf))
        sdr.writeSetting("TDD_MODE", "true")

    for sdr in bsdrs+csdrs:
        sdr.writeSetting("TX_SW_DELAY", str(30))

    if not use_trig:
        for sdr in csdrs:
            # enable the correlator, with zeros as inputs
            corr_conf = {"corr_enabled" : True,
                        "corr_threshold" : 1}
            sdr.writeSetting("CORR_CONFIG", json.dumps(corr_conf))
            sdr.writeRegisters("CORR_COE", 0, coe.tolist())

            # DEV: ueTrigTime = 153 (prefix_length=0),
            # CBRS: ueTrigTime = 235 (prefix_length=82), tx_advance=prefix_length,
            # corr delay is 17 cycles
            #cl_trig_time = prefix_length + len(beacon) + postfix_length + 17 + postfix_length
            cl_trig_time = 256 + 250
            sf_start = cl_trig_time // sym_samps
            sp_start = cl_trig_time % sym_samps
            print("UE starting symbol and sample count (%d, %d)" % (sf_start, sp_start))
            # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."
            sdr.setHardwareTime(SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start, rate), "TRIGGER")
    else:
        for sdr in csdrs:
            sdr.setHardwareTime(0, "TRIGGER")

    for i,sdr in enumerate(bsdrs):
        sdr.setHardwareTime(0, "TRIGGER")

    replay_addr = 0
    pilot_uint = cfloat2uint32(wb_pilot1, order='QI').tolist()
    beacon_uint = cfloat2uint32(beacon1, order='QI').tolist()
    zero_uint = cfloat2uint32(wbz, order='QI').tolist() 
    for i, sdr in enumerate(bsdrs):
        sdr.writeRegisters("BEACON_RAM", 0, beacon_uint)
        sdr.writeRegisters("BEACON_RAM_WGT_A", 0, beacon_weights[i].tolist())
        sdr.writeSetting("BEACON_START", str(M))

    for sdr in csdrs:
        sdr.writeRegisters("TX_RAM_A", replay_addr, pilot_uint)
        sdr.writeRegisters("TX_RAM_B", replay_addr, zero_uint)

    # Create and activate streams
    rx_stream_ul = [sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1]) for sdr in bsdrs]
    rx_stream_dl = [sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1]) for sdr in csdrs]
    flags = 0
    for i, sdr in enumerate(bsdrs):
        sdr.activateStream(rx_stream_ul[i], flags, 0)
    for i, sdr in enumerate(csdrs):
        sdr.activateStream(rx_stream_dl[i], flags, 0)

    #############
    #initialize array and matrixes to hold rx and processed data
    #############
    calib_rx_dl = [np.array([1]*sym_samps).astype(np.complex64) for m in range(M)]
    calib_rx_ul = [np.array([1]*sym_samps).astype(np.complex64) for m in range(M)]
    data_rx_dl = [[np.array([0]*sym_samps).astype(np.complex64) for k in range(K)] for m in range(D)]
    pilot_rx_ul = [[np.array([0]*sym_samps).astype(np.complex64) for m in range(M)] for k in range(K)]
    dummy_rx = np.array([0]*sym_samps).astype(np.complex64)

    ul_cal_offset = np.array([0]*M, np.int32)
    dl_cal_offset = np.array([0]*M, np.int32)

    ul_offset = [np.array([0]*K, np.int32) for m in range(M)] 
    dl_offset = [np.array([0]*K, np.int32) for m in range(M)] 

    ul_csi_mat = np.empty([K, M, N], dtype=np.complex64)
    rx_f_cal_dl = np.empty([M, N], dtype=np.complex64)
    rx_f_cal_ul = np.empty([M, N], dtype=np.complex64)

    w_zf_dl = np.empty([M, K, N], dtype=np.complex64)
    w_conj_dl = np.empty([M, K, N], dtype=np.complex64)

    calib = np.empty((M, N)).astype(np.complex64)

    rxSymbols_mat = np.empty([len(data_sc), D * n_data_ofdm_syms, K], dtype=np.complex64)

    cont_plotter = plotter

    if cont_plotter:
        fig1, axes1 = plt.subplots(nrows=M, ncols=2, figsize=(9, 12))
        axes1[0, 0].set_title('Pilot Uplink (Re)')
        axes1[0, 1].set_title('Pilot Uplink (Im)')
        for m in range(M):
            axes1[m, 0].set_xlim(0, sym_samps)
            axes1[m, 0].set_ylim(-1, 1)
            if m == ref_ant:
                axes1[m, 0].set_ylabel('Ant %d (ref)'%m)
            else:
                axes1[m, 0].set_ylabel('Ant %d'%m)
            axes1[m, 0].legend(fontsize=10)
            axes1[m, 1].set_xlim(0, sym_samps)
            axes1[m, 1].set_ylim(-1, 1)
            axes1[m, 1].legend(fontsize=10)
        lines11 = [[axes1[m, 0].plot(range(sym_samps), np.real(pilot_rx_ul[k][m]), label="User %d (real)"%k)[0] for k in range(K)] for m in range(M)]
        lines12 = [[axes1[m, 1].plot(range(sym_samps), np.imag(pilot_rx_ul[k][m]), label="User %d (imag)"%k)[0] for k in range(K)] for m in range(M)]
        fig1.show()

        fig2, axes2 = plt.subplots(nrows=M, ncols=2, figsize=(9, 12))
        axes2[0, 0].set_title('Calibration Downlink')
        axes2[0, 1].set_title('Calibration Uplink')
        for m in range(M):
            axes2[m, 0].set_xlim(0, sym_samps)
            axes2[m, 0].set_ylim(-1, 1)
            if m == ref_ant:
                axes2[m, 0].set_ylabel('Ant %d (ref)'%m)
            else:
                axes2[m, 0].set_ylabel('Ant %d'%m)
            axes2[m, 0].legend(fontsize=10)
            axes2[m, 1].set_xlim(0, sym_samps)
            axes2[m, 1].set_ylim(-1, 1)
            axes2[m, 1].legend(fontsize=10)
        lines20 = [axes2[m, 0].plot(range(sym_samps), calib_rx_dl[m][:sym_samps])[0] for m in range(M)]
        lines21 = [axes2[m, 1].plot(range(sym_samps), calib_rx_ul[m][:sym_samps])[0] for m in range(M)]
        lines24 = [axes2[m, 0].plot(range(sym_samps), calib_rx_dl[m][:sym_samps])[0] for m in range(M)]
        lines25 = [axes2[m, 1].plot(range(sym_samps), calib_rx_ul[m][:sym_samps])[0] for m in range(M)]
        fig2.show()

        fig3, axes3 = plt.subplots(nrows=K, ncols=1, figsize=(6, 6))
        for k in range(K):
            if K == 1:
                ax3 = axes3
            else:
                ax3 = axes3[k]
            ax3.grid(True)
            ax3.set_title('TX/RX Constellation')
            ax3.set_xlabel('')
            ax3.set_ylabel('')
            ax3.set_ylim(-5.5, 5.5)
            ax3.set_xlim(-5.8, 5.8)
            ax3.legend(fontsize=10)

        if K == 1:
            line31, = axes3.plot([], [], 'ro', label='TXSym')
            line32, = axes3.plot([], [], 'bx', label='RXSym')
        else:
            line31 = [axes3[k].plot([], [], 'ro', label='TXSym')[0] for k in range(K)]
            line32 = [axes3[k].plot([], [], 'bx', label='RXSym')[0] for k in range(K)]

        fig3.show()

        fig4, axes4 = plt.subplots(nrows=K, ncols=1, figsize=(6, 6))
        for k in range(K):
            if K == 1:
                ax4 = axes4
            else:
                ax4 = axes4[k]
            ax4.grid(True)
            ax4.set_title('Received Downlink')
            ax4.set_xlabel('')
            ax4.set_ylabel('')
            ax4.set_ylim(-1, 1)
            ax4.set_xlim(0, sym_samps)
            ax4.legend(fontsize=10)

        if K == 1:
            line41, = axes4.plot(range(sym_samps), data_rx_dl[0][0], label='RX Downlink')
            line42, = axes4.plot(range(sym_samps), data_rx_dl[0][0])
        else:
            line41 = [axes4[k].plot(range(sym_samps), data_rx_dl[0][k], label='RX Downlink')[0] for k in range(K)]
            line42 = [axes4[k].plot(range(sym_samps), data_rx_dl[0][k])[0] for k in range(K)]

        fig4.show()


    cur_frame = 0
    signal.signal(signal.SIGINT, signal_handler)
    tstart = datetime.datetime.now()

    while(RUNNING):

        ## disarm correlator in the clients
        if not use_trig:    
            for i, sdr in enumerate(csdrs):
                sdr.writeSetting("CORR_CONFIG", json.dumps({"corr_enabled": False}))

        bad_recip_read = False
        bad_frame = False
        ## arm correlator in the clients, inputs from adc
        if not use_trig:    
            for i, sdr in enumerate(csdrs):
                sdr.writeSetting("CORR_START", "A")

        for i, sdr in enumerate(bsdrs):
            sdr.writeRegisters("TX_RAM_A", 0, pilot_uint)
            sdr.writeRegisters("TX_RAM_B", 0, zero_uint)

        trig_dev.writeSetting("TRIGGER_GEN", "")

        ## collect reciprocity pilots from antenna m
        for m in range(M):
            if bad_recip_read: break
            if m != ref_ant:
                sr = bsdrs[m].readStream(rx_stream_ul[m], [calib_rx_ul[m], dummy_rx], sym_samps)
                if sr.ret < sym_samps:
                    print("Calib: m %d ret %d"%(m,sr.ret))
                    bad_recip_read = True

        for m in range(M):
            if bad_recip_read: break
            if m != ref_ant:
                sr = bsdrs[ref_ant].readStream(rx_stream_ul[ref_ant], [calib_rx_dl[m], dummy_rx], sym_samps)
                if sr.ret < sym_samps:
                    print("Calib: m %d ret %d"%(m,sr.ret))
                    bad_recip_read = True

        if bad_recip_read: 
            print("BAD RECIPROCAL PILOT READ... CONTINUE! ")
            continue

        ## collect uplink pilots
        bad_pilot_read = False
        for k in range(K):
            if bad_pilot_read: break
            for m in range(M):
                sr = bsdrs[m].readStream(rx_stream_ul[m], [pilot_rx_ul[k][m], dummy_rx], sym_samps)
                if sr.ret < sym_samps:
                    print("PilotUP: k: %d, m %d ret %d"%(k,m,sr.ret))
                    bad_pilot_read = True

        if bad_pilot_read: 
            print("BAD PILOT READ... CONTINUE! ")
            continue


        ## process downlink signal 
        # processing the received calibration samples
        print("frame %d"%(cur_frame))
        for m in range(M):
            if ref_ant == m: 
                calib[m,:] = np.array([1]*N, np.complex64) #continue
                rx_f_cal_dl[m,:] = np.array([0]*N, np.complex64) 
                rx_f_cal_ul[m,:] = np.array([0]*N, np.complex64) 
                continue 
            calib_rx_dl[m] -= np.mean(calib_rx_dl[m])
            calib_rx_ul[m] -= np.mean(calib_rx_ul[m])
             
            best_peak_dl, _, _ = find_lts(calib_rx_dl[m], thresh=LTS_THRESH)
            best_peak_ul, _, _ = find_lts(calib_rx_ul[m], thresh=LTS_THRESH)
            dl_cal_offset[m] = 0 if not best_peak_dl else best_peak_dl - len(lts_sym) + cp_len 
            ul_cal_offset[m] = 0 if not best_peak_ul else best_peak_ul - len(lts_sym) + cp_len 
            if (dl_cal_offset[m] < 150 or ul_cal_offset[m] < 150):
                bad_frame = True
            lts_dn_1 = calib_rx_dl[m][dl_cal_offset[m]:dl_cal_offset[m]+N]
            lts_dn_2 = calib_rx_dl[m][dl_cal_offset[m]+N:dl_cal_offset[m]+2*N]
            lts_up_1 = calib_rx_ul[m][ul_cal_offset[m]:ul_cal_offset[m]+N]
            lts_up_2 = calib_rx_ul[m][ul_cal_offset[m]+N:ul_cal_offset[m]+2*N]

            rx_f_cal_dl1 = np.fft.fftshift(np.fft.fft(lts_dn_1, N, 0), 0)
            rx_f_cal_dl2 = np.fft.fftshift(np.fft.fft(lts_dn_2, N, 0), 0)
            rx_f_cal_ul1 = np.fft.fftshift(np.fft.fft(lts_up_1, N, 0), 0)
            rx_f_cal_ul2 = np.fft.fftshift(np.fft.fft(lts_up_2, N, 0), 0)
            rx_f_cal_dl[m, :] = (rx_f_cal_dl1 + rx_f_cal_dl2)/2
            rx_f_cal_ul[m, :] = (rx_f_cal_ul1 + rx_f_cal_ul2)/2
            calib[m,:] = np.divide(rx_f_cal_dl[m,:], rx_f_cal_ul[m,:])
 
        # processing uplink pilot received samples
        for k in range(K):
            for m in range(M):
                pilot_rx_ul[k][m] -= np.mean(pilot_rx_ul[k][m]) 
                best_peak, _, _ = find_lts(pilot_rx_ul[k][m], thresh=LTS_THRESH)
                ul_offset[m][k] = 0 if not best_peak else (best_peak - len(lts_sym) + cp_len) 
                if ul_offset[m][k] < 150:
                    bad_frame = True 
                lts_ul_1 = pilot_rx_ul[k][m][ul_offset[m][k]:ul_offset[m][k]+N]
                lts_ul_2 = pilot_rx_ul[k][m][ul_offset[m][k]+N:ul_offset[m][k]+2*N]
                rx_f_ul1 = np.fft.fftshift(np.fft.fft(lts_ul_1, N, 0), 0)
                rx_f_ul2 = np.fft.fftshift(np.fft.fft(lts_ul_2, N, 0), 0)
                ul_csi_mat[k,m,:] = (rx_f_cal_ul1 + rx_f_cal_ul2) * lts_f / 2 

        # processing beamforming vectors and downlink transmit data
        for l in range(n_ofdm_syms):
            for n in range(N):
                dl_csi = np.matmul(ul_csi_mat[:, :, n], np.diag(calib[:, n]))
                w_zf_dl[:, :, n] = np.linalg.pinv(dl_csi)
                tx_dl_ifft[:, l, n] = np.matmul(w_zf_dl[:, :, n], tx_dl_data[n, l, :])

        tx_sym = np.fft.ifft(tx_dl_ifft, axis=2)
        tx_sym = np.concatenate((tx_sym[:,:,-data_cp_len:], tx_sym), axis=2)

        # send downlink signal
        for i, sdr in enumerate(bsdrs):
            tx_sig = np.reshape(tx_sym[i, :, :], (1, n_ofdm_syms * data_ofdm_len)) 
            tx_sig = np.concatenate([pad1, tx_sig[0, :], pad2])
            sdr.writeRegisters("TX_RAM_A", 0, cfloat2uint32(tx_sig, order='QI').tolist())
            sdr.writeRegisters("TX_RAM_B", 0, zero_uint)

        trig_dev.writeSetting("TRIGGER_GEN", "")

        # collect downlink data from antenna k
        bad_dl_read = False
        for d in range(D):
            if bad_dl_read: break
            for k in range(K):
                sr = csdrs[k].readStream(rx_stream_dl[k], [data_rx_dl[d][k], dummy_rx], sym_samps)
                if sr.ret < sym_samps:
                    print("DL DATA: symbol %d, k %d, ret %d"%(d, k, sr.ret))
                    bad_dl_read = True

        if bad_dl_read: 
            print("BAD DL READ... CONTINUE! ")
            continue

        # DC removal
        # Find LTS peaks (in case LTSs were sent)
        bad_dl_data = False
        for k in range(K):
            if bad_dl_data: break
            for d in range(D):
                data_rx_dl[d][k] -= np.mean(data_rx_dl[d][k])
                best_peak_dl, b, peaks0 = find_lts(data_rx_dl[d][k], thresh=lts_thresh, flip=True, lts_seq=lts_t_cp)
                if use_trig:
                    dl_offset[k] = 163 + 160 #0 if not best_peak_dl else best_peak_dl
                else:
                    dl_offset[k] = 0 if not best_peak_dl else best_peak_dl
                if dl_offset[k] < lts_len:
                    bad_dl_data = True
                    print("NO VALID DOWNLINK... CONTINUE! ")
                    break
                payload_start = dl_offset[k]
                payload_end = payload_start + payload_len  # Payload_len == (n_ofdm_syms * (num_sc + data_cp_len))
                lts_start = payload_start - lts_len  # where LTS-CP start
                lts = data_rx_dl[d][k][lts_start: payload_start]
                if len(lts) < lts_len:
                    print("BAD DOWNLINK PILOT... CONTINUE!  ")
                    bad_dl_data = True
                    break
                lts_1 = lts[16 + -fft_offset + np.array(range(0, 64))]
                lts_2 = lts[96 + -fft_offset + np.array(range(0, 64))]

                # Average 2 LTS symbols to compute channel estimate
                tmp = np.fft.ifftshift(lts_f)
                chan_est = np.fft.ifftshift(lts_f) * (np.fft.fft(lts_1) + np.fft.fft(lts_2))/2
                if len(data_rx_dl[d][k]) >= payload_end:
                    # Retrieve payload symbols
                    payload_samples = data_rx_dl[d][k][payload_start: payload_end]
                else:
                    bad_dl_data = True
                    print("TOO LATE (payload_end %d)... CONTINUE! "%payload_end)
                    break
                payload_samples_mat_cp = np.reshape(payload_samples, (data_ofdm_len, n_data_ofdm_syms), order="F")

                # Remove cyclic prefix
                payload_samples_mat = payload_samples_mat_cp[data_cp_len - fft_offset + np.array(range(0, N)), :]

                # FFT
                rxSig_freq = np.fft.fft(payload_samples_mat, n=N, axis=0)

                # Equalizer
                chan_est_tmp = chan_est.reshape(len(chan_est), 1, order="F")
                rxSig_freq_eq = rxSig_freq / np.matlib.repmat(chan_est_tmp, 1, n_data_ofdm_syms)
                phase_error = ofdm_obj.phase_correction(rxSig_freq_eq, pilot_sc, pilots_matrix)

                phase_corr_tmp = np.matlib.repmat(phase_error, N, 1)
                phase_corr = np.exp(-1j * phase_corr_tmp)
                rxSig_freq_eq_phase = rxSig_freq_eq * phase_corr
                rxSymbols_mat[:, d * n_data_ofdm_syms : (d + 1) * n_data_ofdm_syms, k] = rxSig_freq_eq_phase[data_sc, :]

        if bad_dl_data:
            continue

        evm_mat = np.power(np.abs(rxSymbols_mat - np.tile(tx_dl_data[data_sc, 2:, :], (1, D, 1))), 2)
        evm_per_user = np.mean(np.reshape(evm_mat, (len(data_sc) * n_data_ofdm_syms * D, K)), axis=0)
        evm_per_user_db = 10 * np.log10(evm_per_user)
        print('EVM (dB) per user')
        print([ "{:2.2f}".format(x) for x in evm_per_user_db ])
        print('')

        cur_frame += 1
        if cur_frame >= TOT_FRAMES: break
        if cont_plotter:

            for m in range(M):
                if m == ref_ant:
                    lines20[m].set_ydata(np.real(wb_pilot1))
                    lines21[m].set_ydata(np.real(wb_pilot1))
                    continue
                lines20[m].set_ydata(np.real(calib_rx_dl[m]))
                lines21[m].set_ydata(np.real(calib_rx_ul[m]))
                lines24[m].set_data(dl_cal_offset[m], np.linspace(-1.0, 1.0, num=100))
                lines25[m].set_data(ul_cal_offset[m], np.linspace(-1.0, 1.0, num=100))

            for m in range(M):
                for k in range(K):
                    lines11[m][k].set_ydata(np.real(pilot_rx_ul[k][m]))
                    lines12[m][k].set_ydata(np.imag(pilot_rx_ul[k][m]))

            if K == 1:
                txSyms_all = tx_dl_data[data_sc, 2:, 0].flatten()
                rxSyms_all = rxSymbols_mat[:, :, 0].flatten()
                line31.set_data(np.real(txSyms_all), np.imag(txSyms_all))
                line32.set_data(np.real(rxSyms_all), np.imag(rxSyms_all))
                line41.set_data(range(sym_samps), np.real(data_rx_dl[0][0]))
                line42.set_data(dl_offset[0], np.linspace(-1.0, 1.0, num=100))
            else:
                for k in range(K):
                    txSyms_all = tx_dl_data[data_sc, 2:, k].flatten()
                    rxSyms_all = rxSymbols_mat[:, :, k].flatten()
                    line31[k].set_data(np.real(txSyms_all), np.imag(txSyms_all))
                    line32[k].set_data(np.real(rxSyms_all), np.imag(rxSyms_all))
                    line41[k].set_data(range(sym_samps), np.real(data_rx_dl[0][k]))
                    line42[k].set_data(dl_offset[k], np.linspace(-1.0, 1.0, num=100))

            fig1.canvas.draw()
            fig1.show()

            fig2.canvas.draw()
            fig2.show()

            fig3.canvas.draw()
            fig3.show()

            fig4.canvas.draw()
            fig4.show()

    tend = datetime.datetime.now()
    c = tend - tstart
    print("Elapsed %d (secs)"%c.total_seconds())

    # clear up fpga states 
    tdd_conf = {"tdd_enabled" : False}
    corr_conf = {"corr_enabled" : False}
    for sdr in csdrs:
        if not use_trig:
            sdr.writeSetting("CORR_CONFIG", json.dumps(corr_conf))
    for sdr in bsdrs+csdrs:
        sdr.writeSetting("TDD_CONFIG", json.dumps(tdd_conf))
        sdr.writeSetting("TDD_MODE", "false")
        sdr.writeSetting("RESET_DATA_LOGIC", "")

    # close streams and exit
    for i, sdr in enumerate(bsdrs):
        sdr.closeStream(rx_stream_ul[i])
    for i, sdr in enumerate(csdrs):
        sdr.closeStream(rx_stream_dl[i])
コード例 #10
0
    def setup(self):

        # BS
        for i, sdr in enumerate(self.bsdrs):
            sched_main = "PG" + ''.join(
                "G" * i * self.sdr_ant) + "T" * self.sdr_ant + ''.join(
                    "G" * (self.num_ants -
                           (i + 1) * self.sdr_ant)) + "G" + ''.join(
                               "R" * (len(self.csdrs))) + "G"
            #print("BS node %d"%i)
            #print("sched_main   %s"%(sched_main))
            bconf = {
                "tdd_enabled": True,
                "frame_mode": "free_running",
                "symbol_size": self.symSamp,
                "frames": [sched_main],
                "max_frame": 1
            }
            sdr.writeSetting("TDD_CONFIG", json.dumps(bconf))
            sdr.writeSetting("TDD_MODE", "true")

        # Client
        for i, sdr in enumerate(self.csdrs):
            sched_main = "GG" + ''.join("R" * self.num_bsdrs) + "G" + ''.join(
                "G" * i) + "P" + ''.join("G" * (self.num_csdrs -
                                                (i + 1))) + "G"
            #print("Client node %d"%i)
            #print("sched_main   %s"%(sched_main))
            cconf = {
                "tdd_enabled": True,
                "frame_mode": "triggered",
                "symbol_size": self.symSamp,
                "frames": [sched_main],
                "max_frame": 0
            }
            sdr.writeSetting("TDD_CONFIG", json.dumps(cconf))
            sdr.writeSetting("TDD_MODE", "true")

        for sdr in self.bsdrs + self.csdrs:
            sdr.writeSetting("TX_SW_DELAY", str(30))

        z = np.empty(self.symSamp).astype(np.complex64)
        if self.ota_trig:
            coe = cfloat2uint32(
                np.conj(self.coeffs),
                order='IQ')  # FPGA correlator takes coefficients in QI order
            for sdr in self.csdrs:
                sdr.writeRegister("IRIS30", CORR_CONF, int(
                    "00004001",
                    16))  # enable the correlator, with zeros as inputs
                for i in range(128):
                    sdr.writeRegister("ARGCOE", i * 4, 0)
                time.sleep(0.1)
                sdr.writeRegister("IRIS30", CORR_RST, 0x1)  # reset corr
                sdr.writeRegister("IRIS30", CORR_RST, 0x0)  # unrst corr
                sdr.writeRegister("IRIS30", CORR_THRESHOLD, 1)
                for i in range(128):
                    sdr.writeRegister("ARGCOE", i * 4, int(coe[i]))

                sf_start = self.rf_roundtrip // self.symSamp
                sp_start = self.rf_roundtrip % self.symSamp
                #print("UE starting symbol and sample count (%d, %d)" % (sf_start, sp_start))
                # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..."
                sdr.setHardwareTime(
                    SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start,
                                           self.rate), "TRIGGER")
        else:
            for sdr in self.csdrs:
                sdr.setHardwareTime(0, "TRIGGER")

        replay_addr = 0
        for i, sdr in enumerate(self.bsdrs):
            sdr.writeRegisters("TX_RAM_A", replay_addr,
                               cfloat2uint32(self.beacon, order='IQ').tolist())
            if self.beacon_weights is not None:
                sdr.writeRegisters(
                    "TX_RAM_B", replay_addr,
                    cfloat2uint32(self.beacon, order='IQ').tolist())
                sdr.writeRegisters(
                    "TX_RAM_WGT_A", replay_addr,
                    self.beacon_weights[self.sdr_ant * i].tolist())
                if self.sdr_ant == 2:
                    sdr.writeRegisters(
                        "TX_RAM_WGT_B", replay_addr,
                        self.beacon_weights[self.sdr_ant * i + 1].tolist())

                sdr.writeRegister("RFCORE", 156, int(self.num_ants))
                sdr.writeRegister("RFCORE", 160, 1)  # enable beamsweeping
            else:
                break  # if beamsweep is not active, only send pilot from the first antenna
            sdr.setHardwareTime(0, "TRIGGER")

        for sdr in self.csdrs:
            sdr.writeRegisters("TX_RAM_A", replay_addr,
                               cfloat2uint32(self.pilot, order='IQ').tolist())
            sdr.writeRegisters("TX_RAM_B", replay_addr,
                               cfloat2uint32(z, order='IQ').tolist())

        ret = 0
        dummy = np.empty(self.symSamp).astype(np.complex64)
        dummy2 = np.empty(self.symSamp).astype(np.complex64)
        for r, sdr in enumerate(self.bsdrs):
            #if r != m:
            while ret >= 0:
                sr = sdr.readStream(self.rxBsStream[r], [dummy, dummy2],
                                    self.symSamp,
                                    timeoutUs=0)
                ret = sr.ret
            ret = 0

        for r, sdr in enumerate(self.csdrs):
            #if r != m:
            while ret >= 0:
                sr = sdr.readStream(self.rxBsStream[r], [dummy, dummy2],
                                    self.symSamp,
                                    timeoutUs=0)
                ret = sr.ret
            ret = 0

        # arm correlator in the clients
        if self.ota_trig:
            for i, sdr in enumerate(self.csdrs):
                sdr.writeRegister("IRIS30", CORR_CONF, int(
                    "00004011",
                    16))  # enable the correlator, with inputs from adc