def signal_handler(rate, numSyms, use_trig, signal, frame): global bsdr, msdr, running, txStreamM, rxStreamB corr_conf = {"corr_enabled" : False} if not use_trig: msdr.writeSetting("CORR_CONFIG", json.dumps(corr_conf)) tpc_conf = {"tpc_enabled" : False} msdr.writeSetting("TPC_CONFIG", json.dumps(tpc_conf)) # stop tx/rx threads running = False print("printing number of frames") print("NB 0x%X" % SoapySDR.timeNsToTicks(bsdr.getHardwareTime(""), rate)) print("UE 0x%X" % SoapySDR.timeNsToTicks(msdr.getHardwareTime(""), rate)) # ADC_rst, stops the tdd time counters tdd_conf = {"tdd_enabled" : False} for sdr in [bsdr, msdr]: sdr.writeSetting("RESET_DATA_LOGIC", "") sdr.writeSetting("TDD_CONFIG", json.dumps(tdd_conf)) sdr.writeSetting("TDD_MODE", "false") agc_conf = {"agc_enabled" : False} msdr.writeSetting("AGC_CONFIG", json.dumps(agc_conf)) bsdr = None msdr = None sys.exit(0)
def recv_stream_tdd(self): '''Read an incoming stream.''' max_frames = int(self.max_frames) in_len = int(self.n_samp) wave_rx_a = np.zeros((in_len), dtype=np.complex64) wave_rx_b = np.zeros((in_len), dtype=np.complex64) rx_frames_a = np.zeros((in_len * max_frames), dtype=np.complex64) n_R = self.tdd_sched.count( "R") #How many Read frames in the tdd schedule print("n_samp is: %d \n" % self.n_samp) for m in range(max_frames): for k in range(n_R): r1 = self.sdr.readStream(self.rx_stream, [wave_rx_a, wave_rx_b], int(self.n_samp)) print("reading stream: ({})".format(r1)) rx_frames_a[m * in_len:(m * in_len + in_len)] = wave_rx_a print("SDR {} ".format( SoapySDR.timeNsToTicks(self.sdr.getHardwareTime(""), self.sample_rate))) #print("recv_stream_tdd: wave_rx_a: \n") return (rx_frames_a)
def sdr_gettriggers(self): #time.sleep(1) t = SoapySDR.timeNsToTicks( self.sdr.getHardwareTime(""), self.sample_rate) >> 32 #trigger count is top 32 bits. print("%d new triggers" % (t)) return t
def signal_handler(rate, numSyms, signal, frame): global bsdr, msdr, running, txStreamM, rxStreamB msdr.writeRegister( "IRIS30", CORR_CONF, 0 ) # stop mobile correlator first, to prevent from the tdd manager going msdr.writeRegister("IRIS30", TX_GAIN_CTRL, 0) # stop tx/rx threads running = False print("printing number of frames") print("NB 0x%X" % SoapySDR.timeNsToTicks(bsdr.getHardwareTime(""), rate)) print("UE 0x%X" % SoapySDR.timeNsToTicks(msdr.getHardwareTime(""), rate)) #print("UE SCNT: 0x%X" % msdr.readRegister("ARGCOR", CORR_SCNT)) # ADC_rst, stops the tdd time counters for sdr in [bsdr, msdr]: sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) sdr.writeRegister("IRIS30", RF_RST_REG, 0) for i in range(numSyms): msdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 msdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 bsdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.writeSetting("TDD_MODE", "false") bsdr.writeSetting("TDD_MODE", "false") bsdr = None msdr = None if exit_plot: fig = plt.figure(figsize=(20, 8), dpi=100) ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2) pilot = uint32tocfloat(read_from_file("rxpilot", 256)) rxdata = uint32tocfloat(read_from_file("rxdata", 256)) ax1.plot(np.real(pilot), label='pilot i') ax1.plot(np.imag(pilot), label='pilot q') ax2.plot(np.real(rxdata), label='rx data i') ax2.plot(np.imag(rxdata), label='rx data q') plt.show() sys.exit(0)
def signal_handler(rate, numSyms, signal, frame): global sdrs, hub_dev print("printing number of frames") for sdr in sdrs: print("NB 0x%X" % SoapySDR.timeNsToTicks(sdr.getHardwareTime(""), rate)) # ADC_rst, stops the tdd time counters sdr.writeSetting("RESET_DATA_LOGIC", "") conf = {"tdd_enabled" : False} sdr.writeSetting("TDD_CONFIG", json.dumps(conf)) sdr.writeSetting("TDD_MODE", "false") sdrs = None hub_dev = None sys.exit(0)
def signal_handler(rate, numSyms, txSymNum, signal, frame): global msdr, running, txStreamM, rxStreamM msdr.writeRegister("IRIS30", CORR_CONF, 0) # stop mobile correlator first, to prevent from the tdd manager going msdr.writeRegister("IRIS30", TX_GAIN_CTRL, 0) # stop tx/rx threads if txSymNum>0: running = False time.sleep(1) print("printing number of frames") print("0x%X" % SoapySDR.timeNsToTicks(msdr.getHardwareTime(""),rate)) # ADC_rst, stops the tdd time counters msdr.writeRegister("IRIS30", RF_RST_REG, (1<<29)| 0x1) msdr.writeRegister("IRIS30", RF_RST_REG, (1<<29)) msdr.writeRegister("IRIS30", RF_RST_REG, 0) #msdr.writeSetting("TDD_MODE", str(0x0)) #disable TDD mode for i in range(numSyms): msdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 msdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay msdr.writeSetting("TDD_MODE", "false") msdr = None sys.exit(0)
def siso_tdd_burst(serial1, serial2, rate, freq, txgain, rxgain, numSamps, prefix_pad, postfix_pad, both_channels, wideband): bsdr = SoapySDR.Device(dict(driver='iris', serial=serial1)) msdr = SoapySDR.Device(dict(driver='iris', 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.setFrequency(SOAPY_SDR_TX, ch, freq) sdr.setFrequency(SOAPY_SDR_RX, ch, freq) sdr.setSampleRate(SOAPY_SDR_TX, ch, rate) sdr.setSampleRate(SOAPY_SDR_RX, ch, 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.setDCOffsetMode(SOAPY_SDR_RX, ch, True) #for ch in [0,1]: # sdr.writeSetting(SOAPY_SDR_RX, ch, "CALIBRATE", '') # sdr.writeSetting(SOAPY_SDR_TX, ch, "CALIBRATE", '') #sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false') #sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false') sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) sdr.writeRegister("IRIS30", RF_RST_REG, 0) bsdr.writeSetting("SYNC_DELAYS", "") symSamp = numSamps + prefix_pad + postfix_pad print("numSamps = %d" % numSamps) print("symSamps = %d" % symSamp) waveRxA1 = np.array([0] * symSamp, np.uint32) waveRxB1 = np.array([0] * symSamp, np.uint32) waveRxA2 = np.array([0] * symSamp, np.uint32) waveRxB2 = np.array([0] * symSamp, np.uint32) #bsdr.writeSetting("FPGA_DIQ_MODE", "PATTERN") #msdr.writeSetting("FPGA_DIQ_MODE", "PATTERN") # CS16 makes sure the 4-bit lsb are samples are being sent rxStreamB = bsdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1], dict(WIRE=SOAPY_SDR_CS16)) rxStreamM = msdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1], dict(WIRE=SOAPY_SDR_CS16)) if wideband: ltsSym = lts.genLTS(upsample=1, cp=0) pilot = np.tile(ltsSym, numSamps / len(ltsSym)).astype( np.complex64) * .5 else: Ts = 1 / rate s_freq = 1e5 s_time_vals = np.array(np.arange(0, numSamps)).transpose() * Ts pilot = np.exp(s_time_vals * 1j * 2 * np.pi * s_freq).astype( np.complex64) * .25 pad1 = np.array([0] * prefix_pad, np.complex64) pad2 = np.array([0] * postfix_pad, np.complex64) wbz = np.array([0] * (symSamp), np.complex64) pilot1 = np.concatenate([pad1, pilot, pad2]) pilot2 = pilot1 if both_channels else wbz # configure tdd mode bconf = { "tdd_enabled": True, "trigger_out": True, "symbol_size": symSamp, "frames": ["PGRG"] } bsdr.writeSetting("TDD_CONFIG", json.dumps(bconf)) mconf = { "tdd_enabled": True, "trigger_out": True, "symbol_size": symSamp, "frames": ["RGPG"] } msdr.writeSetting("TDD_CONFIG", json.dumps(mconf)) msdr.writeSetting("TDD_MODE", "true") bsdr.writeSetting("TDD_MODE", "true") for sdr in [bsdr, msdr]: sdr.writeSetting("TX_SW_DELAY", str(30)) replay_addr = 0 pilot1_ui32 = cfloat2uint32(pilot1) pilot2_ui32 = cfloat2uint32(pilot2) for sdr in [bsdr, msdr]: sdr.writeRegisters("TX_RAM_A", replay_addr, cfloat2uint32(pilot1).tolist()) sdr.writeRegisters("TX_RAM_B", replay_addr, cfloat2uint32(pilot2).tolist()) flags = 0 r1 = bsdr.activateStream(rxStreamB, flags, 0) r2 = msdr.activateStream(rxStreamM, flags, 0) if r1 < 0: print("Problem activating stream #1") if r2 < 0: print("Problem activating stream #2") bsdr.writeSetting("TRIGGER_GEN", "") r1 = msdr.readStream(rxStreamM, [waveRxA1, waveRxB1], symSamp) print("reading stream #1 ({})".format(r1)) r2 = bsdr.readStream(rxStreamB, [waveRxA2, waveRxB2], symSamp) print("reading stream #2 ({})".format(r2)) print("printing number of frames") print("NB {}".format(SoapySDR.timeNsToTicks(bsdr.getHardwareTime(""), rate))) print("UE {}".format(SoapySDR.timeNsToTicks(msdr.getHardwareTime(""), rate))) # ADC_rst, stops the tdd time counters, makes sure next time runs in a clean slate bsdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) bsdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) bsdr.writeRegister("IRIS30", RF_RST_REG, 0) msdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) msdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) msdr.writeRegister("IRIS30", RF_RST_REG, 0) for i in range(4): msdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 msdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 bsdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.closeStream(rxStreamM) bsdr.closeStream(rxStreamB) msdr = None bsdr = None fig = plt.figure(figsize=(20, 8), dpi=120) fig.subplots_adjust(hspace=.5, top=.85) ax1 = fig.add_subplot(2, 1, 1) ax1.grid(True) ax1.set_title('Serials: (%s, %s)' % (serial1, serial2)) ax1.set_ylabel('Signal (units)') ax1.set_xlabel('Sample index') ax1.plot(range(len(waveRxA1)), np.real(uint32tocfloat(waveRxA1)), label='ChA I Node 1') ax1.plot(range(len(waveRxB1)), np.real(uint32tocfloat(waveRxB1)), label='ChB I Node 1') ax1.set_ylim(-1, 1) ax1.set_xlim(0, symSamp) ax1.legend(fontsize=10) ax2 = fig.add_subplot(2, 1, 2) ax2.grid(True) ax2.set_ylabel('Signal (units)') ax2.set_xlabel('Sample index') ax2.plot(range(len(waveRxA2)), np.real(uint32tocfloat(waveRxA2)), label='ChA I Node 2') ax2.plot(range(len(waveRxB2)), np.real(uint32tocfloat(waveRxB2)), label='ChB I Node 2') ax2.set_ylim(-1, 1) ax2.set_xlim(0, symSamp) ax2.legend(fontsize=10) plt.show()
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
def siso_tdd_burst(serial1, serial2, rate, freq, txgain, rxgain, numSamps, prefix_pad, postfix_pad): bsdr = SoapySDR.Device(dict(driver='iris', serial=serial1)) msdr = SoapySDR.Device(dict(driver='iris', 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]: 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.setDCOffsetMode(SOAPY_SDR_RX, ch, True) sdr.writeSetting("SPI_TDD_MODE", "SISO") sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false') sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false') # TX_GAIN_CTRL and SYNC_DELAYS msdr.writeRegister("IRIS30", TX_GAIN_CTRL, 0) bsdr.writeSetting("SYNC_DELAYS", "") # Packet size symSamp = numSamps + prefix_pad + postfix_pad print("numSamps = %d" % numSamps) print("symSamps = %d" % symSamp) # Generate sinusoid to be TX Ts = 1 / rate s_freq = 1e5 s_time_vals = np.array(np.arange(0, numSamps)).transpose() * Ts pilot = np.exp(s_time_vals * 1j * 2 * np.pi * s_freq).astype( np.complex64) * 1 pad1 = np.array([0] * prefix_pad, np.complex64) pad2 = np.array([0] * postfix_pad, np.complex64) wbz = np.array([0] * symSamp, np.complex64) pilot1 = np.concatenate([pad1, pilot, pad2]) pilot2 = wbz # Initialize RX arrays waveRxA1 = np.array([0] * symSamp, np.uint32) waveRxB1 = np.array([0] * symSamp, np.uint32) waveRxA2 = np.array([0] * symSamp, np.uint32) waveRxB2 = np.array([0] * symSamp, np.uint32) # Create RX streams # CS16 makes sure the 4-bit lsb are samples are being sent rxStreamB = bsdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1]) rxStreamM = msdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1]) # Set Schedule bsched = "PGRG" msched = "RGPG" print("Node 1 schedule %s " % bsched) print("Node 2 schedule %s " % msched) # Send one frame (set mamx_frame to 1) bconf = { "tdd_enabled": True, "trigger_out": False, "symbol_size": symSamp, "frames": [bsched], "max_frame": 1 } mconf = { "tdd_enabled": True, "trigger_out": False, "dual_pilot": False, "symbol_size": symSamp, "frames": [msched], "max_frame": 1 } bsdr.writeSetting("TDD_CONFIG", json.dumps(bconf)) msdr.writeSetting("TDD_CONFIG", json.dumps(mconf)) # SW Delays for sdr in [bsdr, msdr]: sdr.writeSetting("TX_SW_DELAY", str(30)) msdr.writeSetting("TDD_MODE", "true") bsdr.writeSetting("TDD_MODE", "true") replay_addr = 0 for sdr in [bsdr, msdr]: sdr.writeRegisters("TX_RAM_A", replay_addr, cfloat2uint32(pilot1, order='IQ').tolist()) sdr.writeRegisters("TX_RAM_B", replay_addr, cfloat2uint32(pilot2, order='IQ').tolist()) flags = 0 r1 = bsdr.activateStream(rxStreamB, flags, 0) r2 = msdr.activateStream(rxStreamM, flags, 0) if r1 < 0: print("Problem activating stream #1") if r2 < 0: print("Problem activating stream #2") bsdr.writeSetting("TRIGGER_GEN", "") r1 = msdr.readStream(rxStreamM, [waveRxA1, waveRxB1], symSamp) print("reading stream #1 ({})".format(r1)) r2 = bsdr.readStream(rxStreamB, [waveRxA2, waveRxB2], symSamp) print("reading stream #2 ({})".format(r2)) print("printing number of frames") print("UE {}".format(SoapySDR.timeNsToTicks(msdr.getHardwareTime(""), rate))) print("NB {}".format(SoapySDR.timeNsToTicks(bsdr.getHardwareTime(""), rate))) # ADC_rst, stops the tdd time counters, makes sure next time runs in a clean slate bsdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) bsdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) bsdr.writeRegister("IRIS30", RF_RST_REG, 0) msdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) msdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) msdr.writeRegister("IRIS30", RF_RST_REG, 0) for i in range(4): msdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 msdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 bsdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.deactivateStream(rxStreamM) bsdr.deactivateStream(rxStreamB) msdr.closeStream(rxStreamM) bsdr.closeStream(rxStreamB) msdr = None bsdr = None fig = plt.figure(figsize=(20, 8), dpi=120) fig.subplots_adjust(hspace=.5, top=.85) ax1 = fig.add_subplot(2, 1, 1) ax1.grid(True) ax1.set_title('Serials: (%s, %s)' % (serial1, serial2)) ax1.set_ylabel('Signal (units)') ax1.set_xlabel('Sample index') ax1.plot(range(len(waveRxA1)), np.real(uint32tocfloat(waveRxA1)), label='ChA I Node 1') ax1.plot(range(len(waveRxB1)), np.real(uint32tocfloat(waveRxB1)), label='ChB I Node 1') ax1.set_ylim(-1, 1) ax1.set_xlim(0, symSamp) ax1.legend(fontsize=10) ax2 = fig.add_subplot(2, 1, 2) ax2.grid(True) ax2.set_ylabel('Signal (units)') ax2.set_xlabel('Sample index') ax2.plot(range(len(waveRxA2)), np.real(uint32tocfloat(waveRxA2)), label='ChA I Node 2') ax2.plot(range(len(waveRxB2)), np.real(uint32tocfloat(waveRxB2)), label='ChB I Node 2') ax2.set_ylim(-1, 1) ax2.set_xlim(0, symSamp) ax2.legend(fontsize=10) plt.show()
siso_bs.burn_data(beacon1_r, beacon1_i) #siso_bs.burn_beacon() siso_ue.burn_data(wb_pilot1_r, wb_pilot1_i) siso_bs.activate_stream_rx() siso_ue.set_corr() siso_bs.set_trigger(True) wave_rx_a_bs_mn = siso_bs.recv_stream_tdd() freq = 2.5e9 print("printing number of frames") print("BS 0x%X" % SoapySDR.timeNsToTicks(siso_bs.sdr.getHardwareTime(""), freq)) print("UE 0x%X" % SoapySDR.timeNsToTicks(siso_ue.sdr.getHardwareTime(""), freq)) siso_ue.close() siso_bs.close() #Test: plt.close('all') fig = plt.figure(figsize=(20, 8), dpi=100) ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2) ax1.plot(np.real(wb_pilot), label='pilot i') ax1.plot(np.imag(wb_pilot), label='pilot q') ax2.plot(np.real(wave_rx_a_bs_mn), label='rx data i') ax2.plot(np.imag(wave_rx_a_bs_mn), label='rx data q')
siso_bs.burn_beacon() siso_ue.burn_data(wb_pilot1_r, wb_pilot1_i) siso_bs.activate_stream_rx() siso_ue.set_corr() if hub is not None: hub.set_trigger() else: siso_bs.set_trigger() wave_rx_a_bs_mn = siso_bs.recv_stream_tdd() freq = args.freq print("printing number of frames") print("BS 0x%X" % SoapySDR.timeNsToTicks( siso_bs.sdr.getHardwareTime(""), freq)) print("UE 0x%X" % SoapySDR.timeNsToTicks( siso_ue.sdr.getHardwareTime(""), freq)) siso_ue.close() siso_bs.close() #Test: plt.close('all') fig = plt.figure(figsize=(20, 8), dpi=100) ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2) ax1.plot(np.real(wb_pilot), label='pilot i') ax1.plot(np.imag(wb_pilot), label='pilot q') ax2.plot(np.real(wave_rx_a_bs_mn), label='rx data i') ax2.plot(np.imag(wave_rx_a_bs_mn), label='rx data q')
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
def signal_handler(rate, numSyms, signal, frame): global bsdr, msdr, running, txStreamM, rxStreamB msdr.writeRegister( "IRIS30", CORR_CONF, 0 ) # stop mobile correlator first, to prevent from the tdd manager going msdr.writeRegister("IRIS30", TX_GAIN_CTRL, 0) # stop tx/rx threads running = False print("printing number of frames") print("NB 0x%X" % SoapySDR.timeNsToTicks(bsdr.getHardwareTime(""), rate)) print("UE 0x%X" % SoapySDR.timeNsToTicks(msdr.getHardwareTime(""), rate)) # print("UE SCNT: 0x%X" % msdr.readRegister("RFCORE", CORR_SCNT)) # ADC_rst, stops the tdd time counters for sdr in [bsdr, msdr]: sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) sdr.writeRegister("IRIS30", RF_RST_REG, 0) for i in range(numSyms): msdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 msdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", SCH_ADDR_REG, i) # subframe 0 bsdr.writeRegister("RFCORE", SCH_MODE_REG, 0) # 01 replay bsdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.writeRegister("RFCORE", TDD_CONF_REG, 0) msdr.writeSetting("TDD_MODE", "false") bsdr.writeSetting("TDD_MODE", "false") for i, sdr in enumerate([bsdr, msdr]): # Reset sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_ENABLE_FLAG, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_RESET_FLAG, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_RESET_FLAG, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_IQ_THRESH, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_NUM_SAMPS_SAT, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_MAX_NUM_SAMPS_AGC, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_WAIT_COUNT_THRESH, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_RSSI_TARGET, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_SMALL_JUMP, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_BIG_JUMP, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_TEST_GAIN_SETTINGS, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_THRESH, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NUM_SAMPS, 5) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_ENABLE, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 0) bsdr = None msdr = None if exit_plot: fig = plt.figure(figsize=(20, 8), dpi=100) ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2) pilot = uint32tocfloat( read_from_file("data_out/rxpilot_sounder", leng=256, offset=0)) rxdata = uint32tocfloat( read_from_file("data_out/rxdata_sounder", leng=256, offset=0)) ax1.plot(np.real(pilot), label='pilot i') ax1.plot(np.imag(pilot), label='pilot q') ax2.plot(np.real(rxdata), label='rx data i') ax2.plot(np.imag(rxdata), label='rx data q') plt.show() sys.exit(0)
def txrx_app(serials, ref_node_idx, hub_serial, rate, freq, txgain, rxgain, numSamps, prefix_pad, postfix_pad, debug): """ Function to configure Iris boards, generate pilot to be transmitted, write pilots to RAM, set up schedule (frame), transmit, and receive. """ serials_all = serials.copy() ref_serial = serials[ref_node_idx] serials.remove(ref_serial) # Get SDR objects (msdr: master SDR, ssdr: slave SDRs) ssdr = [SoapySDR.Device(dict(driver="iris", serial=serial)) for serial in serials] msdr = SoapySDR.Device(dict(driver="iris", serial=ref_serial)) if hub_serial != "": hub = SoapySDR.Device(dict(driver='faros', serial=hub_serial)) # eror flag flag = 0 # Some default sample rates for i, sdr in enumerate(ssdr + [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, '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.setGain(SOAPY_SDR_TX, ch, txgain) sdr.setGain(SOAPY_SDR_RX, ch, rxgain) sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX") sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True) # ADC_rst, stops the tdd time counters, makes sure next time runs in a clean slate sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) sdr.writeRegister("IRIS30", RF_RST_REG, 0) # Generate pilot to be TX # WiFi LTS Signal - Cyclic prefix of 32 lts_sym, lts_freq = generate_training_seq(preamble_type='lts', cp=32, upsample=1) pilot = np.tile(lts_sym, numSamps // len(lts_sym)).astype(complex) pilot = pilot / max(pilot) # Normalize amplitude pad1 = np.array([0] * prefix_pad, np.complex64) pad2 = np.array([0] * postfix_pad, np.complex64) pilot1 = np.concatenate([pad1, pilot, pad2]) pilot2 = np.array([0] * len(pilot1), np.complex64) # Packet size symSamp = len(pilot) + prefix_pad + postfix_pad print("num pilot samps = %d" % len(pilot)) print("num total samps = %d" % symSamp) # Synchronization delays if hub_serial != "": hub.writeSetting("SYNC_DELAYS", "") else: msdr.writeSetting("SYNC_DELAYS", "") # SW Delays [sdr.writeSetting("TX_SW_DELAY", str(30)) for sdr in (ssdr + [msdr])] # TDD Mode [sdr.writeSetting("TDD_MODE", "true") for sdr in (ssdr + [msdr])] # Write Pilot to RAM replay_addr = 0 [sdr.writeRegisters("TX_RAM_A", replay_addr, cfloat2uint32(pilot1, order='IQ').tolist()) for sdr in (ssdr + [msdr])] [sdr.writeRegisters("TX_RAM_B", replay_addr, cfloat2uint32(pilot2, order='IQ').tolist()) for sdr in (ssdr + [msdr])] # Set Schedule ref_sched = "PG" other_sched = "RG" frame_len = len(ref_sched) # Number of subframes (e.g., 3 if PGP, 4 if PGPG) num_rx_pilots = other_sched.count('R') # Two R's for "other" base station radios print("Ref node schedule %s " % ref_sched) print("Other nodes schedule %s " % other_sched) # Send one frame (set max_frame to 1) ref_conf = {"tdd_enabled": True, "trigger_out": False, "dual_pilot": False, "symbol_size": symSamp, "frames": [ref_sched], "max_frame": 1} other_conf = {"tdd_enabled": True, "trigger_out": False, "dual_pilot": False, "symbol_size": symSamp, "frames": [other_sched], "max_frame": 1} # Create RX streams # CS16 makes sure the 4-bit lsb are samples are being sent m_rxStream = msdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1], dict(WIRE=SOAPY_SDR_CS16)) s_rxStream = [sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1], dict(WIRE=SOAPY_SDR_CS16)) for sdr in ssdr] # Write TDD settings (schedule and parameters) msdr.writeSetting("TDD_CONFIG", json.dumps(ref_conf)) for i, sdr in enumerate(ssdr): sdr.writeSetting("TDD_CONFIG", json.dumps(other_conf)) # Begin pilot+calibration process: Send multiple pilots and pick the correlation index that occurs more frequently num_cal_tx = 100 num_ver_tx = 100 pass_thresh = 0.8*num_cal_tx # Aggregate over iterations (for calibration and for verification) waveRxA_agg = np.zeros((num_cal_tx, num_rx_pilots*(len(serials_all)-1), symSamp)) waveRxB_agg = np.zeros((num_cal_tx, num_rx_pilots*(len(serials_all)-1), symSamp)) waveRxA_ver = np.zeros((num_ver_tx, num_rx_pilots*(len(serials_all)-1), symSamp)) waveRxB_ver = np.zeros((num_ver_tx, num_rx_pilots*(len(serials_all)-1), symSamp)) for idx in range(num_cal_tx+num_ver_tx): # Initialize RX arrays # All nodes except ref. Assume num_rx_pilots entries for each node, regardless of whether we use them or not waveRxA = [np.array([0] * symSamp, np.uint32) for i in range(num_rx_pilots) for j in range(len(ssdr))] waveRxB = [np.array([0] * symSamp, np.uint32) for i in range(num_rx_pilots) for j in range(len(ssdr))] dummyA = np.array([0] * symSamp, np.uint32) dummyB = np.array([0] * symSamp, np.uint32) # Activate streams flags = 0 r1 = msdr.activateStream(m_rxStream, flags, 0) if r1 < 0: print("Problem activating RefNode stream (Node0)") for i, sdr in enumerate(ssdr): r2 = sdr.activateStream(s_rxStream[i], flags, 0) if r2 < 0: print("Problem activating stream at RxNode #{}".format(i+1)) # Drain buffers for i, sdr in enumerate([msdr] + ssdr): valid = 0 while valid is not -1: if i == 0: r0 = sdr.readStream(m_rxStream, [dummyA, dummyB], symSamp) else: r0 = sdr.readStream(s_rxStream[i-1], [dummyA, dummyB], symSamp) valid = r0.ret if debug: print("draining buffers: ({}). Board: {}".format(r0, i)) # Generate trigger if hub_serial != "": hub.writeSetting("TRIGGER_GEN", "") else: msdr.writeSetting("TRIGGER_GEN", "") # Read Streams # B0 <-- B1 (NOT REALLY NEEDED WITH THE CURRENT SCHEDULE) # curr_rx_idx = 0 # r1 = msdr.readStream(m_rxStream, [waveRxA[curr_rx_idx], waveRxB[curr_rx_idx]], symSamp) # print("reading stream ref antenna: ({})".format(r1)) curr_rx_idx = 0 for i, sdr in enumerate(ssdr): for j in range(num_rx_pilots): r1 = sdr.readStream(s_rxStream[i], [waveRxA[curr_rx_idx], waveRxB[curr_rx_idx]], symSamp) curr_rx_idx = curr_rx_idx + 1 if debug: print("reading stream non-reference nodes: ({})".format(r1)) # Timestamps if debug: print("Timestamps:") for sdr in ([msdr] + ssdr): print(hex(SoapySDR.timeNsToTicks(sdr.getHardwareTime(""), rate))) waveRxA = uint32tocfloat(waveRxA) waveRxB = uint32tocfloat(waveRxB) if idx < num_cal_tx: waveRxA_agg[idx, :, :] = waveRxA waveRxB_agg[idx, :, :] = waveRxB if idx == num_cal_tx-1: # Find correlation indexes idx_mat_cal = find_corr_idx(waveRxA_agg, waveRxB_agg) # Find most common value at each board most_freq = np.zeros(idx_mat_cal.shape[1]) num_occurr = np.zeros(idx_mat_cal.shape[1]) for colIdx in range(idx_mat_cal.shape[1]): occurr_cnt = Counter(idx_mat_cal[:, colIdx]) most_freq[colIdx] = (occurr_cnt.most_common(1))[0][0] num_occurr[colIdx] = (occurr_cnt.most_common(1))[0][1] # Re-assign corr_idx_vec_cal = most_freq # Check if we didn't meet "PASSING" threshold (i.e., confidence on rx pilots) if any(num_occurr < pass_thresh): cleanup([msdr] + ssdr, frame_len, m_rxStream, s_rxStream) flag = -1 return flag, corr_idx_vec_cal, idx_mat_cal, num_occurr # Perform calibration cal_coeff = calibrate(most_freq, ssdr) elif idx >= num_cal_tx: waveRxA_ver[idx-num_cal_tx, :, :] = waveRxA waveRxB_ver[idx-num_cal_tx, :, :] = waveRxB if idx == num_cal_tx + num_ver_tx - 1: # Find correlation indexes idx_mat = find_corr_idx(waveRxA_ver, waveRxB_ver) idx_mat_ver = idx_mat # Find most common value at each board most_freq = np.zeros(idx_mat_ver.shape[1]) num_occurr = np.zeros(idx_mat_ver.shape[1]) for colIdx in range(idx_mat_ver.shape[1]): occurr_cnt = Counter(idx_mat_ver[:, colIdx]) most_freq[colIdx] = (occurr_cnt.most_common(1))[0][0] num_occurr[colIdx] = (occurr_cnt.most_common(1))[0][1] # Re-assign corr_idx_vec_ver = most_freq cleanup([msdr] + ssdr, frame_len, m_rxStream, s_rxStream) return flag, corr_idx_vec_cal, corr_idx_vec_ver, cal_coeff