Post Go back to editing

How to test RX and TX simultaneously on X-band radar platform?

Category: Software

Hello,

We are working on the configuration of the X-band radar platform. Since we don't have a RF signal generator and a spectrum analyzer, we can only test the radar system by setting part of subarray on Stingray as Tx mode and the others as Rx mode. So we combine the example code "XBDP_SimpleRx.m" and "XBDP_SimpleTx.m". Then, the result of code is as following:

It appears that the results are incorrect, as the frequency of the transmitter (Tx) does not affect the results of the receiver (Rx). So we are wondering what's wrong with the configuration. We use the on-board LO signal on the ADXUD1A board. And we are not sure whether ADXUD1A is working well. The following is our control code, could you give us some suggestion?

In summary, we would like to know:
1. whether the code is correct.

2.how to see whether ADXUD1A is working well?

3. Do we need to enable the on-board LO on the software side?

Finally, we would really appreciate it if you could give us some advice! Looking forward to your reply!

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 = 4; %DAC reference channel
adc_map = [4 2 1 3]; %ADC map to subarray
adc_ref = 4; %ADC reference channel

%% Config Dev Kit
% uri = 'ip:192.168.1.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 = 32; %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();
waveform = ones(tx.SamplesPerFrame,numel(tx.EnabledChannels)).*y;

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
sray.TXRX1 = 0;
sray.TXRX2 = 1;
sray.TXRX3 = 1;
% sray.RxGainMode = 0; %0: Low Gain, 1: High Gain, RX Mode only
sray.ADF4371Frequency = 14.5e9; %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(3:4,:) = true;
sray.TxPowerDown(3:4,:) = false; %Enable all channels for TX

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

sray.TxPowerDown(3:4,:) = true; %Disable all channels for TX

%% 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)*0e6; %NCO Frequency
rx.SamplesPerFrame = 2^12; %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(); %constructor to write properties to hardware
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.ADF4371Frequency = 14.5e9; %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.RxPowerDown(1:2,:) = false; %Enable RX Channels

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

sray.RxPowerDown(1:2,:) = true; %Disable Rx channels

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]);

Best,

Dongyu

  • Hi Dongyu,

    Hope you are doing well.

    Can you describe your test setup? Are you directly looping the TX output to the RX input on the ADAR1000EVAL or are you trying to catch a reflection? Taking a look at the code I can see a couple things that may be getting in your way. I believe what you are seeing on your graphs is not the signal and is something generated by the onboard LO. On line 77 the transmit channels are powered down before you capture data in RX mode. Commenting this out should allow you to transmit a signal through the two subarrays you have designated to TX. You also may need to change line 72 as what you currently have will change the array from a 2x4 to a 4x4. I will show below:

    sray.TxPAEnable(2,:) = true;

    To answer your question, yes the on-board LO must be enabled via MATLAB. Looking at your code I see that it is enabled. Give what I have suggested a try and let me know how it works out.

    Regards,

    Brandon

  • Hello Brandon,

    Thanks so much for your reply! In our test setup, we are just trying to catch a reflection. If you think looping the TX output to the RX input is easier to test the correct signal at this stage, we can also try this. And we have modified the code as your suggestions. But the results appear the same as that before (see below). And do you have other ideas about this problem? 

    And the revised code is as follows:

    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 = 4; %DAC reference channel
    adc_map = [4 2 1 3]; %ADC map to subarray
    adc_ref = 4; %ADC reference channel
    
    %% Config Dev Kit
    % uri = 'ip:192.168.1.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 = 32; %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();
    waveform = ones(tx.SamplesPerFrame,numel(tx.EnabledChannels)).*y;
    
    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
    sray.TXRX1 = 0;
    sray.TXRX2 = 1;
    sray.TXRX3 = 1;
    % sray.RxGainMode = 0; %0: Low Gain, 1: High Gain, RX Mode only
    sray.ADF4371Frequency = 14.5e9; %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(3:4,:) = true;
    sray.TxPAEnable(2,:) = true;
    sray.TxPowerDown(3:4,:) = false; %Enable all channels for TX
    
    detect = sray.LTC2314RFPower; %reads detected power (dBm) for J9 Input
    
    % sray.TxPowerDown(3:4,:) = true; %Disable all channels for TX
    
    %% 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)*0e6; %NCO Frequency
    rx.SamplesPerFrame = 2^12; %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(); %constructor to write properties to hardware
    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.ADF4371Frequency = 14.5e9; %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.RxPowerDown(1:2,:) = false; %Enable RX Channels
    
    data = rx(); %capture data from ADCs, 4096x4 matrix
    
    sray.RxPowerDown(1:2,:) = true; %Disable Rx channels
    
    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]);

    Could you tell me which code enables the on-board LO? I am not familiar about this code. 

    Thanks again for your kind help! 

    Best,

    Dongyu

  • Hi Dongyu,

    I've put together some code that has worked for us in the lab. I would suggest directly looping from the TX output to RX input as it will provide the best performance. In our configuration the connections on the Stingray face are as follows. Row 1 RX input to Row 3 TX output. Row 2 RX input to Row 4 TX output. Take a look at lines 69 & 70. Leaving these lines uncommented allows you to control the on-board LO and it is the only step required to use it. Let me know if this works for you.

    Regards,

    Brandon

    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 = 32; %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();
    waveform = ones(tx.SamplesPerFrame,numel(tx.EnabledChannels)).*y;
    
    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.RxGainMode = 0; %0: Low Gain, 1: High Gain, RX Mode only
    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
    
    %sray.TxPowerDown(3:4,:) = true; %Disable all channels for TX
    
    %% 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)*490e6; %NCO Frequency
    rx.SamplesPerFrame = 2^12; %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(); %constructor to write properties to hardware
    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.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.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]);

  • Hello Brandon,

    Thanks soo much! It works now! See the results below:

    I am wondering why the received frequency is ~17.9MHz. The Baseband frequency of Tx we set is 7.81MHz, right? How can we calculate the expected frequency?

    Thanks again for your help! It's really amazing! Finally done!

    Cheers,

    Dongyu

  • Hi Dongyu,

    I am glad this solution worked out for you. Yes, the original baseband frequency of the signal you generated is at 7.81 MHz. It is interpolated up to 4.5 GHz by the AD9081 and up-converted to 10.1 GHz out of Stingray. In your configuration, this is fed back in and down-converted to the 4.5 GHz IF through the RX chain back. You can change the value of the RX NCOs to achieve the desired baseband frequency. In the code I provided the NCOs are set to 490 MHz which is on line 87. For example, if you'd like the received signal to be at the same frequency it was generated at (7.81 MHz rather than 17.9 MHz) you could increase this value to 500 MHz which will shift the frequency down another 10 MHz.

    Regards,

    Brandon

  • Hi Brandon,

    Thanks so much for your answer. I am wondering how to define the NCO frequency of RX. The received signal is down-converted to the 4.5GHz IF (actually it should be 4.5GHz +7.81Mhz, right?). Then why the NCO of Rx is not the same as that of Tx, which is also 4.5GHz? Why is the NCO frequency 500MHz here? 

    Thanks again!

    Best,

    Dongyu