Beispiel #1
0
def find_corr_idx(waveRxA, waveRxB):
    """
    Find correlation indexes
    Input:
        waveRxA - vector of IQ samples from RF chain A
        waveRxB - vector of IQ samples from RF chain B

    Output:
        idx_mat - matrix with correlation indexes at all boards

    """
    idx_mat = np.empty(
        (waveRxA.shape[0], waveRxA.shape[1]))  # Matrix: 2x#radios. two pilots
    idx_mat[:] = np.nan
    lts_thresh = 0.8

    # Iterate over the multiple entries
    for i in range(waveRxA.shape[0]):
        for j in range(waveRxA.shape[1]):
            # Both channels
            best_peakA, all_peaksA, corrA = find_lts(waveRxA[i, j],
                                                     thresh=lts_thresh,
                                                     flip=False)
            best_peakB, all_peaksB, corrB = find_lts(waveRxB[i, j],
                                                     thresh=lts_thresh,
                                                     flip=False)

            # print("Best peak BOARD: {},  A: {}    and B: {}".format(j, best_peakA, best_peakB))
            # plt.figure(100)
            # plt.plot(corrA)
            # plt.plot(corrB)
            # plt.show()

            # Check if LTS found
            if not best_peakA:  # and not best_peakB:
                print("No LTS Found!")
                continue
            if not (best_peakA == best_peakB):
                print("Same board, different indexes. Wut??")

            idx_mat[i,
                    j] = best_peakA  # best_peakA if best_peakA else best_peakB
    return idx_mat
Beispiel #2
0
def pilot_finder(samples, pilot_type, flip=False, pilot_seq=[]):
    """
    Find pilots from clients to each of the base station antennas

    Input:
        samples    - Raw samples from pilots and data.
                     Dimensions: vector [1 x num samples]
        pilot_type - Type of TX pilot (e.g., 802.11 LTS)
        flip       - Needed for finding LTS function

    Output:
        pilot     - Received pilot (from multiple clients)
        tx_pilot  - Transmitted pilot (same pilot sent by all clients)
    """

    if pilot_type == 'lts-half' or pilot_type == 'lts-full':
        lts_thresh = 0.8
        best_pk, lts_pks, lts_corr = find_lts(samples, thresh=lts_thresh, flip=flip, lts_seq=pilot_seq)

        # full lts contains 2.5 64-sample-LTS sequences, we need only one symbol
        lts, lts_f = generate_training_seq(preamble_type='lts', cp=32, upsample=1)

        if not (pilot_seq.size == 0):
            # pilot provided, overwrite the one returned above
            lts = pilot_seq

        lts_syms_len = len(lts)
        pilot_thresh = lts_thresh * np.max(lts_corr)
        # We'll need the transmitted version of the pilot (for channel estimation, for example)
        tx_pilot = [lts, lts_f]
        lts_start = 0

        # Check if LTS found
        if not best_pk:
            print("SISO_OFDM: No LTS Found! Continue...")
            pilot = np.array([])
            return pilot, tx_pilot, lts_corr, pilot_thresh, best_pk, lts_start
        # If beginning of frame was not captured in current buffer
        if (best_pk - lts_syms_len) < 0:
            print("TOO EARLY. Continue... ")
            pilot = np.array([])
            return pilot, tx_pilot, lts_corr, pilot_thresh, best_pk, lts_start
        if best_pk > len(samples):
            print("TOO LATE. Continue... ")
            pilot = np.array([])
            return pilot, tx_pilot, lts_corr, pilot_thresh, best_pk, lts_start

        # Get pilot
        lts_start = best_pk - lts_syms_len + 0  # where LTS-CP start
        pilot = samples[lts_start:best_pk+0]

    else:
        raise Exception("Only LTS Pilots supported at the moment")

    return pilot, tx_pilot, lts_corr, pilot_thresh, best_pk, lts_start
Beispiel #3
0
def plot_data(pilot,
              rxdata,
              channelnum,
              framelen=512,
              framenum=100,
              pilotsymnum=1,
              uplinksymnum=0):
    # dc removal
    sampsRx = pilot[0].flatten()
    # find LTS assumes signal was generated according to this:
    # generate_training_seq(preamble_type='lts', cp=32, upsample=1)
    # a, b, peaks = lts.findLTS(sampsRx)
    a, b, peaks = find_lts(sampsRx, thresh=0.8, us=1, cp=32)

    fig, axes = plt.subplots(nrows=pilotsymnum + uplinksymnum + 2 + 1, ncols=1)
    sig_power = np.empty([pilotsymnum, framenum], dtype=float)
    sig_phase = np.empty([pilotsymnum, framenum], dtype=float)
    offset = 82 + 128
    sc = 2  # subcarrier
    for i, ax in enumerate(axes):
        if i < pilotsymnum:
            label = "pilot %d " % i
            p = pilot[i].flatten()
            ax.plot(np.real(p), label=label + "I")
            ax.plot(np.imag(p), label=label + "Q")
            ax.legend()
            for k in range(framenum):
                signal = pilot[i, k, offset:offset + 64]
                sig_power[i, k] = np.mean(signal * np.conj(signal))
                sig_phase[i, k] = np.angle(np.fft.fftshift(
                    np.fft.fft(signal)))[sc]
        elif uplinksymnum > 0 and i < pilotsymnum + uplinksymnum:
            j = i - pilotsymnum
            d = rxdata[j].flatten()
            label = "rx data %d " % j
            ax.plot(np.real(d), label=label + "I")
            ax.plot(np.imag(d), label=label + "Q")
            ax.legend()
        elif i == pilotsymnum + uplinksymnum:
            for m in range(pilotsymnum):
                ax.plot(sig_power[m], label='pilot %d power' % m)
            ax.legend()
        elif i == pilotsymnum + uplinksymnum + 1:
            for m in range(pilotsymnum):
                ax.plot(sig_phase[m], label='pilot %d phase sc %d' % (m, sc))
            ax.legend()
        else:
            ax.plot(np.real(peaks), label='Corr Peaks')
    plt.show()
Beispiel #4
0
def init(hub, bnodes, ref_ant, ampl, rate, freq, txgain, rxgain, cyc_prefix,
         num_samps, prefix_length, postfix_length, take_duration,
         both_channels, plotter):
    """main function initializing all radios and performing calibration"""

    if hub != "":
        hub_dev = SoapySDR.Device(dict(driver="remote", serial=hub))
    bsdrs = [
        SoapySDR.Device(dict(driver="iris", serial=serial))
        for serial in bnodes
    ]

    ant = 2 if both_channels else 1
    num_sdrs = len(bsdrs)
    num_ants = num_sdrs * ant

    # 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:
        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))

        #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", "")

    sym_samps = num_samps + prefix_length + postfix_length
    print("num_samps = %d" % sym_samps)

    fft_size = 64
    cp_len = 32 if cyc_prefix else 0
    lts_sym, _ = generate_training_seq(preamble_type='lts',
                                       cp=cp_len,
                                       upsample=1)
    ofdm_len = len(lts_sym)
    zeros = np.array([0] * (num_samps - ofdm_len))
    pilot = np.concatenate((lts_sym, zeros)).astype(np.complex64)
    wb_pilot = ampl * pilot
    wbz = np.array([0] * (sym_samps), np.complex64)
    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_pad = np.concatenate([pad1, wb_pilot, pad2]).astype(np.complex64)
    pilot_subcarriers = [7, 21, 43, 57]
    pilot_sc_num = len(pilot_subcarriers)

    # Create streams
    tx_streams = [
        sdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CF32, [0, 1]) for sdr in bsdrs
    ]
    rx_streams = [
        sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1]) for sdr in bsdrs
    ]
    for r, sdr in enumerate(bsdrs):
        sdr.activateStream(tx_streams[r])

    rx_samps = [[
        np.empty(sym_samps).astype(np.complex64) for r in range(num_ants)
    ] for t in range(num_ants)]
    rx_f = [[np.empty(fft_size).astype(np.complex64) for r in range(num_ants)]
            for t in range(num_ants)]
    calib_mag = [
        np.empty(fft_size).astype(np.complex64) for r in range(num_ants)
    ]
    calib_ang = [
        np.empty(fft_size).astype(np.complex64) for r in range(num_ants)
    ]
    est_calib_mag = [
        np.empty(fft_size).astype(np.complex64) for r in range(num_ants)
    ]
    est_calib_ang = [
        np.empty(fft_size).astype(np.complex64) for r in range(num_ants)
    ]
    mag_buffer = [[
        collections.deque(maxlen=NUM_BUFFER_SAMPS) for i in range(pilot_sc_num)
    ] for j in range(num_ants)]
    ang_buffer = [[
        collections.deque(maxlen=NUM_BUFFER_SAMPS)
        for i in range(len(pilot_subcarriers))
    ] for j in range(num_ants)]
    dummy = np.empty(sym_samps).astype(np.complex64)

    fig1, axes1 = plt.subplots(nrows=num_ants, ncols=2, figsize=(12, 8))
    axes1[0, 0].set_title('Reciprocity Calibration Magnitude')
    axes1[0, 1].set_title('Reciprocity Calibration Phase')
    for m in range(num_ants):
        axes1[m, 0].set_xlim(0, NUM_BUFFER_SAMPS)
        axes1[m, 1].set_xlim(0, NUM_BUFFER_SAMPS)
        axes1[m, 0].set_ylim(0, 5)
        axes1[m, 1].set_ylim(-np.pi, np.pi)
        if m == ref_ant:
            axes1[m, 0].set_ylabel('Ant %d (ref)' % (m))
        else:
            axes1[m, 0].set_ylabel('Ant %d' % (m))

    lines10 = [[
        axes1[m, 0].plot(range(NUM_BUFFER_SAMPS),
                         np.zeros(NUM_BUFFER_SAMPS),
                         label='SC %d' % (pilot_subcarriers[p]))[0]
        for p in range(pilot_sc_num)
    ] for m in range(num_ants)]
    lines11 = [[
        axes1[m, 1].plot(range(NUM_BUFFER_SAMPS),
                         np.zeros(NUM_BUFFER_SAMPS),
                         label='SC %d' % (pilot_subcarriers[p]))[0]
        for p in range(pilot_sc_num)
    ] for m in range(num_ants)]
    for m in range(num_ants):
        for l in range(2):
            axes1[m, l].legend(fontsize=10)
    fig1.show()

    fig3, axes3 = plt.subplots(nrows=num_ants, ncols=2, figsize=(12, 8))
    axes3[0, 0].set_title('Reciprocity Calibration Magnitude')
    axes3[0, 1].set_title('Reciprocity Calibration Phase')
    for m in range(num_ants):
        axes3[m, 0].set_xlim(-8, 72)
        axes3[m, 1].set_xlim(-8, 72)
        axes3[m, 0].set_ylim(0, 5)
        axes3[m, 1].set_ylim(-np.pi, np.pi)
        if m == ref_ant:
            axes3[m, 0].set_ylabel('Ant %d (ref)' % (m))
        else:
            axes3[m, 0].set_ylabel('Ant %d' % (m))

    lines300 = [
        axes3[m, 0].plot(range(64), np.zeros(64), label='Measured Mag')[0]
        for m in range(num_ants)
    ]
    lines301 = [
        axes3[m, 0].plot(range(64), np.zeros(64), label='Estimated Mag')[0]
        for m in range(num_ants)
    ]
    lines310 = [
        axes3[m, 1].plot(range(64), np.zeros(64), label='Measured Ang')[0]
        for m in range(num_ants)
    ]
    lines311 = [
        axes3[m, 1].plot(range(64), np.zeros(64), label='Estimated Ang')[0]
        for m in range(num_ants)
    ]
    for m in range(num_ants):
        for l in range(2):
            axes3[m, l].legend(fontsize=10)
    fig3.show()

    if plotter:
        fig2, axes2 = plt.subplots(nrows=num_ants,
                                   ncols=num_ants,
                                   figsize=(12, 12))
        for m in range(num_ants):
            for l in range(num_ants):
                axes2[m, l].set_xlim(0, sym_samps)
                axes2[m, l].set_ylim(-1, 1)
                axes2[m, l].set_ylabel('Tx Ant %d, Rx Ant %d' % (m, l))
                axes2[m, l].legend(fontsize=10)

        lines20 = [[
            axes2[m,
                  l].plot(range(sym_samps),
                          np.real(wbz),
                          label='Pilot TxAnt %d RxAnt %d (real)' % (m, l))[0]
            for l in range(num_ants)
        ] for m in range(num_ants)]
        lines21 = [[
            axes2[m,
                  l].plot(range(sym_samps),
                          np.imag(wbz),
                          label='Pilot TxAnt %d RxAnt %d (imag)' % (m, l))[0]
            for l in range(num_ants)
        ] for m in range(num_ants)]
        lines22 = [[
            axes2[m, l].plot(range(sym_samps), sym_samps * [LTS_THRESH])[0]
            for m in range(num_ants)
        ] for l in range(num_ants)]
        fig2.show()

    first = True
    take = 0
    prev_take = take
    cur_mean_ang = np.ndarray(shape=(num_ants, pilot_sc_num), dtype=float)
    cur_mean_mag = np.ndarray(shape=(num_ants, pilot_sc_num), dtype=float)
    prev_mean_ang = np.ndarray(shape=(num_ants, pilot_sc_num), dtype=float)
    prev_mean_mag = np.ndarray(shape=(num_ants, pilot_sc_num), dtype=float)
    first_mean_ang = np.ndarray(shape=(num_ants, pilot_sc_num), dtype=float)
    first_mean_mag = np.ndarray(shape=(num_ants, pilot_sc_num), dtype=float)

    signal.signal(signal.SIGINT, signal_handler)
    begin = time.time()
    prev_time = begin
    while RUNNING:
        for d in range(num_sdrs):
            ref_sdr = bsdrs[d]
            flags = SOAPY_SDR_WAIT_TRIGGER | SOAPY_SDR_END_BURST

            # transmit pilot from node m
            sr = ref_sdr.writeStream(tx_streams[d], [wb_pilot_pad, wbz],
                                     sym_samps, flags)
            if sr.ret == -1:
                print("bad write")

            flags = SOAPY_SDR_WAIT_TRIGGER | SOAPY_SDR_END_BURST
            for r, sdr in enumerate(bsdrs):
                if r != d:
                    sdr.activateStream(rx_streams[r], flags, 0, sym_samps)

            trig_dev.writeSetting("TRIGGER_GEN", "")

            for r, sdr in enumerate(bsdrs):
                if r != d:
                    sr = sdr.readStream(rx_streams[r], [rx_samps[d][r], dummy],
                                        sym_samps,
                                        timeoutUs=int(1e6))
                    if sr.ret != sym_samps:
                        print("bad read %d" % sr.ret)

        bad_data = False
        for m in range(num_ants):
            if bad_data: break
            for p in range(num_ants):
                if m != p:
                    rx_samps[m][p] -= np.mean(rx_samps[m][p])
                    best_peak, _, _ = find_lts(rx_samps[m][p],
                                               thresh=LTS_THRESH,
                                               flip=True)
                    offset = 0 if not best_peak else best_peak - len(
                        lts_sym) + cp_len
                    if offset < 150:
                        print("bad data, skip")
                        bad_data = True
                        #break
                    rx_m_p = rx_samps[m][p]
                    rx_f1 = np.fft.fft(rx_m_p[offset:offset + fft_size],
                                       fft_size, 0)
                    rx_f2 = np.fft.fft(
                        rx_m_p[offset + fft_size:offset + 2 * fft_size],
                        fft_size, 0)
                    rx_f[m][p] = (rx_f1 + rx_f2) / 2

                    if plotter:
                        lines20[m][p].set_ydata(np.real(rx_samps[m][p]))
                        lines21[m][p].set_ydata(np.imag(rx_samps[m][p]))
                        lines22[m][p].set_data(offset,
                                               np.linspace(-1.0, 1.0, num=100))

        if bad_data:
            continue

        mag_model = LinearRegression()
        ang_model = LinearRegression()
        for m in range(num_ants):
            if m == ref_ant:
                calib_mag[m] = np.ones(fft_size)
                calib_ang[m] = np.zeros(fft_size)
            else:
                calib_mag[m] = np.divide(np.abs(rx_f[m][ref_ant]),
                                         np.abs(rx_f[ref_ant][m]))
                calib_ang[m] = np.angle(rx_f[m][ref_ant] *
                                        np.conj(rx_f[ref_ant][m]))
            for c in range(pilot_sc_num):
                s = pilot_subcarriers[c]
                mag_buffer[m][c].append(calib_mag[m][s])
                ang_buffer[m][c].append(calib_ang[m][s])
            x = np.asarray(pilot_subcarriers).reshape((-1, 1))
            y_mag = calib_mag[m][pilot_subcarriers]
            y_ang = calib_ang[m][pilot_subcarriers]
            mag_model.fit(x, y_mag)
            ang_model.fit(x, y_ang)
            for c in range(64):
                est_calib_mag[m][
                    c] = mag_model.intercept_ + mag_model.coef_ * c
                est_calib_ang[m][
                    c] = ang_model.intercept_ + ang_model.coef_ * c

        for m in range(num_ants):
            for p in range(pilot_sc_num):
                lines10[m][p].set_data(range(len(mag_buffer[m][p])),
                                       mag_buffer[m][p])
                lines11[m][p].set_data(range(len(mag_buffer[m][p])),
                                       ang_buffer[m][p])
            lines300[m].set_ydata(calib_mag[m])
            lines301[m].set_ydata(est_calib_mag[m])
            lines310[m].set_ydata(calib_ang[m])
            lines311[m].set_ydata(est_calib_ang[m])

        fig1.canvas.draw()
        fig1.show()
        fig3.canvas.draw()
        fig3.show()
        if plotter:
            fig2.canvas.draw()
            fig2.show()

        cur_time = time.time()
        if (cur_time - prev_time > take_duration):
            take_num = take - prev_take
            for m in range(num_ants):
                for p in range(pilot_sc_num):
                    mag_buffer_list = list(mag_buffer[m][p])
                    ang_buffer_list = list(ang_buffer[m][p])
                    mag_buffer_shot = mag_buffer_list[-take_num:]
                    ang_buffer_shot = ang_buffer_list[-take_num:]
                    cur_mean_mag[m, p] = np.mean(mag_buffer_shot)
                    cur_mean_ang[m, p] = np.mean(ang_buffer_shot)
            if first:
                first_mean_mag = cur_mean_mag.copy()
                first_mean_ang = cur_mean_ang.copy()
                first = False

            mag_drift_last = cur_mean_mag - prev_mean_mag
            ang_drift_last = np.unwrap(cur_mean_ang - prev_mean_ang)
            mag_drift_start = cur_mean_mag - first_mean_mag
            ang_drift_start = np.unwrap(cur_mean_ang - first_mean_ang)
            print("%d total takes, %d new takes, %f secs elapsed:" %
                  (take, take_num, cur_time - begin))
            print("Mag drift from last take:")
            print(mag_drift_last[1:, :])
            print("")
            print("Ang drift from last take:")
            print(ang_drift_last[1:, :])
            print("")
            print("Mag drift from first take:")
            print(mag_drift_start[1:, :])
            print("")
            print("Ang drift from first take:")
            print(ang_drift_start[1:, :])
            print("")
            print("")
            print("")
            prev_time = cur_time
            prev_take = take
            prev_mean_mag = cur_mean_mag.copy()
            prev_mean_ang = cur_mean_ang.copy()
        take += 1

    for r, sdr in enumerate(bsdrs):
        sdr.closeStream(tx_streams[r])
        sdr.closeStream(rx_streams[r])
Beispiel #5
0
def animate(i, num_samps, recorder, agc_en, wait_trigger, info):
    global sdr, rxStream, freqScale, sampsRx, frameCounter, fft_size, Rate, num_samps_circ_buff, rssi_circ_buff, pwr_circ_buff

    # Trigger AGC
    if agc_en:
        if frameCounter == 10:
            print(" *** ENABLE AGC/PKT DETECT *** ")
            sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_ENABLE, 1)
            sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_AGC_ENABLE_FLAG, 1)
        if frameCounter == 20:
            print(" *** DONE WITH PREVIOUS FRAME, ASSUME NEW FRAME INCOMING *** ")
            sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 1)
            sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 0)  # DO NOT REMOVE ME!! Disable right away

    # Read samples into this buffer
    sampsRx = [np.zeros(num_samps, np.complex64), np.zeros(num_samps, np.complex64)]
    buff0 = sampsRx[0]  # RF Chain 1
    buff1 = sampsRx[1]  # RF Chain 2

    flags = SOAPY_SDR_END_BURST
    if wait_trigger: flags |= SOAPY_SDR_WAIT_TRIGGER
    sdr.activateStream(rxStream,
        flags,    # flags
        0,                      # timeNs (dont care unless using SOAPY_SDR_HAS_TIME)
        buff0.size)             # numElems - this is the burst size
    sr = sdr.readStream(rxStream, [buff0, buff1], buff0.size)
    if sr.ret != buff0.size:
        print("Read RX burst of %d, requested %d" % (sr.ret, buff0.size))

    # DC removal
    for i in [0, 1]:
        sampsRx[i] -= np.mean(sampsRx[i])

    # Find LTS peaks (in case LTSs were sent)
    lts_thresh = 0.8
    a, b, peaks0 = find_lts(sampsRx[0], thresh=lts_thresh)
    a, b, peaks1 = find_lts(sampsRx[1], thresh=lts_thresh)

    # If recording samples
    if recorder is not None: 
        frame = np.empty((2, buff0.size), dtype='complex64')
        frame[0] = sampsRx[0]
        frame[1] = sampsRx[1]
        recorder.save_frame(sampsRx, sr.timeNs)

    # Store received samples in binary file (second method of storage)
    write_to_file('./data_out/rxsamps', sampsRx)

    # Magnitude of IQ Samples (RX RF chain A)
    I = np.real(sampsRx[0])
    Q = np.imag(sampsRx[0])
    IQmag = np.mean(np.sqrt(I**2 + Q**2))

    # Retrieve RSSI measured from digital samples at the LMS7, and convert to PWR in dBm
    agc_avg = 0
    rssi, PWRdBFS = getDigitalRSSI(sdr, agc_avg)  # dBFS

    # Compute Power of Time Domain Signal
    sigRms = np.sqrt(np.mean(sampsRx[0] * np.conj(sampsRx[0])))
    sigPwr = np.real(sigRms) ** 2
    sigPwr_dB = 10 * np.log10(sigPwr)
    sigPwr_dBm = 10 * np.log10(sigPwr / 1e-3)

    # Compute Power of Frequency Domain Signal (FFT)
    f1, powerBins, noiseFloor, pks = fft_power(sampsRx[0], Rate, num_bins=fft_size, peak=1.0,
                                               scaling='spectrum', peak_thresh=20)
    fftPower = bandpower(sampsRx[0], Rate, 0, Rate / 2)
    if fftPower <= 0:
        fftPower = 1e-15     # Remove warning
    fftPower_dB = 10 * np.log10(fftPower)
    fftPower_dBm = 10 * np.log10(fftPower / 1e-3)

    # Retrieve RSSI computed in the FPGA
    rssi_fpga = int(sdr.readRegister("IRIS30", FPGA_IRIS030_RD_MEASURED_RSSI))
    Vrms_fpga = (rssi_fpga / 2.0 ** 16) * (1 / np.sqrt(2.0))  # Vrms = Vpeak/sqrt(2) (In Volts) - 16 bit value
    PWRrms_fpga = (Vrms_fpga ** 2.0) / 50.0                   # 50 Ohms load (PWRrms in Watts)
    PWRdBm_fpga = 10.0 * np.log10(PWRrms_fpga) + 30           # P(dBm)=10*log10(Prms/1mW)  OR  P(dBm)=10*log10(Prms)+30

    # Circular buffer - continuously display data
    rssiPwrBuffer.append(PWRdBFS)
    timePwrBuffer.append(sigPwr_dB)
    freqPwrBuffer.append(fftPower_dB)
    noisPwrBuffer.append(noiseFloor)
    rssiPwrBuffer_fpga.append(PWRdBm_fpga)

    # Current gain values?
    lna_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA')    # ChanA (0)
    tia_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'TIA')    # ChanA (0)
    pga_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'PGA')    # ChanA (0)
    if "CBRS" in info["frontend"]:
        lna1_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA1')    # ChanA (0)
        lna2_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA2')    # ChanA (0)
        attn_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'ATTN')    # ChanA (0)
    else:
        lna1_rd = []
        lna2_rd = []
        attn_rd = []

    # Moving average (just for visualization purposes)
    circ_buff_idx = frameCounter % num_samps_circ_buff
    rssi_circ_buff[circ_buff_idx] = rssi
    pwr_circ_buff[circ_buff_idx] = PWRdBFS
    rssi_buff_avg = np.mean(rssi_circ_buff)
    pwr_buff_avg = np.mean(pwr_circ_buff)

    # Count number of frames received
    frameCounter = frameCounter + 1

    print("RSSI: {} \t PWR: {} \t ||| GAINS - ATTN: {} \t LNA1: {} \t LNA2: {} \t LNA: {} \t TIA: {} \t PGA: {} ".format(
        rssi_buff_avg, pwr_buff_avg, attn_rd, lna1_rd, lna2_rd, lna_rd, tia_rd, pga_rd))

    # Fill out data structures with measured data
    line1.set_data(range(buff0.size), np.real(sampsRx[0]))
    line2.set_data(range(buff0.size), np.imag(sampsRx[0]))
    line3.set_data(range(buff0.size), np.abs(sampsRx[0]))
    line4.set_data(range(buff0.size), np.abs(sampsRx[1]))
    line5.set_data(range(buff0.size), np.angle(sampsRx[0]))
    line6.set_data(range(buff0.size), np.angle(sampsRx[1]))
    line7.set_data(range(buff0.size), np.angle(sampsRx[0] * np.conj(sampsRx[1])))
    line8.set_data(f1, powerBins)
    line9.set_data(range(len(rssiPwrBuffer)), rssiPwrBuffer)
    line10.set_data(range(len(timePwrBuffer)), timePwrBuffer)
    line11.set_data(range(len(freqPwrBuffer)), freqPwrBuffer)
    line12.set_data(range(len(noisPwrBuffer)), noisPwrBuffer)
    line13.set_data(range(len(rssiPwrBuffer_fpga)), rssiPwrBuffer_fpga)
    line14.set_data(range(buff0.size), np.real(peaks0[:buff0.size]))

    return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12, line13, line14
Beispiel #6
0
def animate(i, num_samps_rd, rxStream, sdr, sdrTx, ofdm_params, tx_struct, ota, ofdm_obj, agc_en, infoTx):
    global FIG_LEN, pkt_count, ax6

    pkt_count = pkt_count + 1

    # Init
    n_ofdm_syms = ofdm_params[0]
    cp_len = ofdm_params[1]
    data_cp_len = ofdm_params[2]
    num_sc = ofdm_params[3]
    mod_order = ofdm_params[4]
    fft_offset = ofdm_params[5]

    tx_payload = tx_struct[0]
    payload_len = len(tx_struct[0])
    data_const = tx_struct[1]
    sc_idx_all = tx_struct[2]
    tx_data = tx_struct[3]
    txSignal = tx_struct[4]
    lts_syms_len = len(tx_struct[5])
    lts_freq = tx_struct[6]
    pilots_matrix = tx_struct[8]

    data_sc = sc_idx_all[0]
    pilot_sc = sc_idx_all[1]
    n_data_syms = n_ofdm_syms * len(data_sc)

    # Read samples into this buffer
    sampsRx = [np.zeros(num_samps_rd, np.complex64), np.zeros(num_samps_rd, np.complex64)]
    buff0 = sampsRx[0]  # RF Chain 1
    buff1 = sampsRx[1]  # RF Chain 2

    if ota:
        # Over-the-air Mode
        #find_optimal_gain(sdrTx, sdr)

        flags = SOAPY_SDR_END_BURST
        flags |= SOAPY_SDR_WAIT_TRIGGER
        sdr.activateStream(rxStream,
            flags,                  # flags
            0,                      # timeNs (dont care unless using SOAPY_SDR_HAS_TIME)
            buff0.size)             # numElems - this is the burst size

        if agc_en and "CBRS" in infoRx["frontend"]:
            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_PKT_DET_NEW_FRAME, 1)
            sdr.writeRegister("IRIS30", FPGA_IRIS030_WR_PKT_DET_NEW_FRAME, 0)

        sdr.writeSetting("TRIGGER_GEN", "")
        sr = sdr.readStream(rxStream, [buff0, buff1], buff0.size)
        if sr.ret != buff0.size:
            print("Read RX burst of %d, requested %d" % (sr.ret, buff0.size))

        # Retrieve RSSI computed in the FPGA
        rssi_fpga = int(sdr.readRegister("IRIS30", FPGA_IRIS030_RD_MEASURED_RSSI))
        # RX
        if "CBRS" in infoTx["frontend"]:
            lna_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA')       # ChanA (0)
            tia_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'TIA')       # ChanA (0)
            pga_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'PGA')       # ChanA (0)
            lna1_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA1')     # ChanA (0)
            lna2_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA2')     # ChanA (0)
            attn_rd1 = sdr.getGain(SOAPY_SDR_RX, 0, 'ATTN')    # ChanA (0)
            print("LNA: {} \t TIA: {} \t PGA: {} \t LNA1: {} \t LNA2: {} \t ATTN1: {}".format(lna_rd,
                                                                                                          tia_rd,
                                                                                                          pga_rd,
                                                                                                          lna1_rd,
                                                                                                          lna2_rd,
                                                                                                          attn_rd1))
        else:
            lna_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'LNA')  # ChanA (0)
            tia_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'TIA')  # ChanA (0)
            pga_rd = sdr.getGain(SOAPY_SDR_RX, 0, 'PGA')  # ChanA (0)
            print("LNA: {} \t TIA: {} \t PGA: {}".format(lna_rd, tia_rd, pga_rd))

    else:
        # Simulation Mode
        sampsRx[0] = txSignal + 0.01 * (np.random.randn(len(txSignal)) + np.random.randn(len(txSignal)) * 1j)
        sampsRx[1] = txSignal + 0.01 * (np.random.randn(len(txSignal)) + np.random.randn(len(txSignal)) * 1j)

    # DC removal
    for i in [0, 1]:
        sampsRx[i] -= np.mean(sampsRx[i])

    # Find LTS peaks (in case LTSs were sent)
    lts_thresh = 0.8
    a, b, peaks0 = find_lts(sampsRx[0], thresh=lts_thresh, flip=True)
    a, b, peaks1 = find_lts(sampsRx[1], thresh=lts_thresh, flip=True)

    # Check if LTS found
    if not a:
        print("SISO_OFDM: No LTS Found!")
        return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12

    # If beginning of frame was not captured in current buffer
    if (a - lts_syms_len) < 0:
        print("TOO EARLY... CONTINUE! ")
        return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12

    # Decode signal (focus on RF chain A only for now)
    rxSignal = sampsRx[0]
    payload_start = a + 1
    payload_end = payload_start + payload_len - 1  # Payload_len == (n_ofdm_syms * (num_sc + data_cp_len))
    lts_start = a - lts_syms_len + 1  # where LTS-CP start

    # Apply CFO Correction
    if APPLY_CFO_CORR:
        coarse_cfo_est = ofdm_obj.cfo_correction(rxSignal, lts_start, lts_syms_len, fft_offset)
    else:
        coarse_cfo_est = 0

    correction_vec = np.exp(-1j * 2 * np.pi * coarse_cfo_est * np.array(range(0, len(rxSignal))))
    rxSignal_cfo = rxSignal * correction_vec

    # Channel estimation
    # Get LTS again (after CFO correction)
    lts = rxSignal_cfo[lts_start: lts_start + lts_syms_len]

    # Verify number of samples
    if len(lts) != 160:
        print("INCORRECT START OF PAYLOAD... CONTINUE!")
        return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12

    lts_1 = lts[-64 + -fft_offset + np.array(range(97, 161))]
    lts_2 = lts[-fft_offset + np.array(range(97, 161))]

    # Average 2 LTS symbols to compute channel estimate
    tmp = np.fft.ifftshift(lts_freq)
    chan_est = np.fft.ifftshift(lts_freq) * (np.fft.fft(lts_1) + np.fft.fft(lts_2))/2

    # Assert sample position
    # NOTE: If packet found is not fully captured in current buffer read, ignore it and continue...
    if len(rxSignal_cfo) >= payload_end:
        # Retrieve payload symbols
        payload_samples = rxSignal_cfo[payload_start: payload_end + 1]
    else:
        print("TOO LATE... CONTINUE! ")
        return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12

    # Assert
    if len(payload_samples) != ((num_sc + data_cp_len) * n_ofdm_syms):
        print("INCORRECT START OF PAYLOAD... CONTINUE!")
        return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12
    else:
        payload_samples_mat_cp = np.reshape(payload_samples, ((num_sc + data_cp_len), n_ofdm_syms), order="F")

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

    # FFT
    rxSig_freq = np.fft.fft(payload_samples_mat, n=num_sc, 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_ofdm_syms)

    # Apply SFO Correction
    if APPLY_SFO_CORR:
        rxSig_freq_eq = ofdm_obj.sfo_correction(rxSig_freq_eq, pilot_sc, pilots_matrix, n_ofdm_syms)
    else:
        sfo_corr = np.zeros((num_sc, n_ofdm_syms))

    # Apply phase correction
    if APPLY_PHASE_CORR:
        phase_error = ofdm_obj.phase_correction(rxSig_freq_eq, pilot_sc, pilots_matrix)
    else:
        phase_error = np.zeros((1, n_ofdm_syms))

    phase_corr_tmp = np.matlib.repmat(phase_error, num_sc, 1)
    phase_corr = np.exp(-1j * phase_corr_tmp)
    rxSig_freq_eq_phase = rxSig_freq_eq * phase_corr
    rxSymbols_mat = rxSig_freq_eq_phase[data_sc, :]

    # Demodulation
    rxSymbols_vec = np.reshape(rxSymbols_mat, n_data_syms, order="F")       # Reshape into vector
    rx_data = ofdm_obj.demodulation(rxSymbols_vec, mod_order)

    print(" === STATS ===")
    symbol_err = np.sum(tx_data != rx_data)
    print("Frame#: {} --- Symbol Errors: {} out of {} total symbols".format(pkt_count, symbol_err, n_data_syms))

    # PLOTTING SECTION
    rx_H_est_plot = np.squeeze(np.matlib.repmat(complex('nan'), 1, len(chan_est)))
    rx_H_est_plot[data_sc] = np.squeeze(chan_est[data_sc])
    rx_H_est_plot[pilot_sc] = np.squeeze(chan_est[pilot_sc])
    x_ax = (20 / num_sc) * np.array(range(-(num_sc // 2), (num_sc // 2)))  # add 5 on each side for visualization

    # Fill out data structures with measured data
    line1.set_data(range(len(txSignal)), np.abs(txSignal))
    line2.set_data(range(len(rxSignal)), np.real(rxSignal))
    line3.set_data(range(len(rxSignal)), np.imag(rxSignal))
    line4.set_data(range(len(rxSignal)), np.abs(rxSignal))
    line5.set_data(range(len(peaks0)), np.abs(peaks0))
    line6.set_data(np.real(data_const), np.imag(data_const))
    line7.set_data(np.real(rxSymbols_mat), np.imag(rxSymbols_mat))

    line8.set_data(payload_start * np.ones(100), np.linspace(0.0, 1.0, num=100))
    line9.set_data(payload_end * np.ones(100), np.linspace(0.0, 1.0, num=100))
    line10.set_data((a - 2*lts_syms_len + 1) * np.ones(100), np.linspace(0.0, 1.0, num=100))
    line11.set_data(np.linspace(0.0, FIG_LEN, num=1000), (lts_thresh * np.max(peaks0)) * np.ones(1000))
    line12.set_data(x_ax, np.fft.fftshift(abs(rx_H_est_plot)))

    return line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12
Beispiel #7
0
def init(hub, bnodes, cnodes, ref_ant, ampl, rate, freq, txgain, rxgain, cp, plotter, numSamps, prefix_length, postfix_length, tx_advance, mod_order, threshold, use_trig):
    if hub != "": hub_dev = SoapySDR.Device(dict(driver="remote", serial = hub)) # device that triggers bnodes and ref_node
    bsdrs = [SoapySDR.Device(dict(driver="iris", serial = serial)) for serial in bnodes] # base station sdrs
    csdrs = [SoapySDR.Device(dict(driver="iris", serial = serial)) for serial in cnodes] # client sdrs
    # assume trig_sdr is part of the master nodes
    trig_dev = None
    if hub != "":
        trig_dev = hub_dev
    else:
        trig_dev = bsdrs[0]

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

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

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

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

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

    trig_dev.writeSetting("SYNC_DELAYS", "")

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    cont_plotter = plotter

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

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

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

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

        fig3.show()

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

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

        fig4.show()


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

    while(RUNNING):

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

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

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

        trig_dev.writeSetting("TRIGGER_GEN", "")

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

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

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

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

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


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

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

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

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

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

        trig_dev.writeSetting("TRIGGER_GEN", "")

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

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

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

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

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

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

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

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

        if bad_dl_data:
            continue

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

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

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

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

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

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

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

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

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

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

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

    # close streams and exit
    for i, sdr in enumerate(bsdrs):
        sdr.closeStream(rx_stream_ul[i])
    for i, sdr in enumerate(csdrs):
        sdr.closeStream(rx_stream_dl[i])
Beispiel #8
0
def animate(i):
    global sdr, rxStream, timeScale, sampsRx, fft_size, rate, num_samps, agc_fsm, IQmag, countMegd
    # read samples into this buffer
    buff0 = sampsRx[0]  # RF Chain 1
    buff1 = sampsRx[1]  # RF Chain 2 (Ignore for now)

    sdr.activateStream(
        rxStream,
        SOAPY_SDR_END_BURST,  # flags
        0,  # timeNs (dont care unless using SOAPY_SDR_HAS_TIME)
        buff0.size)  # numElems - this is the burst size
    sr = sdr.readStream(rxStream, [buff0, buff1], buff0.size)

    # Re-assign
    rxSignal = sampsRx[0]

    # dc removal
    sampsRx[rxChan] -= np.mean(sampsRx[rxChan])
    lts_thresh = 0.8
    a, b, peaks = find_lts(sampsRx[0], thresh=lts_thresh)
    write_to_file("./data_out/rx0", sampsRx[0])

    # Magnitude of IQ Samples - Real and imaginary
    I = np.real(rxSignal)
    Q = np.imag(rxSignal)
    IQmag = np.mean(np.sqrt(I**2 + Q**2))

    # DIGITAL RSSI
    agc_avg = 7  # average over X number of samples. See LMS7 datasheet
    rssi, PWRdBm = getDigitalRSSI(sdr, agc_avg)
    PWRdB = PWRdBm - 30

    # TIME DOMAIN POWER
    sigRms = np.sqrt(np.mean(rxSignal * np.conj(rxSignal)))
    sigPwr = np.real(sigRms)**2
    sigPwr_dB = 10 * np.log10(sigPwr)
    sigPwr_dBm = 10 * np.log10(sigPwr / 1e-3)

    # POWER FFT
    # powerBins = log_power_fft(rxSignal, fft_size)
    # noiseFloor, _ = log_power_fft_analysis(powerBins, rate)
    f1, powerBins, noiseFloor, pks = fft_power(rxSignal,
                                               rate,
                                               num_bins=None,
                                               peak=1.0,
                                               scaling='density',
                                               peak_thresh=20)
    fftPower = bandpower(rxSignal, rate, 0, rate / 2)
    fftPower_dB = 10 * np.log10(fftPower)
    fftPower_dBm = 10 * np.log10(fftPower / 1e-3)

    # Circular buffer - continuously display data
    rssiPwrBuffer.append(PWRdBm)
    timePwrBuffer.append(sigPwr_dB)
    freqPwrBuffer.append(fftPower_dB)
    noisPwrBuffer.append(noiseFloor)

    # PRINT VALUES
    # 50kHz sinusoid
    print("DigitalRSSI: {} \t DigitalPwr: {} ".format(rssi, PWRdBm))

    line1.set_data(range(buff0.size), np.real(rxSignal))
    line2.set_data(range(buff0.size), np.imag(rxSignal))
    line3.set_data(f1, powerBins)
    line4.set_data(range(len(rssiPwrBuffer)), rssiPwrBuffer)
    line5.set_data(range(len(timePwrBuffer)), timePwrBuffer)
    line6.set_data(range(len(freqPwrBuffer)), freqPwrBuffer)
    line7.set_data(range(len(noisPwrBuffer)), noisPwrBuffer)
    line8.set_data(range(buff0.size), np.real(peaks[:buff0.size]))

    return line1, line2, line3, line4, line5, line6, line7, line8