def set_python_log_handler(exception_level=None): """Replace the default SoapySDR log handler with a Python one. The python handler sends the log text to stderr. If the log_level is at exception_level or worse then a SoapyException is thrown. """ log_level_text = { SOAPY_SDR_FATAL: "FATAL", SOAPY_SDR_CRITICAL: "CRITICAL", SOAPY_SDR_ERROR: "ERROR", SOAPY_SDR_WARNING: "WARNING", SOAPY_SDR_NOTICE: "NOTICE", SOAPY_SDR_INFO: "INFO", SOAPY_SDR_DEBUG: "DEBUG", SOAPY_SDR_TRACE: "TRACE", SOAPY_SDR_SSI: "SSI"} def log_handler(log_level, message): level_text = log_level_text[log_level] log_text = "[{}] {}".format(level_text, message) print(log_text, file=sys.stderr) if exception_level is not None and log_level <= exception_level: raise SoapyException(log_text) SoapySDR.registerLogHandler(log_handler)
import SoapySDR from SoapySDR import * #SOAPY_SDR_* constants import numpy as np import time if __name__ == '__main__': streamBoardSDR = SoapySDR.Device({"driver": "lime"}) print("Pick sample rates") streamBoardSDR.setSampleRate(SOAPY_SDR_RX, 0, 13e6 / 48) streamBoardSDR.setSampleRate(SOAPY_SDR_TX, 0, 13e6 / 12) print 'Results...' print 'Rx', streamBoardSDR.getSampleRate(SOAPY_SDR_RX, 0) / 1e6, "MHz" print 'Tx', streamBoardSDR.getSampleRate(SOAPY_SDR_TX, 0) / 1e6, "MHz" print 'CGEN', streamBoardSDR.getMasterClockRate() / 1e6, "MHz"
def main(args): # Create an SDR device instance try: sdr = SoapySDR.Device(dict(driver="lime")) except: sys.stderr.write("Failed to create an SDR device instance.\n") return False if not sdr: sys.stderr.write("Could not find any SDR devices.\n") return False # Setup the Rx channel 0 sdr.setSampleRate(SoapySDR.SOAPY_SDR_RX, 0, args.sample_rate) sdr.setBandwidth(SoapySDR.SOAPY_SDR_RX, 0, args.bandwidth) sdr.setAntenna(SoapySDR.SOAPY_SDR_RX, 0, "LNAW") sdr.setGain(SoapySDR.SOAPY_SDR_RX, 0, 30.0) sdr.setFrequency(SoapySDR.SOAPY_SDR_RX, 0, args.rf) # Setup an Rx stream rxStream = sdr.setupStream(SoapySDR.SOAPY_SDR_RX, SoapySDR.SOAPY_SDR_CF32, [0]) # Activate the stream sdr.activateStream(rxStream) # Check the maximum transmit unit mtu = sdr.getStreamMTU(rxStream) # Prepare a receive buffer rxBuffer = np.zeros(mtu, np.complex64) prevSamples = np.array([], dtype=np.complex64) while True: # Receive samples status = sdr.readStream(rxStream, [rxBuffer], rxBuffer.size) if status.ret != rxBuffer.size: sys.stderr.write( "Failed to receive samples in readStream(): {}\n".format( status.ret)) return False # Concatenate the previous samples and the current samples samples = np.concatenate([prevSamples, rxBuffer]) # Calculate angles from previous symbols cur = samples[args.samples_per_symbol:] # current symbols prev = samples[0:-args.samples_per_symbol] # previous symbols prev = np.where(prev == 0, prev + 1e-9, prev) # to avoid zero division x = cur / prev diffAngles = np.arctan2(x.imag, x.real) # Check if the preamble is included if np.sum(np.absolute(diffAngles) > math.pi / 2) >= 8 * args.samples_per_symbol: # Concatenate two sample buffers samples = np.copy(rxBuffer) status = sdr.readStream(rxStream, [rxBuffer], rxBuffer.size) if status.ret != rxBuffer.size: sys.stderr.write( "Failed to receive samples in readStream(): {}\n".format( status.ret)) return False samples = np.concatenate([samples, rxBuffer]) if demodulate(samples, args.samples_per_symbol): break prevSamples = np.copy(rxBuffer) # Deactivate and close the stream sdr.deactivateStream(rxStream) sdr.closeStream(rxStream)
def __init__( self, serial_id=None, tx_freq=None, rx_freq=None, tx_gain=None, rx_gain=None, bw=None, sample_rate=None, n_samp=None, # Total number of samples, including zero-pads n_zpad_samp=150, # Total number of samples used for zero-padding in prefix and postfix max_frames=1, # Number of frames TXed: How many times the schedule will be repeated both_channels=False, agc_en=False, ): if serial_id is not None: self.sdr = SoapySDR.Device(dict(driver="iris", serial=serial_id)) self.serial_id = serial_id else: self.sdr = None self.sample_rate = sample_rate if n_samp is not None: self.n_samp = int(n_samp) self.agc_en = agc_en self.both_channels = both_channels self.n_zpad_samp = int(n_zpad_samp) self.max_frames = int(max_frames) # PACKET DETECT SETUP self.sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_THRESH, 0) self.sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NUM_SAMPS, 5) self.sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_ENABLE, 0) self.sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 0) ### Setup channel rates, ports, gains, and filters ### info = self.sdr.getHardwareInfo() for chan in [0, 1]: #Tx: if sample_rate is not None: self.sdr.setSampleRate(SOAPY_SDR_TX, chan, sample_rate) if bw is not None: self.sdr.setBandwidth(SOAPY_SDR_TX, chan, bw) else: self.sdr.setBandwidth(SOAPY_SDR_TX, chan, 2.5 * sample_rate) if tx_gain is not None: self.sdr.setGain(SOAPY_SDR_TX, chan, tx_gain) if tx_freq is not None: self.sdr.setFrequency(SOAPY_SDR_TX, chan, 'RF', tx_freq - .75 * sample_rate) self.sdr.setFrequency(SOAPY_SDR_TX, chan, 'BB', .75 * sample_rate) #print("Set TX frequency to %f" % self.sdr.getFrequency(SOAPY_SDR_TX, chan)) #self.sdr.setAntenna(SOAPY_SDR_TX, chan, "TRX") self.sdr.setGain(SOAPY_SDR_TX, chan, 'IAMP', 12) #[0,12] self.sdr.setGain(SOAPY_SDR_TX, chan, 'PAD', tx_gain) #[-52,0] #Rx: if sample_rate is not None: self.sdr.setSampleRate(SOAPY_SDR_RX, chan, sample_rate) if bw is not None: self.sdr.setBandwidth(SOAPY_SDR_RX, chan, bw) else: self.sdr.setBandwidth(SOAPY_SDR_RX, chan, 2.5 * sample_rate) if rx_gain is not None: self.sdr.setGain(SOAPY_SDR_RX, chan, rx_gain) if rx_freq is not None: self.sdr.setFrequency(SOAPY_SDR_RX, chan, 'RF', rx_freq - .75 * sample_rate) self.sdr.setFrequency(SOAPY_SDR_RX, chan, 'BB', .75 * sample_rate) self.sdr.setAntenna(SOAPY_SDR_RX, chan, "TRX") if self.agc_en: self.sdr.setGain(SOAPY_SDR_RX, chan, 'LNA', 30) # [0,30] self.sdr.setGain(SOAPY_SDR_RX, chan, 'TIA', 12) # [0,12] self.sdr.setGain(SOAPY_SDR_RX, chan, 'PGA', 19) # [-12,19] else: self.sdr.setGain(SOAPY_SDR_RX, chan, 'LNA', rx_gain) #[0,30] self.sdr.setGain(SOAPY_SDR_RX, chan, 'TIA', 0) #[0,12] self.sdr.setGain(SOAPY_SDR_RX, chan, 'PGA', 0) #[-12,19] self.sdr.setDCOffsetMode(SOAPY_SDR_RX, chan, True) if ("CBRS" in info["frontend"]): #Tx: self.sdr.setGain(SOAPY_SDR_TX, chan, 'ATTN', 0) #[-18,0] by 3 self.sdr.setGain(SOAPY_SDR_TX, chan, 'PA1', 15) #[0|15] self.sdr.setGain(SOAPY_SDR_TX, chan, 'PA2', 0) #[0|15] self.sdr.setGain(SOAPY_SDR_TX, chan, 'PA3', 30) #[0|30] #Rx: self.sdr.setGain(SOAPY_SDR_RX, chan, 'ATTN', -18) #[-18,0] self.sdr.setGain(SOAPY_SDR_RX, chan, 'LNA1', 30) #[0,33] self.sdr.setGain(SOAPY_SDR_RX, chan, 'LNA2', 17) #[0,17] self.tx_stream = None # Burst mode self.sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29) | 0x1) self.sdr.writeRegister("IRIS30", RF_RST_REG, (1 << 29)) self.sdr.writeRegister("IRIS30", RF_RST_REG, 0) if not self.both_channels: self.sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false') self.sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false')
import numpy as np import os import SoapySDR from SoapySDR import * from util import simulation # soapysdr is not on pip, it is a python binding to a c++ library soapy1 = SoapySDR.Device_enumerate()[-1] #class Simulated: # def __init__(self, name='receiver'): # self.name = name # self.sim = simulation(name) # self.tuner = Simulated.Tuner(self, name + '_tuner') # def enable(self): # def disable(self): # self.sim = None # def read(self): # return self.sim.read() # class Tuner: # def __init__(self, fn): # self.sim = simulation(name) # self.last = self.sim.read() class Receiver: def __init__(self, soapy_device_data=soapy1,
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, 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) # sdr.setGain(SOAPY_SDR_TX, ch, txgain) # txgain: at 2.5GHz [16:1:93], at 3.6GHz [15:1:102] # sdr.setGain(SOAPY_SDR_RX, ch, rxgain) # rxgain: at 2.5GHz [3:1:105], at 3.6GHz [3:1:102] # else: # No CBRS board gains, only changing LMS7 gains sdr.setGain(SOAPY_SDR_TX, ch, "PAD", txgain) # [0:1:42] txgain sdr.setGain(SOAPY_SDR_TX, ch, "ATTN", -6) sdr.setGain(SOAPY_SDR_RX, ch, "LNA", rxgain) # [0:1:30] rxgain sdr.setGain(SOAPY_SDR_RX, ch, "LNA2", 14) sdr.setGain(SOAPY_SDR_RX, ch, "ATTN", 0 if freq > 3e9 else -18) # SYNC_DELAYS 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, "frame_mode": "free_running", "symbol_size": symSamp, "frames": [bsched], "max_frame": 1} mconf = {"tdd_enabled": True, "frame_mode": "free_running", "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") for sdr in [bsdr, msdr]: sdr.writeRegisters("TX_RAM_A", 0, cfloat2uint32(pilot1, order='QI').tolist()) sdr.writeRegisters("TX_RAM_B", 0, cfloat2uint32(pilot2, order='QI').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)) # ADC_rst, stops the tdd time counters, makes sure next time runs in a clean slate 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") 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()
def __init__( self, serial_id=None, tx_freq=None, rx_freq=None, tx_gain=None, rx_gain=None, bw=None, sample_rate=None, n_samp=None, # Total number of samples, including zero-pads both_channels=False, agc_en=False, ): if serial_id is not None: self.sdr = SoapySDR.Device( dict(driver="iris", timeout="1000000", serial=serial_id)) self.serial_id = serial_id else: self.sdr = None self.sample_rate = sample_rate if n_samp is not None: self.n_samp = int(n_samp) self.agc_en = agc_en self.both_channels = both_channels self.max_frames = 1 ### Setup channel rates, ports, gains, and filters ### info = self.sdr.getHardwareInfo() for chan in [0, 1]: #Tx: if sample_rate is not None: self.sdr.setSampleRate(SOAPY_SDR_TX, chan, sample_rate) if bw is not None: self.sdr.setBandwidth(SOAPY_SDR_TX, chan, bw) else: self.sdr.setBandwidth(SOAPY_SDR_TX, chan, 2.5 * sample_rate) if tx_gain is not None: self.sdr.setGain(SOAPY_SDR_TX, chan, min(tx_gain, 81.0)) if tx_freq is not None: self.sdr.setFrequency(SOAPY_SDR_TX, chan, 'RF', tx_freq - .75 * sample_rate) self.sdr.setFrequency(SOAPY_SDR_TX, chan, 'BB', .75 * sample_rate) #print("Set TX frequency to %f" % self.sdr.getFrequency(SOAPY_SDR_TX, chan)) #self.sdr.setAntenna(SOAPY_SDR_TX, chan, "TRX") #self.sdr.setGain(SOAPY_SDR_TX, chan, 'ATTN', -6) #Rx: if sample_rate is not None: self.sdr.setSampleRate(SOAPY_SDR_RX, chan, sample_rate) if bw is not None: self.sdr.setBandwidth(SOAPY_SDR_RX, chan, bw) else: self.sdr.setBandwidth(SOAPY_SDR_RX, chan, 2.5 * sample_rate) if rx_gain is not None: self.sdr.setGain(SOAPY_SDR_RX, chan, rx_gain) if rx_freq is not None: self.sdr.setFrequency(SOAPY_SDR_RX, chan, 'RF', rx_freq - .75 * sample_rate) self.sdr.setFrequency(SOAPY_SDR_RX, chan, 'BB', .75 * sample_rate) self.sdr.setAntenna(SOAPY_SDR_RX, chan, "TRX") if self.agc_en: self.sdr.setGain(SOAPY_SDR_RX, chan, 100) # high gain value else: self.sdr.setGain(SOAPY_SDR_RX, chan, rx_gain) self.sdr.setDCOffsetMode(SOAPY_SDR_RX, chan, True) self.tx_stream = None # Burst mode self.sdr.writeSetting("RESET_DATA_LOGIC", "") if not self.both_channels: self.sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false') self.sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false')
if __name__ == '__main__': app = QApplication(sys.argv) parser = argparse.ArgumentParser() parser.add_argument("--args", help="Device arguments (or none for selection dialog)") parser.add_argument("--file", help="Load saved config when specified") args = parser.parse_args() handle = args.args settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "Skylark", "IrisControlGUI") if not handle: dialog = DeviceSelectionDialog(settings=settings) dialog.exec() handle = dialog.deviceHandle() else: handle = SoapySDR.Device.enumerate(handle)[0] if not handle: print('No device selected!') sys.exit(-1) iris = SoapySDR.Device(handle) w = MainWindow(iris=iris, settings=settings, handle=handle) w.show() if args.file: w.loadFile(args.file) sys.exit(app.exec_())
def siggen_app( args, rate, waves, ampl=0.7, freq=None, txBw=None, txChan=0, rxChan=0, txGain=None, txAnt=None, clockRate=None, waveFreq=None, ): if waveFreq is None: waveFreq = rate / 10 sdr = SoapySDR.Device(args) #set clock rate first if clockRate is not None: sdr.setMasterClockRate(clockRate) #set sample rate sdr.setSampleRate(SOAPY_SDR_TX, txChan, rate) print("Actual Tx Rate %f Msps" % (sdr.getSampleRate(SOAPY_SDR_TX, txChan) / 1e6)) #set bandwidth if txBw is not None: sdr.setBandwidth(SOAPY_SDR_TX, txChan, txBw) #set antenna print("Set the antenna") if txAnt is not None: sdr.setAntenna(SOAPY_SDR_TX, txChan, txAnt) #set overall gain print("Set the gain") if txGain is not None: sdr.setGain(SOAPY_SDR_TX, txChan, txGain) #tune frontends print("Tune the frontend") if freq is not None: sdr.setFrequency(SOAPY_SDR_TX, txChan, freq) print("Waveform:" + waves) #tx loop #create tx stream print("Create Tx stream") txStream = sdr.setupStream(SOAPY_SDR_TX, "CF32", [txChan]) print("Activate Tx Stream") sdr.activateStream(txStream) phaseAcc = 0 #phaseInc = 2*math.pi*waveFreq/rate phaseInc = math.pi / 4 * waveFreq / rate streamMTU = sdr.getStreamMTU(txStream) sampsCh0 = np.array([ampl] * streamMTU, np.complex64) print streamMTU timeLastPrint = time.time() totalSamps = 0 #phaseAccNext = streamMTU*phaseInc #phaseAcc = phaseAccNext #testSpace = np.pi/4*np.linspace(0,streamMTU-1) while True: phaseAccNext = phaseAcc + streamMTU * phaseInc if waves == "sine": sampsCh0 = ampl * np.exp(1j * np.linspace( phaseAcc, phaseAccNext, streamMTU)).astype(np.complex64) #sampsCh0 = ampl*np.exp(1j*testSpace).astype(np.complex64) elif waves == "pulse": n = len(sampsCh0) a = np.zeros(n) l = .25 a[:int(l * n)] = 1 a[-int(l * n):] = 1 sampsCh0 = np.fft.ifft(a) elif waves == "zeros": sampsCh0 = np.zeros(len(sampsCh0)) phaseAcc = phaseAccNext while phaseAcc > math.pi * 2: phaseAcc -= math.pi * 2 #while phaseAcc > math.pi*2: phaseAcc -= math.pi #phaseAcc %= math.pi*2 # plt.plot(sampsCh0) # plt.show() sr = sdr.writeStream(txStream, [sampsCh0], len(sampsCh0)) if sr.ret != sampsCh0.size: raise Exception( "Expected writeStream() to consume all samples! %d" % sr.ret) totalSamps += sr.ret if time.time() > timeLastPrint + 5.0: print("Python siggen rate: %f Msps" % (totalSamps / (time.time() - timeLastPrint) / 1e6)) totalSamps = 0 timeLastPrint = time.time() #cleanup streams print("Cleanup stream") sdr.deactivateStream(txStream) sdr.closeStream(txStream) print("Done!")
# Read transmit buffer from stdin pulseFile = open("skylark_transmit.txt", 'r') for line in pulseFile: input_interleaved = np.fromstring(line, dtype=np.float32, count=-1, sep=' ') sigLength = int(len(input_interleaved) / 2) interleavedValues = input_interleaved.reshape((sigLength, 2)) realSamples = interleavedValues[:, 0] imagSamples = interleavedValues[:, 1] inputbuffer = realSamples + 1j * imagSamples num_samps = num_pulses*len(inputbuffer) print(num_samps) from pulseDopplerTxRx import MIMO_SDR sdrs = [SoapySDR.Device(dict(driver="uhd", serial = serial)) for serial in serials] for serial in serials: print(serial) # SoapySDR.Device(dict(driver="iris", serial = serial)) tx_sdrs = sdrs[0:len(sdrs)//2] rx_sdrs = sdrs[len(sdrs)//2:] trig_sdr = sdrs[0] print("Using %i tx USRP and %i rx USRP." % (len(tx_sdrs), len(rx_sdrs)) ) #override default settings for sdr in sdrs: for chan in [0]: sdr.setSampleRate(SOAPY_SDR_RX, chan, rate)
def siso_sounder(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)) # 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: bsdr.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)) 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() 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 __init__(self, cent_freq, meas_time, rx_bw, fs, channel): #rx_bw - bandwidth, fs - sampling rate self.channel = channel use_agc = True # Use or don't use the AGC self.freq = cent_freq # LO tuning frequency in Hz self.timeout_us = int(5e6) self.N = int(fs * meas_time) # Number of complex samples per transfer self.rx_bits = 12 # The Lime's ADC is 12 bits RX1 = 0 # RX1 = 0, RX2 = 1 RX2 = 1 self.sdr = SoapySDR.Device( dict(driver="lime")) # Create AIR-T instance if (len(self.channel) == 2): self.sdr.setSampleRate(SOAPY_SDR_RX, RX1, fs) # Set sample rate self.sdr.setSampleRate(SOAPY_SDR_RX, RX2, fs) self.sdr.setGainMode(SOAPY_SDR_RX, RX1, True) # Set the gain mode self.sdr.setGainMode(SOAPY_SDR_RX, RX2, True) self.sdr.setGain(SOAPY_SDR_RX, RX1, "TIA", 0) # Set TransImpedance Amplifier gain self.sdr.setGain(SOAPY_SDR_RX, RX2, "TIA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX1, "LNA", 0) # Set Low-Noise Amplifier gain self.sdr.setGain(SOAPY_SDR_RX, RX2, "LNA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX1, "PGA", 0) # programmable-gain amplifier (PGA) self.sdr.setGain(SOAPY_SDR_RX, RX2, "PGA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX1, 0) self.sdr.setGain(SOAPY_SDR_RX, RX2, 0) self.sdr.setDCOffsetMode(SOAPY_SDR_RX, 0, False) self.sdr.setDCOffsetMode(SOAPY_SDR_RX, 1, False) self.sdr.setFrequency(SOAPY_SDR_RX, RX1, self.freq) # Tune the LO self.sdr.setFrequency(SOAPY_SDR_RX, RX2, self.freq) # Tune the LO self.RX1_buff = np.empty( 2 * self.N, np.int16) # Create memory buffer for data stream self.RX2_buff = np.empty( 2 * self.N, np.int16) # Create memory buffer for data stream self.sdr.setBandwidth(SOAPY_SDR_RX, RX1, rx_bw) self.sdr.setBandwidth(SOAPY_SDR_RX, RX2, rx_bw) self.sdr.setAntenna(SOAPY_SDR_RX, RX1, "LNAL") self.sdr.setAntenna(SOAPY_SDR_RX, RX2, "LNAL") # Create data buffer and start streaming samples to it self.rx_stream = self.sdr.setupStream( SOAPY_SDR_RX, SOAPY_SDR_CS16, [RX1, RX2]) # Setup data stream elif (self.channel[0] == 1): self.sdr.setSampleRate(SOAPY_SDR_RX, RX1, fs) # Set sample rate self.sdr.setGainMode(SOAPY_SDR_RX, RX1, True) # Set the gain mode self.sdr.setGain(SOAPY_SDR_RX, RX1, "TIA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX1, "LNA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX1, "PGA", 0) # programmable-gain amplifier (PGA) self.sdr.setFrequency(SOAPY_SDR_RX, RX1, self.freq) # Tune the LO self.RX1_buff = np.empty( 2 * self.N, np.int16) # Create memory buffer for data stream self.sdr.setBandwidth(SOAPY_SDR_RX, RX1, rx_bw) self.sdr.setAntenna(SOAPY_SDR_RX, RX1, "LNAL") self.rx_stream = self.sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [RX1]) # Setup data stream elif (self.channel[0] == 2): self.sdr.setSampleRate(SOAPY_SDR_RX, RX2, fs) # Set sample rate self.sdr.setGainMode(SOAPY_SDR_RX, RX2, True) # Set the gain mode self.sdr.setGain(SOAPY_SDR_RX, RX2, "TIA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX2, "LNA", 0) self.sdr.setGain(SOAPY_SDR_RX, RX2, "PGA", 0) # programmable-gain amplifier (PGA) self.sdr.setFrequency(SOAPY_SDR_RX, RX2, self.freq) # Tune the LO self.RX2_buff = np.empty( 2 * self.N, np.int16) # Create memory buffer for data stream self.sdr.setBandwidth(SOAPY_SDR_RX, RX2, rx_bw) self.sdr.setAntenna(SOAPY_SDR_RX, RX2, "LNAL") self.rx_stream = self.sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [RX2]) # Setup data stream else: print("Channel amount has to be 1 or 2")
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") 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 siso_sounder(serial1, serial2, rate, freq, txgain, rxgain, numSamps, numSyms, txSymNum, threshold, tx_advance, prefix_length, postfix_length, both_channels, wait_trigger, calibrate, record, use_trig, auto_tx_gain, 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)) for i, sdr in enumerate([bsdr, msdr]): # AGC SETUP (Init) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_ENABLE_FLAG, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_RESET_FLAG, 1) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_RESET_FLAG, 0) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_IQ_THRESH, 10300) # 10300 about -6dBm sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_NUM_SAMPS_SAT, 3) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_MAX_NUM_SAMPS_AGC, 20) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_WAIT_COUNT_THRESH, 160) # gain settle takes about 20 samps (val=20) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_RSSI_TARGET, 14) # ideally around 14 sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_SMALL_JUMP, 5) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_BIG_JUMP, 15) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_TEST_GAIN_SETTINGS, 0) # PACKET DETECT SETUP 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) # 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] # LMS gains if agc_en: # Set gains to max (initially) sdr.setGain(SOAPY_SDR_RX, ch, 'LNA', 30) # [0,30] sdr.setGain(SOAPY_SDR_RX, ch, 'TIA', 12) # [0,12] sdr.setGain(SOAPY_SDR_RX, ch, 'PGA', 19) # [-12,19] else: 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', -10) # [-12,19] sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX") sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True) # 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(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: #GM #msdr.writeRegister("ARGCOR", CORR_RST, 0x1) # reset corr msdr.writeRegister("RFCORE", 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]) for i, sdr in enumerate([bsdr, msdr]): # ENABLE PKT DETECT AND AGC sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_ENABLE, agc_en) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_ENABLE_FLAG, agc_en) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 1) sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 0) # 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 = 1 beacon = preambles[0, :] * ampl 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) 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 = "GRP" + ''.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) # [15] en, [14] mode, [13:12] step, [11:6] stop, [5:0] start msdr.writeRegister("IRIS30", TX_GAIN_CTRL, gain_reg) # 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)) # make sure to set this after TDD mode is enabled "writeSetting("TDD_CONFIG", ..." msdr.setHardwareTime( SoapySDR.ticksToTimeNs((sf_start << 16) | sp_start, rate), "TRIGGER") 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()
def rxsamples_app(args, srl, freq, bw, rxgain, clockRate, out): global sdr, rxStream, timeScale, sampsRx, freqScale, rate, num_samps, fft_size, threadT, agc_fsm sdr = SoapySDR.Device(dict(serial=srl)) info = sdr.getHardwareInfo() ch = rxChan # RSSI read setup setUpDigitalRssiMode(sdr) # Instantiate AGC FSM and enable agc_fsm = AutomaticGainControl(sdr, ch) # Enable AGC and trigger AGC state machine threadT = threading.Thread(target=agc_thread) # , args=(sampsRx,)) # set clock rate first if clockRate is None: sdr.setMasterClockRate(rate * 8) else: sdr.setMasterClockRate(clockRate) if bw is not None: sdr.setBandwidth(SOAPY_SDR_RX, ch, bw) # set params on both channels # sdr.setBandwidth(SOAPY_SDR_RX, ch, 10e6) sdr.setSampleRate(SOAPY_SDR_RX, ch, rate) sdr.setFrequency(SOAPY_SDR_RX, ch, "RF", freq) sdr.setFrequency(SOAPY_SDR_RX, ch, "BB", 0) # don't use cordic sdr.setGain(SOAPY_SDR_RX, ch, rxgain) # w/CBRS 3.6GHz [0:105], 2.5GHZ [0:108] sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX") sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True) sdr.setHardwareTime(0) print("Set Frequency to %f" % sdr.getFrequency(SOAPY_SDR_RX, 0)) # setup rxStreaming # request an rx burst as an example # repeat activateStream and readStream() for each burst needed sdr.writeSetting(SOAPY_SDR_RX, 0, 'CALIBRATE', 'SKLK') rxStream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0], {}) # cleanup rxStream # print("Cleanup rxStreams") # sdr.deactivateStream(rxStream) # sdr.closeStream(rxStream) step = 1 print("numSamps %d " % num_samps) timeScale = np.arange(0, num_samps * step, num_samps) sampsRx = [ np.zeros(num_samps, np.complex64), np.zeros(num_samps, np.complex64) ] # Start AGC thread threadT.start() #anim = animation.FuncAnimation(fig, animate, init_func=init, # frames=100, interval=100, blit=True) anim = MyFuncAnimation(fig, animate, init_func=init, frames=100, interval=100, blit=True) plt.show() if out is not None: fig.savefig(out) plt.close(fig)
def siggen_app(args, rate, ampl, ant, gain, freq, bbfreq, waveFreq, numSamps, serial1, serial2, sigType, lo_tone): """ Generate signal and write stream to RAM for TX """ global sdr # Device information sdr = SoapySDR.Device(dict(serial=serial)) info = sdr.getHardwareInfo() amplFixed = int(ampl * (1 << 13)) if ant == 'A': txChannel = [0] elif ant == 'B': txChannel = [1] elif ant == 'AB': txChannel = [0, 1] else: txChannel = [] # Settings for c in txChannel: print("Writing settings for channel {}".format(c)) sdr.setBandwidth(SOAPY_SDR_TX, c, 2.5 * rate) sdr.setSampleRate(SOAPY_SDR_TX, c, rate) sdr.setFrequency(SOAPY_SDR_TX, c, "RF", freq - .75 * rate) sdr.setFrequency(SOAPY_SDR_TX, c, "BB", .75 * rate) #sdr.setFrequency(SOAPY_SDR_TX, c, "RF", freq+bbfreq) #sdr.setFrequency(SOAPY_SDR_TX, c, "BB", bbfreq) sdr.setAntenna(SOAPY_SDR_TX, c, "TRX") if lo_tone: sdr.writeSetting(SOAPY_SDR_TX, c, 'TSP_TSG_CONST', str(amplFixed)) sdr.writeSetting(SOAPY_SDR_TX, c, 'TX_ENB_OVERRIDE', 'true') if "CBRS" in info["frontend"]: sdr.setGain(SOAPY_SDR_TX, c, gain) else: # No CBRS board gains, only changing LMS7 gains sdr.setGain(SOAPY_SDR_TX, c, "PAD", gain) # [0:1:42] sdr.setGain(SOAPY_SDR_TX, c, "IAMP", 0) # [-12:1:3] # Generate TX signal txSignal = np.empty(numSamps).astype(np.complex64) wbz = txSignal if sigType == "LTE": # LTE signal for i in range(numSamps): txSignal[i] = np.complex(LTE5_re.lte5i[i] / 32768.0, LTE5_im.lte5q[i] / 32768.0) elif sigType == "LTS": # WiFi LTS Signal ltsSym, lts_f = generate_training_seq(preamble_type='lts', cp=32, upsample=1) txSignal = np.tile(ltsSym, numSamps // len(ltsSym)).astype( np.complex64) * ampl elif sigType == "STS": # WiFi STS Signal stsSym = generate_training_seq(preamble_type='sts', reps=10) txSignal = np.tile(stsSym, numSamps // len(stsSym)).astype( np.complex64) * 5 elif sigType == "SINE": # Sine Waveform Ts = 1 / rate if waveFreq is None: waveFreq = rate / 20 x = 20 numSamps = int(x * rate / waveFreq) # x period worth of samples s_freq = waveFreq s_time_vals = np.array(np.arange(0, numSamps)).transpose() * Ts txSignal = np.exp(s_time_vals * 1j * 2 * np.pi * s_freq).astype( np.complex64) * ampl if bbfreq > 0: txSignal = np.array([0] * numSamps, np.complex64) # use with cordic txSignal += .1 else: raise Exception( "Signal type not supported. Valid entries: LTE/LTS/STS/SINE") # Float to fixed point pilot1_ui32 = cfloat2uint32(txSignal, order='QI') pilot2_ui32 = cfloat2uint32(wbz) if not lo_tone: replay_addr = 0 if ant == 'A': sdr.writeRegisters("TX_RAM_A", replay_addr, pilot1_ui32.tolist()) elif ant == 'B': sdr.writeRegisters("TX_RAM_B", replay_addr, pilot1_ui32.tolist()) elif ant == 'AB': sdr.writeRegisters("TX_RAM_A", replay_addr, pilot1_ui32.tolist()) sdr.writeRegisters("TX_RAM_B", replay_addr, pilot1_ui32.tolist()) sdr.writeSetting("TX_REPLAY", str(numSamps)) # this starts transmission # Show current gains if "CBRS" in info["frontend"]: IAMP = sdr.getGain(SOAPY_SDR_TX, 0, "IAMP") PAD = sdr.getGain(SOAPY_SDR_TX, 0, "PAD") PA1 = sdr.getGain(SOAPY_SDR_TX, 0, "PA1") PA2 = sdr.getGain(SOAPY_SDR_TX, 0, "PA2") PA3 = sdr.getGain(SOAPY_SDR_TX, 0, "PA3") ATTN = sdr.getGain(SOAPY_SDR_TX, 0, "ATTN") print("GAINS CHAN0: PA1 {}, PA3 {}, PA2 {}, ATTN {}, PAD {}, IAMP {}". format(PA1, PA3, PA2, ATTN, PAD, IAMP)) else: IAMP = sdr.getGain(SOAPY_SDR_TX, 0, "IAMP") PAD = sdr.getGain(SOAPY_SDR_TX, 0, "PAD") print("GAINS CHAN0: PAD {}, IAMP {}".format(PAD, IAMP)) # Plot signal debug = 0 if debug: fig = plt.figure(figsize=(20, 8), dpi=100) ax1 = fig.add_subplot(2, 1, 1) ax1.plot(np.real(txSignal), label='pilot i') ax1.plot(np.imag(txSignal), label='pilot q') ax2 = fig.add_subplot(2, 1, 2) ax2.plot(np.abs(txSignal), label='abs(signal)') plt.show(block=False) # Stop/Close/Cleanup signal.signal(signal.SIGINT, signal_handler) pth = threading.Thread(target=print_thread, args=(sdr, info)) pth.start() print("ctrl-c to stop ...") signal.pause()
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
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])
def beamsweeper(hub, serials, rate, freq, txgain, rxgain, numSamps, numSyms, prefix_length, postfix_length, calibrate, both_channels): global sdrs, hub_dev if hub != "": hub_dev = SoapySDR.Device(dict(serial=hub)) print("setting %s as eNB" % (serials)) sdrs = [ SoapySDR.Device(dict(serial=serial1)) for serial1 in serials.split(',') ] #some default sample rates for sdr in sdrs: info = sdr.getHardwareInfo() print("%s settings on device" % (info["frontend"])) for ch in [0, 1]: sdr.setBandwidth(SOAPY_SDR_RX, ch, 2.5 * rate) sdr.setBandwidth(SOAPY_SDR_TX, ch, 2.5 * rate) sdr.setSampleRate(SOAPY_SDR_TX, ch, rate) sdr.setSampleRate(SOAPY_SDR_RX, ch, rate) sdr.setFrequency(SOAPY_SDR_TX, ch, "BB", 0.75 * rate) sdr.setFrequency(SOAPY_SDR_RX, ch, "BB", 0.75 * rate) sdr.setFrequency(SOAPY_SDR_TX, ch, "RF", freq - 0.75 * rate) sdr.setFrequency(SOAPY_SDR_RX, ch, "RF", freq - 0.75 * rate) sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX") sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True) if calibrate: sdr.writeSetting(SOAPY_SDR_RX, ch, "CALIBRATE", 'SKLK') sdr.writeSetting(SOAPY_SDR_TX, ch, "CALIBRATE", '') if "CBRS" in info["frontend"]: # Set gains to high val (initially) sdr.setGain( SOAPY_SDR_TX, ch, txgain ) # txgain: at 2.5GHz [16:1:93], at 3.6GHz [15:1:102] sdr.setGain( SOAPY_SDR_RX, ch, rxgain) # rxgain: at 2.5GHz [3:1:105], at 3.6GHz [3:1:102] else: # No CBRS board gains, only changing LMS7 gains 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] if not both_channels: sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false') sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false') sdr.writeSetting("RESET_DATA_LOGIC", "") if hub == "": sdrs[0].writeSetting("SYNC_DELAYS", "") else: hub_dev.writeSetting("SYNC_DELAYS", "") #packet size symSamp = numSamps + prefix_length + postfix_length print("numSamps = %d" % symSamp) # preambles to be sent from BS and correlated against in UE upsample = 1 preambles_bs = generate_training_seq(preamble_type='gold_ifft', seq_length=128, cp=0, upsample=1) preambles = preambles_bs[:, :: upsample] #the correlators can run at lower rates, so we only need the downsampled signal. beacon = preambles[0, :] * .25 possible_dim = [] nRadios = len(sdrs) nChannels = 2 if both_channels else 1 numAnt = nRadios * nChannels possible_dim.append(2**(np.ceil(np.log2(numAnt)))) h_dim = min(possible_dim) hadamard_matrix = hadamard( h_dim ) #hadamard matrix : http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.linalg.hadamard.html beacon_weights = hadamard_matrix[0:numAnt, 0:numAnt] print(beacon_weights) beacon_weights = beacon_weights.astype(np.uint32) bzeros = np.array([0] * numAnt, np.uint32) bsched = "BG" #+''.join("G"*(numSyms-1)) print("Schedule %s " % bsched) bconf = { "tdd_enabled": True, "frame_mode": "free_running", "symbol_size": symSamp, "frames": [bsched], "beacon_start": prefix_length, "beacon_stop": prefix_length + len(beacon) } for i, sdr in enumerate(sdrs): sdr.writeSetting("TDD_CONFIG", json.dumps(bconf)) sdr.writeSetting("TX_SW_DELAY", str(30)) sdr.writeSetting("TDD_MODE", "true") for i, sdr in enumerate(sdrs): sdr.writeRegisters("BEACON_RAM", 0, cfloat2uint32(beacon, order='QI').tolist()) sdr.writeRegisters("BEACON_RAM_WGT_A", 0, beacon_weights[i * nChannels].tolist()) sdr.writeRegisters( "BEACON_RAM_WGT_B", 0, beacon_weights[2 * i + 1].tolist() if both_channels else bzeros.tolist()) sdr.writeSetting("BEACON_START", str(numAnt)) signal.signal(signal.SIGINT, partial(signal_handler, rate, numSyms)) if hub == "": sdrs[0].writeSetting("TRIGGER_GEN", "") else: hub_dev.writeSetting("TRIGGER_GEN", "") signal.pause()
# Settings ############################################################################################ # Data transfer settings rx_chan = 0 # RX1 = 0, RX2 = 1 N = 16384 # Number of complex samples per transfer fs = 31.25e6 # Radio sample Rate freq = 2.4e9 # LO tuning frequency in Hz use_agc = True # Use or don't use the AGC timeout_us = int(5e6) rx_bits = 16 # The AIR-T's ADC is 16 bits ############################################################################################ # Receive Signal ############################################################################################ # Initialize the AIR-T receiver using SoapyAIRT sdr = SoapySDR.Device(dict(driver="SoapyAIRT")) # Create AIR-T instance sdr.setSampleRate(SOAPY_SDR_RX, 0, fs) # Set sample rate sdr.setGainMode(SOAPY_SDR_RX, 0, use_agc) # Set the gain mode sdr.setFrequency(SOAPY_SDR_RX, 0, freq) # Tune the LO # Create data buffer and start streaming samples to it rx_buff = np.empty(2 * N, np.int16) # Create memory buffer for data stream rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [rx_chan]) # Setup data stream sdr.activateStream(rx_stream) # this turns the radio on # Read the samples from the data buffer sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=timeout_us) rc = sr.ret # number of samples read or the error code assert rc == N, 'Error {}: {}'.format(rc.ret, errToStr(rc.ret))
#prin dir(dev.getDeviceDescription()['frequencies']['rx'][0]) #print dev.getDeviceDescription()['frequencies']['rx'][0] #print dev.getDeviceDescription()['frequencies']['rx'].index #for a in dir(dev.sdr): # if 'list' in a or 'get' in a: # print a #print dev.bbdev.values() #print dev.bbdev.items() #exit(0) #print(reSult) #create device instance #args can be user defined or from the enumeration result #args = dict(driver="hackrf") sdr = SoapySDR.Device({'driver': 'hackrf'}) #query device info #print(sdr.listAntennas(SOAPY_SDR_RX, 0)) #print(sdr.listGains(SOAPY_SDR_RX, 0)) #freqs = sdr.getFrequencyRange(SOAPY_SDR_RX, 0) #for freqRange in freqs: print("F"+str(freqRange)) print("Setting up rtx") #apply settings sdr.setSampleRate(SOAPY_SDR_RX, 0, 1e6) sdr.setFrequency(SOAPY_SDR_RX, 0, 99.4e7) #sdr.setSampleRate(SOAPY_SDR_TX, 0, 1e6) #sdr.setFrequency(SOAPY_SDR_TX, 0, 99.4e7) print("Setting up streams")
def LimeSuiteCalibrate( args, freqStart, freqStop, freqStep, dumpDir, validate, ): if freqStart is None: raise Exception("No start frequency specified") if freqStop is None: freqStop = freqStart #open device print('#' * 40) print('## Open device with "%s"' % (args)) print('#' * 40) limeSDR = SoapySDR.Device(args) print(str(limeSDR)) info = limeSDR.getHardwareInfo() for k in info.keys(): print("%s:%s" % (k, info[k])) #initialize parameters print('#' * 40) print('## Initialize "%s"' % (str(limeSDR))) print('#' * 40) limeSDR.setMasterClockRate(CLOCK_RATE) for channel in [0, 1]: limeSDR.setSampleRate(SOAPY_SDR_TX, channel, SAMPLE_RATE) limeSDR.setSampleRate(SOAPY_SDR_RX, channel, SAMPLE_RATE) limeSDR.setAntenna(SOAPY_SDR_RX, channel, RX_ANTENNA) limeSDR.setAntenna(SOAPY_SDR_TX, channel, TX_ANTENNA) limeSDR.setGain(SOAPY_SDR_TX, channel, "PAD", PAD_GAIN) limeSDR.setGain(SOAPY_SDR_TX, channel, "LB_PAD", LB_PAD_GAIN) limeSDR.setGain(SOAPY_SDR_RX, channel, "PGA", PGA_GAIN) limeSDR.setGain(SOAPY_SDR_RX, channel, "TIA", TIA_GAIN) limeSDR.setGain(SOAPY_SDR_RX, channel, "LNA", LNA_GAIN) limeSDR.setGain(SOAPY_SDR_RX, channel, "LB_LNA", LB_LNA_GAIN) limeSDR.setDCOffsetMode(SOAPY_SDR_RX, channel, False) #open the rx stream rxStream = limeSDR.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1]) #sweep for each frequency for freq in np.arange(freqStart, freqStop + freqStep, freqStep): t0 = time.time() try: CalibrateAtFreq(limeSDR=limeSDR, rxStream=rxStream, freq=freq, dumpDir=dumpDir, validate=validate) except Exception as ex: print("Failed at %g MHz, skipping...\n %s" % (freq / 1e6, str(ex))) if not validate: print("Cal took %s seconds" % (time.time() - t0)) #close the rx stream limeSDR.closeStream(rxStream) #close the device limeSDR = None print("Done")
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
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')
pwr_circ_buff = np.zeros(num_samps_circ_buff) ######################################## # LOGGER # ######################################## # SOAPY_SDR_FATAL = 1, //!< A fatal error. The application will most likely terminate. This is the highest priority. # SOAPY_SDR_CRITICAL = 2, //!< A critical error. The application might not be able to continue running successfully. # SOAPY_SDR_ERROR = 3, //!< Error.An operation didn't complete successfully, but application as a whole not affected. # SOAPY_SDR_WARNING = 4, //!< A warning. An operation completed with an unexpected result. # SOAPY_SDR_NOTICE = 5, //!< A notice, which is an information with just a higher priority. # SOAPY_SDR_INFO = 6, //!< An informational message, usually denoting the successful completion of an operation. # SOAPY_SDR_DEBUG = 7, //!< A debugging message. # SOAPY_SDR_TRACE = 8, //!< A tracing message. This is the lowest priority. # SOAPY_SDR_SSI = 9, //!< Streaming status indicators such as "U" (underflow) and "O" (overflow). logLevel = 3 # 4:WARNING, 6:WARNING+INFO, 7:WARNING+INFO+DEBUG... SoapySDR.SoapySDR_setLogLevel(logLevel) logging.basicConfig( filename='./data_out/debug_SISO_RX.log', level=logging.DEBUG, format='[%(levelname)s] (%(threadName)-10s) %(asctime)s %(message)s', ) ######################################### # Create Plots # ######################################### matplotlib.rcParams.update({'font.size': 10}) fig = plt.figure(figsize=(20, 8), dpi=120) fig.subplots_adjust(hspace=.5, top=.85) ax1 = fig.add_subplot(6, 1, 1) ax1.grid(True)
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" 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)) 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: 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", ..." 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")
def rxsamples_app(srl, freq, gain, num_samps, recorder, agc_en, wait_trigger): """ Initialize IRIS parameters and animation kick-off """ # Global declarations global sdr, rxStream, freqScale, Rate # Instantiate device sdr = SoapySDR.Device(dict(serial=srl)) info = sdr.getHardwareInfo() print(info) # Set gains to very high value if AGC enabled (AGC only supports CBRS RF frontend at the moment). if agc_en and "CBRS" in info["frontend"]: gain = 100 rssi_target_idx = 20 agc_init(sdr, rssi_target_idx) else: # Make sure AGC is disabled if any of the previous checks fails agc_en = 0 # Set params on both channels (both RF chains) for ch in [0, 1]: sdr.setBandwidth(SOAPY_SDR_RX, ch, 2.5 * Rate) sdr.setBandwidth(SOAPY_SDR_TX, ch, 2.5 * Rate) sdr.setFrequency(SOAPY_SDR_RX, ch, freq) sdr.setSampleRate(SOAPY_SDR_RX, ch, Rate) sdr.setFrequency(SOAPY_SDR_TX, ch, freq) sdr.setSampleRate(SOAPY_SDR_TX, ch, Rate) sdr.setAntenna(SOAPY_SDR_RX, ch, "TRX") sdr.setDCOffsetMode(SOAPY_SDR_RX, ch, True) if "CBRS" in info["frontend"]: sdr.setGain(SOAPY_SDR_RX, ch, gain) else: # No CBRS board gains, only changing LMS7 gains sdr.setGain(SOAPY_SDR_RX, ch, "LNA", gain) # [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] print("Number of Samples %d " % num_samps) print("Frequency has been set to %f" % sdr.getFrequency(SOAPY_SDR_RX, 0)) sdr.writeRegister("RFCORE", 120, 0) # Setup RX stream rxStream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1]) # RSSI read setup setUpDigitalRssiMode(sdr) # There's a bug in the FuncAnimation function, we replaced it with a fixed version # anim = animation.FuncAnimation(fig, animate, init_func=init, fargs=(num_samps, recorder, agc_en, wait_trigger), # frames=100, interval=100, blit=True) anim = MyFuncAnimation(fig, animate, init_func=init, fargs=(num_samps, recorder, agc_en, wait_trigger, info), frames=100, interval=100, blit=True) plt.show()
def siggen_app(args, rate, ampl=0.7, freq=None, txBw=None, txChan=0, rxChan=0, txGain=None, txAnt=None, clockRate=None, waveFreq=None): if waveFreq is None: waveFreq = rate / 10 sdr = SoapySDR.Device(args) #set clock rate first if clockRate is not None: sdr.setMasterClockRate(clockRate) #set sample rate sdr.setSampleRate(SOAPY_SDR_TX, txChan, rate) print("Actual Tx Rate %f Msps" % (sdr.getSampleRate(SOAPY_SDR_TX, txChan) / 1e6)) #set bandwidth if txBw is not None: sdr.setBandwidth(SOAPY_SDR_TX, txChan, txBw) #set antenna print("Set the antenna") if txAnt is not None: sdr.setAntenna(SOAPY_SDR_TX, txChan, txAnt) #set overall gain print("Set the gain") if txGain is not None: sdr.setGain(SOAPY_SDR_TX, txChan, txGain) #tune frontends print("Tune the frontend") if freq is not None: sdr.setFrequency(SOAPY_SDR_TX, txChan, freq) #tx loop #create tx stream print("Create Tx stream") txStream = sdr.setupStream(SOAPY_SDR_TX, "CF32", [txChan]) print("Activate Tx Stream") sdr.activateStream(txStream) phaseAcc = 0 phaseInc = 2 * math.pi * waveFreq / rate streamMTU = sdr.getStreamMTU(txStream) sampsCh0 = np.array([ampl] * streamMTU, np.complex64) timeLastPrint = time.time() totalSamps = 0 while True: phaseAccNext = phaseAcc + streamMTU * phaseInc sampsCh0 = ampl * np.exp(1j * np.linspace( phaseAcc, phaseAccNext, streamMTU)).astype(np.complex64) phaseAcc = phaseAccNext while phaseAcc > math.pi * 2: phaseAcc -= math.pi * 2 sr = sdr.writeStream(txStream, [sampsCh0], sampsCh0.size) if sr.ret != sampsCh0.size: raise Exception( "Expected writeStream() to consume all samples! %d" % sr.ret) totalSamps += sr.ret if time.time() > timeLastPrint + 5.0: print("Python siggen rate: %f Msps" % (totalSamps / (time.time() - timeLastPrint) / 1e6)) totalSamps = 0 timeLastPrint = time.time() #cleanup streams print("Cleanup stream") sdr.deactivateStream(txStream) sdr.closeStream(txStream) print("Done!")
import SoapySDR from SoapySDR import * #SOAPY_SDR_ constants import numpy #use numpy for buffers import matplotlib.pyplot as plt from scipy.signal import decimate, hilbert from scipy import sqrt #create device instance #args can be user defined or from the enumeration result args = dict(driver="rtlsdr") sdr = SoapySDR.Device(args) #apply settings sdr.setSampleRate(SOAPY_SDR_RX, 0, 1e6) sdr.setFrequency(SOAPY_SDR_RX, 0, 434e6) # sdr.setGain('auto') sdr.setBandwidth(SOAPY_SDR_RX, 0, 1e6) #setup a stream (complex floats) rxStream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32) sdr.activateStream(rxStream) #start streaming #create a re-usable buffer for rx samples buff = numpy.array([0] * 1024 * 256, numpy.complex64) #receive some samples sr = sdr.readStream(rxStream, [buff], len(buff)) print(buff[0], buff[100], buff[200], buff[2000]) samples_sq = [sqrt(i.real * i.real + i.imag * i.imag) for i in buff] samples_sq = decimate(samples_sq, 50)
def simo_fdx_burst(hub, bserials, rate, freq, txgain, rxgain, numSamps, prefix_pad, postfix_pad, both_channels) -> np.array: # ## hub and multi-sdr integration copied from WB_CAL_DEMO.py if hub != "": hub_dev = SoapySDR.Device(dict(driver="remote", serial=hub)) sdrs = [ SoapySDR.Device(dict(driver="iris", serial=serial)) for serial in bserials ] ant = 2 if both_channels else 1 num_sdrs = len(sdrs) num_ants = num_sdrs * ant # assume trig_dev is part of the sdr nodes if no hub given trig_dev = None if hub != "": trig_dev = hub_dev else: trig_dev = sdrs[0] # set params on both channels for sdr in sdrs: 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, '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) # Read initial gain settings read_lna = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA') read_tia = sdr.getGain(SOAPY_SDR_RX, 0, 'TIA') read_pga = sdr.getGain(SOAPY_SDR_RX, 0, 'PGA') print("INITIAL GAIN - LNA: {}, \t TIA:{}, \t PGA:{}".format( read_lna, read_tia, read_pga)) # gain setting from SISO_TXRX_TDD.py if "CBRS" in info["frontend"]: # Set gains to high val (initially) # sdr.setGain(SOAPY_SDR_TX, ch, txgain) # txgain: at 2.5GHz [16:1:93], at 3.6GHz [15:1:102] # sdr.setGain(SOAPY_SDR_RX, ch, rxgain) # rxgain: at 2.5GHz [3:1:105], at 3.6GHz [3:1:102] # else: # No CBRS board gains, only changing LMS7 gains sdr.setGain(SOAPY_SDR_TX, ch, "PAD", txgain) # [0:1:42] txgain sdr.setGain(SOAPY_SDR_TX, ch, "ATTN", -6) sdr.setGain(SOAPY_SDR_RX, ch, "LNA", rxgain) # [0:1:30] rxgain sdr.setGain(SOAPY_SDR_RX, ch, "LNA2", 14) sdr.setGain(SOAPY_SDR_RX, ch, "ATTN", 0 if freq > 3e9 else -18) # for ch in [0, 1]: # if calibrate: # sdr.writeSetting(SOAPY_SDR_RX, ch, "CALIBRATE", 'SKLK') # sdr.writeSetting(SOAPY_SDR_TX, ch, "CALIBRATE", '') sdr.writeSetting("RESET_DATA_LOGIC", "") if not both_channels: sdr.writeSetting(SOAPY_SDR_RX, 1, 'ENABLE_CHANNEL', 'false') sdr.writeSetting(SOAPY_SDR_TX, 1, 'ENABLE_CHANNEL', 'false') trig_dev.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 # pilot1_energy = np.sum(np.abs(cfloat2uint32(pilot1, order='QI')**2))/len(pilot1) # Initialize RX Matrix | num_sdrs x num_sdrs filled with None, to be filled with np.ndarray of np.ndarray of np.ndarray of np.uint32 # The layers ought to be: array of each iteration (distinct TX board), each of which is an array of each board's RX, # each of which is an array of two arrays (one per antenna), each antenna having an array of values # this initializes all values to be None, might cause problems if something isn't overwritten for some reason rxMatrix = np.empty([num_ants, num_sdrs, ant], np.ndarray) # Create RX streams # CS16 makes sure the 4-bit lsb are samples are being sent rxStreams = [ sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1]) for sdr in sdrs ] # Set Schedule #NOTE: this config is still unchanged from SISO_TXRX_TDD.py, needs to be fixed txsched = "PG" rxsched = "RG" print("Node 1 schedule %s " % txsched) print("Node 2 schedule %s " % rxsched) # Send one frame (set mamx_frame to 1) txconf = { "tdd_enabled": True, "frame_mode": "free_running", "symbol_size": symSamp, "frames": [txsched], "max_frame": 1 } rxconf = { "tdd_enabled": True, "frame_mode": "free_running", "dual_pilot": False, "symbol_size": symSamp, "frames": [rxsched], "max_frame": 1 } # SW Delays for sdr in sdrs: sdr.writeSetting("TX_SW_DELAY", str(30)) # TDD_MODE Setting sdr.writeSetting("TDD_MODE", "true") #for sdr in sdrs: # sdr.writeRegisters("TX_RAM_B", 0, cfloat2uint32(pilot2, order='QI').tolist()) # Average Energy in signal energy_func = lambda x: np.sum(np.abs(x)**2) / len(x) dB_func = lambda x: 10 * np.log10(x) # implement loop logic here to make each board the TX board once per antenna, run num_ant times for i, txsdr in enumerate(sdrs): # repeat twice if both channels active for tx_ant in range(ant): activate_B = tx_ant % 2 if activate_B: # if second time through, activate channel B txsdr.writeRegisters( "TX_RAM_B", 0, cfloat2uint32(pilot1, order='QI').tolist()) txsdr.writeRegisters( "TX_RAM_A", 0, cfloat2uint32(pilot2, order='QI').tolist()) else: # activate channel A first time through txsdr.writeRegisters( "TX_RAM_A", 0, cfloat2uint32(pilot1, order='QI').tolist()) txsdr.writeRegisters( "TX_RAM_B", 0, cfloat2uint32(pilot2, order='QI').tolist()) txsdr.writeSetting("TDD_CONFIG", json.dumps(txconf)) # list comp. here makes sure we loop over every other board for j, rxsdr in enumerate( [board for board in sdrs if board != txsdr]): rxsdr.writeSetting("TDD_CONFIG", json.dumps(rxconf)) # build rx Arrays rxArray_single_channel = np.array([0] * symSamp, np.complex64) rxArray_both_channels = np.array([rxArray_single_channel] * 2) rxArrays = np.array([rxArray_both_channels] * num_sdrs) flags = 0 rList = np.empty(num_sdrs, object) # activate streams for r, sdr in enumerate(sdrs): rList[r] = sdr.activateStream(rxStreams[r], flags, 0) if rList[r] < 0: print("Problem activating stream # %d" % i) trig_dev.writeSetting("TRIGGER_GEN", "") dBArrays = np.zeros( [num_sdrs, ant] ) #NOTE: this will initialize it to be 0s, which might be problematic # read Streams for r, sdr in enumerate(sdrs): rList[r] = sdrs[r].readStream(rxStreams[r], rxArrays[r], symSamp) print("reading stream #{} ({})".format(r, rList[r])) # read num_ant stream (either A or B depending) on which one sent for rx_ant in range(ant): dBArrays[r][rx_ant] = dB_func( energy_func(rxArrays[r][rx_ant])) amp = np.max(abs(rxArrays[r][rx_ant])) if amp > 0.1: print("Board {0} with board {1}, max amp:{2}".format( i * 2 + tx_ant, r * 2 + rx_ant, amp)) for r, sdr in enumerate(sdrs): sdr.deactivateStream(rxStreams[r]) # print("\n ================ \n ") # print(dBArrays.shape) # print(dBArrays) # print("\n =============== \n") rxMatrix[i * ant + tx_ant] = dBArrays # print(np.transpose(rxMatrix)) # End of data collection loops # # ADC_rst, stops the tdd time counters, makes sure next time runs in a clean slate tdd_conf = {"tdd_enabled": False} for sdr in sdrs: sdr.writeSetting("RESET_DATA_LOGIC", "") sdr.writeSetting("TDD_CONFIG", json.dumps(tdd_conf)) sdr.writeSetting("TDD_MODE", "false") for r, sdr in enumerate(sdrs): sdr.deactivateStream(rxStreams[r]) sdr.closeStream(rxStreams[r]) sdrs[r] = None print("3D dB Matrix: \n", rxMatrix) retMatrix = extract_ant(rxMatrix, both_channels) retMatrix = np.transpose(retMatrix) print("2D dB Matrix: \n", retMatrix) return (retMatrix)
def calibrate_array(hub_serial, serials, ref_serial, rate, freq, txgain, rxgain, numSamps, prefix_pad, postfix_pad, second_channel): global running bsdr = [ SoapySDR.Device(dict(driver='iris', serial=serial)) for serial in serials ] ref_sdr = SoapySDR.Device(dict(driver='iris', serial=ref_serial)) if hub_serial != "": hub = SoapySDR.Device(dict(driver='remote', serial=hub_serial)) sdrs = [ref_sdr] + bsdr #some default sample rates for i, sdr in enumerate(sdrs): info = sdr.getHardwareInfo() print("%s settings on device %d" % (info["frontend"], i)) channel = [1] if second_channel else [0] for ch in channel: 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) 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) sdr.writeSetting("RESET_DATA_LOGIC", "") if hub_serial != "": hub.writeSetting("SYNC_DELAYS", "") else: bsdr[0].writeSetting("SYNC_DELAYS", "") num_bs_ant = len(bsdr) symSamp = numSamps + prefix_pad + postfix_pad print("numSamps = %d" % numSamps) print("symSamps = %d" % symSamp) DnA = [np.array([0] * symSamp, np.uint32) for i in range(num_bs_ant)] DnB = [np.array([0] * symSamp, np.uint32) for i in range(num_bs_ant)] UpA = [np.array([0] * symSamp, np.uint32) for i in range(num_bs_ant)] UpB = [np.array([0] * symSamp, np.uint32) for i in range(num_bs_ant)] #phaseDeltaDn = np.empty(num_bs_ant).astype(np.float) #phaseDeltaUp = np.empty(num_bs_ant).astype(np.float) #calibPhase = np.empty(num_bs_ant).astype(np.float) #ampDn = np.empty(num_bs_ant).astype(np.float) #ampUp = np.empty(num_bs_ant).astype(np.float) #calibAmp = np.empty(num_bs_ant).astype(np.float) # CS16 makes sure the 4-bit lsb are samples are being sent bs_rx_stream = [ sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1], dict(WIRE=SOAPY_SDR_CS16)) for sdr in bsdr ] ref_rx_stream = ref_sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0, 1], dict(WIRE=SOAPY_SDR_CS16)) 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) * .2 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]) if not second_channel else wbz pilot2 = np.concatenate([pad1, pilot, pad2]) if second_channel else wbz # configure tdd mode frameLen = len(bsdr) + 1 + 1 + 1 for i, sdr in enumerate(bsdr): bsched = "RG" + ''.join("G" * i) + "P" + ''.join("G" * (frameLen - i - 3)) print("node %d schedule: %s" % (i, bsched)) bconf = { "tdd_enabled": True, "frame_mode": "triggered", "symbol_size": symSamp, "frames": [bsched], "max_frame": 0 } sdr.writeSetting("TDD_CONFIG", json.dumps(bconf)) msched = "PG" + ''.join("R" * len(bsdr)) + "G" print("ref node schedule: %s" % (msched)) mconf = { "tdd_enabled": True, "frame_mode": "triggered", "symbol_size": symSamp, "frames": [msched], "max_frame": 0 } ref_sdr.writeSetting("TDD_CONFIG", json.dumps(mconf)) for sdr in sdrs: sdr.writeSetting("TDD_MODE", "true") for sdr in sdrs: sdr.writeSetting("TX_SW_DELAY", str(30)) replay_addr = 0 for sdr in sdrs: sdr.writeRegisters("TX_RAM_A", replay_addr, cfloat2uint32(pilot1, order='QI').tolist()) sdr.writeRegisters("TX_RAM_B", replay_addr, cfloat2uint32(pilot2, order='QI').tolist()) flags = 0 [ sdr.activateStream(bs_rx_stream[i], flags, 0) for i, sdr in enumerate(bsdr) ] ref_sdr.activateStream(ref_rx_stream, flags, 0) fig, axes = plt.subplots(nrows=len(serials), ncols=2) # figsize=(16,16)) axes[0, 0].set_title('Downlink') axes[0, 1].set_title('Uplink') for i in range(len(serials)): #axes[i, 0].set_ylabel('Amplitude') axes[i, 0].set_ylim(-.1, .1) axes[i, 0].set_xlim(0, symSamp) axes[i, 0].legend(fontsize=10) #axes[i, 1].set_ylabel('Amplitude') axes[i, 1].set_ylim(-.1, .1) axes[i, 1].set_xlim(0, symSamp) axes[i, 1].legend(fontsize=10) interval = range(100, symSamp) lineI0 = [ axes[i, 0].plot(np.real(uint32tocfloat(UpA[i][interval])), label='ChA(I) Ref->Node %d' % i)[0] for i in range(num_bs_ant) ] lineQ0 = [ axes[i, 0].plot(np.imag(uint32tocfloat(UpA[i][interval])), label='ChA(Q) Ref->Node %d' % i)[0] for i in range(num_bs_ant) ] lineI1 = [ axes[i, 1].plot(np.real(uint32tocfloat(DnA[i][interval])), label='ChA(I) Node %d->Ref' % i)[0] for i in range(num_bs_ant) ] lineQ1 = [ axes[i, 1].plot(np.imag(uint32tocfloat(DnA[i][interval])), label='ChA(Q) Node %d->Ref' % i)[0] for i in range(num_bs_ant) ] fig.show() #print("Timestamps:") #for sdr in sdrs: # print(hex(SoapySDR.timeNsToTicks(sdr.getHardwareTime(""), rate))) plot_size = len(interval) H1 = [np.empty(plot_size).astype(np.complex64) for r in range(num_bs_ant)] H2 = [np.empty(plot_size).astype(np.complex64) for r in range(num_bs_ant)] calib = [ np.empty(plot_size).astype(np.complex64) for r in range(num_bs_ant) ] fg, ax = plt.subplots(nrows=2, ncols=1) #, figsize=(16,8)) ax[0].set_ylabel('calibration amplitude') ax[0].set_xlim(interval[0], interval[-1]) ax[0].set_ylim(-.1, .1) ax[1].set_ylabel('calibration phase') ax[1].set_xlim(interval[0], interval[-1]) ax[1].set_ylim(-np.pi, np.pi) line0 = [ ax[0].plot([0] * plot_size, label='Amplitude %d' % i)[0] for i in range(num_bs_ant) ] line1 = [ ax[1].plot([0] * plot_size, label='Phase %d' % i)[0] for i in range(num_bs_ant) ] fg.show() signal.signal(signal.SIGINT, signal_handler) #def animate(i): while (running): if hub_serial != "": hub.writeSetting("TRIGGER_GEN", "") else: bsdr[0].writeSetting("TRIGGER_GEN", "") for i, sdr in enumerate(bsdr): sdr.readStream(bs_rx_stream[i], [UpA[i], UpB[i]], symSamp) for i in range(len(bsdr)): ref_sdr.readStream(ref_rx_stream, [DnA[i], DnB[i]], symSamp) for i in range(num_bs_ant): H1[i] = uint32tocfloat( DnA[i][interval] if not second_channel else DnB[i][interval]) H2[i] = uint32tocfloat( UpA[i][interval] if not second_channel else UpB[i][interval]) calib[i] = H1[i] * np.conj(H2[i]) #phaseDeltaDn[i] = np.mean(np.angle(DnA[i][interval] * np.conj(pilot[interval]))) #phaseDeltaUp[i] = np.mean(np.angle(UpA[i][interval] * np.conj(pilot[interval]))) #calibPhase[i] = np.mean(np.angle(DnA[i][interval] * np.conj(UpA[i][interval]))) #ampDn[i] = np.sum(np.abs(DnA[i][interval]))/np.sum(np.abs(pilot[interval])) #ampUp[i] = np.sum(np.abs(UpA[i][interval]))/np.sum(np.abs(pilot[interval])) #calibAmp[i] = np.sum(np.abs(UpA[i][interval]))/np.sum(np.abs(DnA[interval])) #np.set_printoptions(precision=2) lineI0[i].set_ydata(np.real(H1[i])) lineQ0[i].set_ydata(np.imag(H1[i])) lineI1[i].set_ydata(np.real(H2[i])) lineQ1[i].set_ydata(np.imag(H2[i])) line0[i].set_ydata(np.abs(calib[i])) line1[i].set_ydata((np.angle(calib[i]))) fig.canvas.draw() fg.canvas.draw() fg.show() fig.show() #return line0, line1, #anim = animation.FuncAnimation(fig, animate, init_func=None, # frames=100, interval=100, blit=True) #plt.show() tdd_conf = {"tdd_enabled": False} for sdr in sdrs: sdr.writeSetting("RESET_DATA_LOGIC", "") sdr.writeSetting("TDD_CONFIG", json.dumps(tdd_conf)) sdr.writeSetting("TDD_MODE", "false") ref_sdr.closeStream(ref_rx_stream) for i, sdr in enumerate(bsdr): sdr.closeStream(bs_rx_stream[i]) ref_sdr = None bsdr = None