Post Go back to editing

How to determine the correctness of the received signal?

Category: Software

Hello!

Greeting!

We are trying to use subarray #2 and #3 of Stingray as Tx and subarray #1 and #4 as Rx. And we also directly connect the ADC0 and DAC0 on the AD9081 board to provide a reference of Tx. In this case, we are trying to achieve the following test:

While, we found that the waterfall spectrum of Tx_Ref and Rx are always the same (Tx_Ref has higher SNR), see the results below. So, it's hard to determine whether the received signal is right, because it seems not include the target information. In this case, how can we know the received signal is from the reflection of target? 


The following is our code:

clear all, close all, clc
%% Array Mapping
%verify element maps correctly to hardware!
subarray = ...
    [[1 2 5 6 9 10 13 14];... %subarray 1
    [3 4 7 8 11 12 15 16];... %subarray 2
    [19 20 23 24 27 28 31 32];... %subarray 3
    [17 18 21 22 25 26 29 30]]';  %subarray 4 
subarray_ref = [2 4 18 20]; %subarray reference elements
dac_map = [4 3 2 1]; %DAC map to subarray
dac_ref = 20; %DAC reference channel
adc_map = [4 1 2 3]; %ADC map to subarray
adc_ref = 4; %ADC reference channel

%% Config Dev Kit
 uri = 'ip:192.168.0.101';
% uri = 'ip:169.254.183.161';
amplitude = 2^15*db2mag(-6); %Tx Baseband Amplitude [dBFS]
interFreq = 4.5e9; %Tx NCO Frequency [Hz]

fs_TxIQ = 250e6; %Tx Decimated IQ Sample Rate [Hz]
periods = 16; %Desired Number Of Periods For Tx Signal
basebandFreq = fs_TxIQ/periods; %Baseband Frequency [Hz]
%Setup AD9081 Tx
tx = adi.AD9081.Tx;
tx.uri = uri;
tx.EnabledChannels = [1 2 3 4];%Enabled Tx Channels, Only Needed for DMA

tx.SamplesPerFrame = 2^10; %Number Of Samples
tx.NCOEnables = ones(1,numel(tx.EnabledChannels));
tx.ChannelNCOGainScales = ones(1,numel(tx.EnabledChannels)).*0.5; %MxFE0 Digital Gain Code

%DMA Configuration
tx.DataSource = 'DMA'; %'DMA' or 'DDS'
tx.EnableCyclicBuffers = 1; %0: Don't Cycle Tx Waveform, 1: Cycle Tx Waveform

% swv1 = dsp.SineWave(amplitude, basebandFreq);
% swv1.ComplexOutput = true;
% swv1.SamplesPerFrame = tx.SamplesPerFrame;
% swv1.SampleRate = fs_TxIQ;
% y = swv1();
% 
swv1 = phased.FMCWWaveform('SampleRate', fs_TxIQ, ...
    'SweepBandwidth', 50e6, 'SweepTime', tx.SamplesPerFrame/fs_TxIQ);
y = swv1();
y = y.*amplitude;



waveform = ones(tx.SamplesPerFrame,numel(tx.EnabledChannels)).*y;
waveform(:,1) = waveform(:,1).*0.5;
% plot(linspace((-fs_TxIQ/1e6/2), (fs_TxIQ/1e6/2), length(y)),20*log10(abs(fftshift(fft(y)))))
figure;spectrogram(y,[],[],[],fs_TxIQ);
title('Waterfall Spectrum of Tx');

release(tx)
tx(waveform);

tx.MainNCOFrequencies = ones(1,numel(tx.EnabledChannels))*interFreq; %NCO Frequency
tx.MainNCOPhases = zeros(1,numel(tx.EnabledChannels)); %NCO Phase

% Setup ADAR1000EVAL1Z in Tx Mode
sray = adi.Stingray;
sray.uri = uri;
sray.Mode(2,:) = {'Tx'}; %set mode, 'Rx', 'Tx, 'Disabled'
txPhaseCalOffsets = zeros(size(sray.TxGain));
sray.TxAttn(3:4,:) = 1; %1: Attenuation Off, 0: Attenuation On
sray.TxGain(3:4,:) = 127; %127: Highest Gain, 0: Lowest Gain, Decimal Value
sray(); %Stingray Constructor
sray.SteerTx(0,0,txPhaseCalOffsets); %Broadside
sray.LatchTxSettings; %Latch settings to devices

%Setup ADXUD1AEBZ, %Tx Mode
sray.TXRX0 = 0; %0: RX, 1: TX Subarray 4
sray.TXRX1 = 1; % Subarray 3
sray.TXRX2 = 1; % Subarray 2
sray.TXRX3 = 0; % Subarray 1
sray.ADF4371Frequency = 14.6e9; %program if using on-board LO PLL
sray.PllOutputSel = 1; %1: ADF4371 RF1 (8 GHz to 16 GHz), 0: ADF4371 RF2 (16 GHz to 32 GHz)

sray.PABiasOn(3:4,:) = -1.06;
sray.TxPAEnable(2,:) = true;
sray.TxPowerDown(3:4,:) = false; %Enable all channels for TX

detect = sray.LTC2314RFPower; %reads detected power (dBm) for J9 Input

%% Rx
fs_RxTxIQ = 250e6; %I/Q Data Rate in MSPS

%Setup AD9081 RX
rx = adi.AD9081.Rx;
rx.uri = uri;
rx.EnabledChannels = [1 2 3 4];
rx.MainNCOFrequencies = ones(1,4)*500e6; %NCO Frequency
rx.SamplesPerFrame = 2^10; %Number Of Samples To Capture: 4096
rx.kernelBuffersCount = 1; %Number Of Buffers To Subsequently Capture
rx.EnablePFIRs = true; %MxFE pFIR Configuration; false: Don't Use pFIRs, true: Use pFIRs
rx.PFIRFilenames = 'disabled.cfg';  %MxFE0 pFIR File
data = rx(); %Initialize The Rx System; Grab The Rx Data Into 'data' Matrix
rx.setRegister(hex2dec('FF'),'19'); %Fine DDC Page
rx.setRegister(hex2dec('61'),'283'); %Fine DDC Control, bypass fine NCO

% Setup ADAR1000EVAL1Z in RX Mode
rxPhaseCalOffsets = zeros(size(sray.RxGain));
sray.Mode(1,:) = {'Rx'}; %set mode, 'Rx', 'Tx, 'Disabled'
sray.RxAttn(1:2,:) = 1; %1: Attenuation Off, 0: Attenuation On
sray.RxGain(1:2,:) = 127; %127: Highest Gain, 0: Lowest Gain, Decimal Value
sray.SteerRx(0,0,rxPhaseCalOffsets); %Broadside
sray.LatchRxSettings; %Latch SPI settings to devices

%Setup ADXUD1AEBZ, %Rx High Gain Mode
sray.RxGainMode   = 1; %0: Low Gain, 1: High Gain - RX Mode only

sray.RxPowerDown(1:2,:) = false; %Enable RX Channels

data = rx(); %capture data from ADCs, 4096x4 matrix

sray.RxPowerDown(1:2,:) = true; %Disable Rx channels
sray.TxPowerDown(3:4,:) = true;
combinedComplexData = sum(data,2); %complex addition for all 4 ADCs

%% plot
%Calculate FFT of sample domain data for frequency response plots
hanningWindow = hanning(rx.SamplesPerFrame);
hanNoiseEqBw = enbw(hanningWindow);
scalingFactor = sqrt(hanNoiseEqBw)*(rx.SamplesPerFrame/2)*2^15;
scalingFactorArray = sqrt(hanNoiseEqBw)*(rx.SamplesPerFrame/2)*2^17; %bit growth due to coherent combining 4 ADCs

%FFT for each subarray
complexData = data./scalingFactor;
windowedData = complexData.*hanningWindow;
fftComplex = fft(windowedData);
fftComplexShifted = fftshift(fftComplex);
fftMags = abs(fftComplexShifted);
fftMagsdB = 20*log10(fftMags);
freqAxis = linspace((-fs_RxTxIQ/1e6/2), (fs_RxTxIQ/1e6/2), length(fftMagsdB));

%%frequency response plot for each subarray
figure
subplot(2,2,1)
plot(freqAxis, fftMagsdB(:,adc_map(1)))
grid on;
hold on;
title('Frequency Response Of Subarray 1');
xlabel('Frequency (MHz)','FontSize',12);
ylabel('Amplitude (dBFS)','FontSize',12);
axis([-fs_RxTxIQ/1e6/2, fs_RxTxIQ/1e6/2, -120, 0]);

subplot(2,2,2)
plot(freqAxis, fftMagsdB(:,adc_map(2)))
grid on;
hold on;
title('Frequency Response Of Subarray 2');
xlabel('Frequency (MHz)','FontSize',12);
ylabel('Amplitude (dBFS)','FontSize',12);
axis([-fs_RxTxIQ/1e6/2, fs_RxTxIQ/1e6/2, -120, 0]);

subplot(2,2,3)
plot(freqAxis, fftMagsdB(:,adc_map(3)))
grid on;
hold on;
title('Frequency Response Of Subarray 3');
xlabel('Frequency (MHz)','FontSize',12);
ylabel('Amplitude (dBFS)','FontSize',12);
axis([-fs_RxTxIQ/1e6/2, fs_RxTxIQ/1e6/2, -120, 0]);

subplot(2,2,4)
plot(freqAxis, fftMagsdB(:,adc_map(4)))
grid on;
hold on;
title('Frequency Response Of Subarray 4');
xlabel('Frequency (MHz)','FontSize',12);
ylabel('Amplitude (dBFS)','FontSize',12);
axis([-fs_RxTxIQ/1e6/2, fs_RxTxIQ/1e6/2, -120, 0]);
%%
figure;
subplot(1,2,1)
spectrogram(windowedData(:,2),[],[],[],fs_RxTxIQ);
title('Waterfall Spectrum of Rx');
subplot(1,2,2)
spectrogram(windowedData(:,1),[],[],[],fs_RxTxIQ);
title('Frequency-time of Tx Ref');

Could anyone give us some suggestions? Thanks in advance!

Best,

Dongyu