You are not logged in.
Hi, I am using WARP v3 and WARPLab 7.5.0.
I am studying wl_example_siso_ofdm_txrx example code.
when a source node send packet to a destination node, a packet is linear data.
wl_basebandCmd(node_tx,[RF_TX], 'write_IQ', tx_vec_air(:));
In this part, I want to know how to operate each subcarrier.
Subcarriers have different channel information each other.
I understand rx_H_est parameter has channel information of 64 subcarriers.
when I calculated below code, result is similar with syms_f_mat.
but as the number of column increased, result is not similar with syms_f_mat.
result = ifft_in_mat .* repmat(rx_H_est.', 1, N_OFDM_SYMS);
Although a packet is transmitted with linearity, does this code operate like real OFDM way?
and I want to know why result and syms_f_mat are similar only in the fore number column.
Offline
tx_vec_air is a vector of complex samples. This vector is the result of all the Tx PHY processing. If you want to operate on subcarriers you should look above this in the code. tx_syms_mat is a matrix with one complex value for each data-bearing subcarrier for each OFDM symbol. This matrix is merged with pilots_mat (pilot tone subcarriers) to form the input matrix for the IFFT.
syms_f_mat is the matrix output of the FFT in the Rx processing. The dimensions of the matrix are N_OFDM_SYMS by N_SUBCARRIERS. The raw FFT output must be equalized before demod/detection. syms_eq_mat is the matrix of equalized values (includes data-bearing subcarriers, pilot tones and empty subcarriers). payload_syms_mat is the matrix of just the data-bearing subcarriers. rx_syms is the vector version of payload_syms_mat.
Offline
I am using WARP v3 and WARPLab 7.5.0.
I am studying wl_example_siso_ofdm_txrx example code.
NUMNODES = 3; % Create a vector of node objects nodes = wl_initNodes(NUMNODES); % Create a UDP broadcast trigger and tell each node to be ready for it eth_trig = wl_trigger_eth_udp_broadcast; wl_triggerManagerCmd(nodes, 'add_ethernet_trigger', [eth_trig]); % Read Trigger IDs into workspace [T_IN_ETH_A, T_IN_ENERGY, T_IN_AGCDONE, T_IN_REG, T_IN_D0, T_IN_D1, T_IN_D2, T_IN_D3, T_IN_ETH_B] = wl_getTriggerInputIDs(nodes(1)); [T_OUT_BASEBAND, T_OUT_AGC, T_OUT_D0, T_OUT_D1, T_OUT_D2, T_OUT_D3] = wl_getTriggerOutputIDs(nodes(1)); % For both nodes, we will allow Ethernet to trigger the buffer baseband and the AGC wl_triggerManagerCmd(nodes, 'output_config_input_selection', [T_OUT_BASEBAND, T_OUT_AGC], [T_IN_ETH_A, T_IN_REG]); % Set the trigger output delays. nodes.wl_triggerManagerCmd('output_config_delay', [T_OUT_BASEBAND], 0); nodes.wl_triggerManagerCmd('output_config_delay', [T_OUT_AGC], 3000); %3000 ns delay before starting the AGC % Get IDs for the interfaces on the boards. Since this example assumes each % board has the same interface capabilities, we only need to get the IDs % from one of the boards [RFA,RFB] = wl_getInterfaceIDs(nodes(1)); % Set up the interface for the experiment wl_interfaceCmd(nodes, 'RF_ALL', 'tx_gains', 3, 30); wl_interfaceCmd(nodes, 'RF_ALL', 'channel', 2.4, 4); if(USE_AGC) wl_interfaceCmd(nodes, 'RF_ALL', 'rx_gain_mode', 'automatic'); wl_basebandCmd(nodes, 'agc_target', -13); else wl_interfaceCmd(nodes, 'RF_ALL', 'rx_gain_mode', 'manual'); RxGainRF = 1; % Rx RF Gain in [1:3] RxGainBB = 1; % Rx Baseband Gain in [0:31] wl_interfaceCmd(nodes, 'RF_ALL', 'rx_gains', RxGainRF, RxGainBB); end % Set up the TX / RX nodes and RF interfaces node1 = nodes(1); node2 = nodes(2); node3 = nodes(3); RF_TX = RFB; RF_RX = RFA; % Get parameters from the node SAMP_FREQ = wl_basebandCmd(nodes(1),'tx_buff_clk_freq'); % We will read the transmitter's maximum I/Q buffer length % and assign that value to a temporary variable. % % node2 - WARPLab node object for the transmitter % RF_TX - index of RF interface used for transmission maximum_buffer_len = wl_basebandCmd(node2, RF_TX, 'tx_buff_max_num_samples'); % Our transmission length for this example does not need % to fill the entire transmit buffer, so we will use the smaller % of two values: the maximum buffer length the board % can support or an arbitrary value defined by this script TX_NUM_SAMPS = min(MAX_TX_LEN, maximum_buffer_len); % Set up the baseband for the experiment wl_basebandCmd(nodes, 'tx_delay', 0); wl_basebandCmd(nodes, 'tx_length', TX_NUM_SAMPS); % Number of samples to send wl_basebandCmd(nodes, 'rx_length', TX_NUM_SAMPS); % Number of samples to receive example_mode_string = 'hw'; %% transmission tx_vec_air2 wl_basebandCmd(node2,[RFB], 'write_IQ', tx_vec_air2(:)); % Enable the Tx and Rx radios wl_interfaceCmd(node2,RFB, 'tx_en'); wl_interfaceCmd(node2,RFA, 'rx_en'); % Enable the Tx and Rx buffers wl_basebandCmd(node2,RFB, 'tx_buff_en'); wl_basebandCmd(node2,RFA, 'rx_buff_en'); eth_trig.send(); pause(TX_NUM_SAMPS * 1/(40e6)); rx_vec_airA = wl_basebandCmd(node2,[RFA], 'read_IQ', 0, TX_NUM_SAMPS); rx_vec_airA = rx_vec_airA(:).'; wl_basebandCmd(nodes, 'RF_ALL', 'tx_rx_buff_dis'); wl_interfaceCmd(nodes, 'RF_ALL', 'tx_rx_dis'); %% transmission tx_vec_air wl_basebandCmd(node1,[RFA], 'write_IQ', tx_vec_air(:)); % Enable the Tx and Rx radios wl_interfaceCmd(node1,RFA, 'tx_en'); wl_interfaceCmd(node2,RFA, 'rx_en'); % Enable the Tx and Rx buffers wl_basebandCmd(node1,RFA, 'tx_buff_en'); wl_basebandCmd(node2,RFA, 'rx_buff_en'); eth_trig.send(); pause(TX_NUM_SAMPS * 1/(40e6)); rx_vec_airtB = wl_basebandCmd(node2,[RFA], 'read_IQ', 0, TX_NUM_SAMPS); rx_vec_airtB = rx_vec_airtB(:).'; wl_basebandCmd(nodes, 'RF_ALL', 'tx_rx_buff_dis'); wl_interfaceCmd(nodes, 'RF_ALL', 'tx_rx_dis'); %% simultaneously transmit above two transmissions % Write the Tx waveform to the Tx node wl_basebandCmd(node1,[RFA], 'write_IQ', tx_vec_air(:)); % Enable the Tx and Rx radios wl_interfaceCmd(node1,RFA, 'tx_en'); wl_interfaceCmd(node2,RFA, 'rx_en'); % Enable the Tx and Rx buffers wl_basebandCmd(node1,RFA, 'tx_buff_en'); wl_basebandCmd(node2,RFA, 'rx_buff_en'); %%%%%%%%%%%%%%%%%%%%%%% wl_basebandCmd(node2,[RFB], 'write_IQ', tx_vec_air2(:)); %Enable the Tx and Rx radios wl_interfaceCmd(node2,RFB, 'tx_en'); wl_interfaceCmd(node2,RFA, 'rx_en'); %Enable the Tx and Rx buffers wl_basebandCmd(node2,RFB, 'tx_buff_en'); wl_basebandCmd(node2,RFA, 'rx_buff_en'); %%%%%%%%%%%%%%%%%%%%%%% % Trigger the Tx/Rx cycle at both nodes eth_trig.send(); % Pause for the samples to be processed at the node pause(TX_NUM_SAMPS * 1/(40e6)); % Retrieve the received waveform from the Rx node rx_vec_air = wl_basebandCmd(node2,[RFA], 'read_IQ', 0, TX_NUM_SAMPS); rx_vec_air = rx_vec_air(:).'; % Disable the Tx/Rx radios and buffers wl_basebandCmd(nodes, 'RF_ALL', 'tx_rx_buff_dis'); wl_interfaceCmd(nodes, 'RF_ALL', 'tx_rx_dis'); syms_f_mat = Rx_processing(rx_vec_air); syms_f_matA = Rx_processing(rx_vec_airA); syms_f_matB = Rx_processing(rx_vec_airB); syms_f_mat_sum = syms_f_matA + syms_f_matB;
Rx_processing function calculates syms_f_mat which is the matrix output of the FFT.
I think syms_f_mat and syms_f_mat_sum will be same but there are some difference between them.
I want to remove this difference and know why the difference occur.
Last edited by JayG8027 (2015-Jul-22 08:22:02)
Offline
For us to provide the most help, you need to describe what exactly you are trying to do, what you are trying to measure, and what you expect to see. I'm skeptical that the code you pasted is doing what you think its doing. But without knowing what you think its doing (since you provided no description), I can't address any discrepancy there. Please provide a detailed description of what you are trying to measure and what you expect to see.
Observations from your script:
- rx_vec_air is captured from a trial consisting of the transmission of tx_vec_air2 from node1 RFA -> node2 RFA
- rx_vec_airA is captured from a different trial consisting of the transmission of tx_vec_air2 from node2 RFB -> node2 RFA
- rx_vec_airB is not defined in the above script. rx_vec_airtB is defined and appears to be a typo of rx_vec_airB. The script shouldn't even run unless you have some stale variable in your workspace for rx_vec_airB
- rx_vec_airtB is captured from a third trial consisting of the transmission of tx_vec_air from node1 RFA -> node2 RFB
- You have not provided code that defines tx_vec_air or tx_vec_air2.
Even assuming that rx_vec_airtB is actually rx_vec_airB, I can't see any way that syms_f_mat and syms_f_mat_sum would ever be exactly equal to one another. Why do you expect that they should be? Here are a few reasons of why they might be different:
1. The three relevant Rx vectors (rx_vec_air, rx_vec_airA, rx_vec_airB) all come from independent trials. Every time you run a trial, you are exposing a transmission to new random perturbations like the wireless channel and noise.
2. syms_f_mat is based on a trial consisting of the transmission of tx_vec_air2 while syms_f_mat_sum is based on multiple trials consisting of the transmissions of tx_vec_air and tx_vec_air2.
3. I don't know what Rx_processing is doing since you didn't provide that function. Even if rx_vec_air = rx_vec_airA+ rx_vec_airB (which they don't for the above reasons), you can only expect the output of those functions to equal one another if Rx_processing exhibits additivity. Does it?
Offline
rx_vec_airB is same with rx_vec_airtB. this is typing error.
below is code to produce tx_vec_air and tx_vec_air2
tx_data = randi(MOD_ORDER, 1, N_DATA_SYMS) - 1;
[tx_vec_air, pilots_mat, tx_syms, tx_syms_mat] = tx_processing(tx_data, preamble, TX_NUM_SAMPS, interp_filt2);
tx_data2 = randi(MOD_ORDER, 1, N_DATA_SYMS) - 1;
[tx_vec_air2, pilots_mat2, tx_syms2, tx_syms_mat2] = tx_processing(tx_data2, preamble, TX_NUM_SAMPS, interp_filt2);
and below code is tx_processing function.
%% Generate a payload % Functions for data -> complex symbol mapping (avoids comm toolbox requirement for qammod) modvec_bpsk = (1/sqrt(2)) .* [-1 1]; modvec_16qam = (1/sqrt(10)) .* [-3 -1 +3 +1]; mod_fcn_bpsk = @(x) complex(modvec_bpsk(1+x),0); mod_fcn_qpsk = @(x) complex(modvec_bpsk(1+bitshift(x, -1)), modvec_bpsk(1+mod(x, 2))); mod_fcn_16qam = @(x) complex(modvec_16qam(1+bitshift(x, -2)), modvec_16qam(1+mod(x,4))); % Map the data values on to complex symbols switch MOD_ORDER case 2 % BPSK tx_syms = arrayfun(mod_fcn_bpsk, tx_data); case 4 % QPSK tx_syms = arrayfun(mod_fcn_qpsk, tx_data); case 16 % 16-QAM tx_syms = arrayfun(mod_fcn_16qam, tx_data); otherwise fprintf('Invalid MOD_ORDER (%d)! Must be in [2, 4, 16]\n', MOD_ORDER); return; end % Reshape the symbol vector to a matrix with one column per OFDM symbol tx_syms_mat = reshape(tx_syms, length(SC_IND_DATA), N_OFDM_SYMS); % Define the pilot tones if(USE_PILOT_TONES) pilots = [1 1 -1 1].'; else pilots = [0 0 0 0].'; end % Repeat the pilots across all OFDM symbols pilots_mat = repmat(pilots, 1, N_OFDM_SYMS); %% IFFT % Construct the IFFT input matrix ifft_in_mat = zeros(N_SC, N_OFDM_SYMS); % Insert the data and pilot values; other subcarriers will remain at 0 ifft_in_mat(SC_IND_DATA, :) = tx_syms_mat; ifft_in_mat(SC_IND_PILOTS, :) = pilots_mat; %Perform the IFFT tx_payload_mat = ifft(ifft_in_mat, N_SC, 1); % Insert the cyclic prefix if(CP_LEN > 0) tx_cp = tx_payload_mat((end-CP_LEN+1 : end), :); tx_payload_mat = [tx_cp; tx_payload_mat]; end % Reshape to a vector tx_payload_vec = reshape(tx_payload_mat, 1, numel(tx_payload_mat)); % Construct the full time-domain OFDM waveform tx_vec = [preamble tx_payload_vec]; % Pad with zeros for transmission tx_vec_padded = [tx_vec zeros(1,(TX_NUM_SAMPS/INTERP_RATE)-length(tx_vec))]; %% Interpolate if(INTERP_RATE == 1) tx_vec_air = tx_vec_padded; elseif(INTERP_RATE == 2) tx_vec_2x = zeros(1, 2*numel(tx_vec_padded)); tx_vec_2x(1:2:end) = tx_vec_padded; tx_vec_air = filter(interp_filt2, 1, tx_vec_2x); end % Scale the Tx vector tx_vec_air = TX_SCALE .* tx_vec_air ./ max(abs(tx_vec_air)); end
and below code is RX_processing function code.
%% Decimate if(DECIMATE_RATE == 1) raw_rx_dec = rx_vec_air; elseif(DECIMATE_RATE == 2) raw_rx_dec = filter(interp_filt2, 1, rx_vec_air); raw_rx_dec = raw_rx_dec(1:2:end); end %% Correlate for LTS % Complex cross correlation of Rx waveform with time-domain LTS lts_corr = abs(conv(conj(fliplr(lts_t)), sign(raw_rx_dec))); % Skip early and late samples lts_corr = lts_corr(32:end-32); % Find all correlation peaks lts_peaks = find(lts_corr > LTS_CORR_THRESH*max(lts_corr)); % Select best candidate correlation peak as LTS-payload boundary [LTS1, LTS2] = meshgrid(lts_peaks,lts_peaks); [lts_second_peak_index,y] = find(LTS2-LTS1 == length(lts_t)); % Stop if no valid correlation peak was found if(isempty(lts_second_peak_index)) fprintf('No LTS Correlation Peaks Found!\n'); return; end % Set the sample indices of the payload symbols and preamble payload_ind = lts_peaks(max(lts_second_peak_index))+32; lts_ind = payload_ind-160; if(DO_APPLY_CFO_CORRECTION) %Extract LTS (not yet CFO corrected) rx_lts = raw_rx_dec(lts_ind : lts_ind+159); rx_lts1 = rx_lts(-64+-FFT_OFFSET + [97:160]); rx_lts2 = rx_lts(-FFT_OFFSET + [97:160]); %Calculate coarse CFO est rx_cfo_est_lts = mean(unwrap(angle(rx_lts1 .* conj(rx_lts2)))); rx_cfo_est_lts = rx_cfo_est_lts/(2*pi*64); else rx_cfo_est_lts = 0; end % Apply CFO correction to raw Rx waveform rx_cfo_corr_t = exp(1i*2*pi*rx_cfo_est_lts*[0:length(raw_rx_dec)-1]); rx_dec_cfo_corr = raw_rx_dec .* rx_cfo_corr_t; % Re-extract LTS for channel estimate rx_lts = rx_dec_cfo_corr(lts_ind : lts_ind+159); rx_lts1 = rx_lts(-64+-FFT_OFFSET + [97:160]); rx_lts2 = rx_lts(-FFT_OFFSET + [97:160]); rx_lts1_f = fft(rx_lts1); rx_lts2_f = fft(rx_lts2); % Calculate channel estimate rx_H_est = lts_f .* (rx_lts1_f + rx_lts2_f)/2; %% Rx payload processing % Extract the payload samples (integral number of OFDM symbols following preamble) payload_vec = rx_dec_cfo_corr(payload_ind : payload_ind+N_OFDM_SYMS*(N_SC+CP_LEN)-1); payload_mat = reshape(payload_vec, (N_SC+CP_LEN), N_OFDM_SYMS); % Remove the cyclic prefix, keeping FFT_OFFSET samples of CP (on average) payload_mat_noCP = payload_mat(CP_LEN-FFT_OFFSET+[1:N_SC], :); % Take the FFT syms_f_mat = fft(payload_mat_noCP, N_SC, 1);
rx_vec_air received two signals from path node2 RFB -> node2 RFA and node1 RFA -> node2 RFB at the same time.
rx_vec_airA received a signal from path node2 RFB -> node2 RFA
rx_vec_airB received a signal from path node1 RFA -> node2 RFB
they are operated in one program, so their channel information are similar each other.
therefore I think that rx_vec_air and rx_vec_airA+ rx_vec_airB are similar each other.
But they have some differences, I want to know way to minimize this difference.
Offline
Two vectors of Rx samples captured at different times on one interface, or at any time on different RF interfaces, will never be identical. Random noise is inherent in the Rx circuitry and unique noise will always be present in any vector of Rx samples. Further, propagation channel fluctuations are random and constantly changing. Finally two nodes will have sampling and carrier frequency offsets (unless they're sharing a clock signal).
I would strongly encourage you to study the setup you're building in simulation. You can add realistic hardware and propagation effects to the simulation (carrier frequency offset, random channel fading, additive random noise) and observe how these impact your Rx processing. The OFDM example has a section of code specifically for this purpose, where you can modify the vector of samples passed from Tx -> Rx in simulation. You should start with the sim, applying realistic effects and convince yourself your Tx and Rx processing is working before introducing actual hardware.
Offline
If a signal A and a signal B mixed signal and A is much stronger than a signal B, can I subtract signal A?
More details, I estimate the signal A and adjust delay by using correlation A and the mixed signal.
And then I subtract the signal A from the mixed signal. In this way, can I obtain the signal B?
Offline
Yes, a receiver observes the superposition of simultaneously transmitted signals. However you must account for all the phase and amplitude variations that occur between your Tx DAC and Rx ADC. This includes the 3 Tx amplifiers (Tx baseband VGA , Tx RF VGA, Tx PA), 2 Rx amplifiers (Rx RF LNA, Rx baseband VGA), phase/frequency offsets due to carrier and sampling frequency offsets, and the wireless propagation channel itself (i.e. random amplitude and phase). Your Rx code must estimate the overall phase/frequency/amplitude change experienced along each Tx-Rx path and use this estimate to separate the superimposed Rx signals. Melissa's thesis on building a full duplex system describes the processing she implemented in detail.
Offline
Thank you for your answer.
I am using WARP v3 and WARPLab 7.5.0 and I have another question in wl_example_siso_ofdm_txrx example.
I obtained two rx_H_est values continuously by same way in one program. rx_H_est is channel estimation value in wl_example_siso_ofdm_txrx.
If tx and rx antenna connect one board, two rx_H_est values are same each other. But tx and rx antenna connect different board each other, two rx_H_est value are different.
maybe there are many cause such as amplifiers and wireless propagation channel information.
can I make different two rx_H_est values to be same?
Offline
Again, two independent measurements of rx_H_est will never be exactly the same. When using a single board for both Tx and Rx, you have a fixed carrier frequency and sampling frequency between your transmitter and receiver. Absent OTA channel effects (e.g., the experiment is over an attenuated coax cable), rx_H_est should be similar between runs. When you use two different boards that each have their own independent clocks, CFO and SFO will make it so that rx_H_est won't be the same between two runs. There will be an arbitrary phase offset in rx_H_est at the beginning of time as well as a time-varying phase rotation.
Making rx_H_est "the same" is thinking of it backwards. rx_H_est is the independent and uncontrollable channel and the goal is to work around it. A classic way to deal with differences in rx_H_est is the general principle of precoding at your transmitter, where you modify your transmission taking the expected rx_H_est into account so that the received signal has an effective (rx_H_est = 1).
Offline
chunter wrote:
A classic way to deal with differences in rx_H_est is the general principle of precoding at your transmitter, where you modify your transmission taking the expected rx_H_est into account so that the received signal has an effective (rx_H_est = 1).
Could you explain in detail?
Offline
Could you explain in detail?
You will need to do explore this topic on your own. Tx precoding is a complex topic, with many approaches and nuances. Our forums are meant to answer questions about WARP hardware and the WARP reference designs. We cannot provide instruction on fundamentals of wireless comm. There are many excellent resources online and in print that are better places for this.
Offline