%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Using WARPLab (SISO configuration) to Transmit Bits Over a Wireless % Channel . %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This matlab srcipt generates a bitstream, modulates the bitstream using % DQPSK, transmits the modulated symbols over a wireless channel using % WARPLab, and demodulates the received signal to obtain the % transmitted bits. Bit error rate (BER) is computed by comparing the % transmitted bitstream with the bitstream recovered at the receiver % The specific steps implemented in this script are the following: % 0. Initialization, define paramters, create pulse shaping filter, and % create reference matrix for detection of preamble % 1. Generate a random bit stream and map it to symbols % 2. Modulate the symbols (map symbols to constellation points) and append % preamble symbols % 3. Upsample the modulated symbols with the appended preamble and filter % using a pulse shaping filter % 4. Upconvert from baseband to 5MHz to avoid radio DC attenuation % 5. Transmit the signal over a wireless channel using Warplab % 6. Downconvert from 5MHz to baseband % 7. Filter the received signal with a Matched Filter (matched to the pulse % shaping filter), detect preamble, and downsample output of Matched Filter % 8. Demodulate and recover the transmitted bitstream % 9. Compute the Bit Error Rate (BER) and close sockets % Part of this code was adapted from Matlab's commdoc_mod and commdoc_rrc % examples. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 0. Initialization, define paramters, create pulse shaping filter, and % create reference matrix for detection of preamble %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Define basic parameters M = 4; % Size of signal constellation k = log2(M); % Number of bits per symbol nsamp = 8; % Oversampling rate or Number of samples per symbol % Define parameters related to the pulse shaping filter and create the % pulse shaping filter % This pulse shaping filter is a Squared Root Raised Cosine (SRRC) filter filtorder = 64; % Filter order delay = filtorder/(nsamp*2); % Group delay (# of input samples). Group % delay is the time between the input to the filter and the filter's peak % response counted in number of input samples. In number of output samples % the delay would be equal to 'delay*nsam'. rolloff = 0.3; % Rolloff factor of filter rrcfilter = rcosine(1,nsamp,'fir/sqrt',rolloff,delay); % Create SRRC filter % Plot the filter's impulse response in a stem plot figure; % Create new figure window. stem(rrcfilter); title('Raised Cosine Impulse Response'); xlabel('n (samples)'); ylabel('Amplitude'); % Define number of symbols to process, number of bits to process, and the % preamble. % The Warplab transmit buffer can store a maximum of 2^14 samples, the % number of samples per symbol is equal 'nsam', and the SRRC filter delay % in number of samples is equal to 'delay*nsam'. Consequently, the total % number of symbols to be transmitted must be less than % (2^14-200)/nsam-2*delay. We subtract extra 200 to account for jitter in % sync trigger. nsym = floor((2^14-200)/nsamp-2*delay); % Number or symbols to transmit preamble = [-1;-1;-1;1;-1;0;0;0;0;0;0;0;0]; % Preamble is a Barker sequence % modulated with BPSK nsym_preamble = length(preamble); % number of symbols in preamble nsym_payload = nsym-nsym_preamble; nbits = floor(nsym_payload*k); % Number of bits to process % Create a reference matrix used for detection of the preamble in the % received signal. We will correlate the received signal with the reference % matrix preamble_upsamp = upsample(preamble,nsamp); % Upsample preamble length_preamble_upsamp = length(preamble_upsamp); corr_window = 300; % We expect to find the preamble within the first % 300 received samples reference_samples = zeros(corr_window,1); % Create reference vector. reference_samples(1:length_preamble_upsamp) = preamble_upsamp; % First samples of reference vector correspond to the % preamble upsampled reference_matrix = toeplitz(reference_samples,... circshift(reference_samples(corr_window:-1:1),1)); % Create reference matrix. The first column of the reference % matrix is equal to the reference_samples vector. The i-th column % of the reference matrix is equal to circular shift of the % reference samples vector, it is a shift down by i samples. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 1. Generate a random bit stream and map it to symbols %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Create a random binary data stream as a column vector. x = randint(nbits,1); % Map bits in vector x into k-bit symbols xsym = bi2de(reshape(x,k,length(x)/k).','left-msb'); % Stem plot of bits and symbols % Plot first 40 bits in a stem plot. figure; subplot(2,1,1) stem(x(1:40),'filled'); title('Random Bits'); xlabel('Bit Index'); ylabel('Binary Value'); % Plot first 40/k symbols in a stem plot. subplot(2,1,2) stem(xsym(1:40/k),'filled'); title('Random Bits Mapped to Symbols'); xlabel('Symbol Index'); ylabel('Integer Value'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 2. Modulate the symbols (map symbols to constellation points) and append % preamble symbols %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Modulate using DQPSK ytx_mod = dpskmod(xsym,M); % Append preamble ytx_mod = [preamble;ytx_mod]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 3. Upsample the modulated symbols with the appended preamble and filter % using a pulse shaping filter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Upsample and apply square root raised cosine filter. ytx_mod_filt = rcosflt(ytx_mod,1,nsamp,'filter',rrcfilter); % Stem Plot of modulated symbols before and after Squared Root Raised % Cosine (SRRC) filter % Plots first 30 symbols. % Plots I and Q in different windows figure; % Create new figure window. subplot(2,1,1) stem([1:nsamp:nsamp*30],real(ytx_mod(1:30))); hold stem(real(ytx_mod_filt(1+delay*nsamp:1+30*nsamp+delay*nsamp)),'r'); title('I Signal'); xlabel('n (sample)'); ylabel('Amplitude'); legend('Before SRRC Filter','After SRRC Filter'); subplot(2,1,2) stem([1:nsamp:nsamp*30],imag(ytx_mod(1:30))); hold stem(imag(ytx_mod_filt(1+delay*nsamp:1+30*nsamp+delay*nsamp)),'r'); title('Q Signal'); xlabel('n (sample)'); ylabel('Amplitude'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 4. Upconvert from baseband to 5MHz to avoid radio DC attenuation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% time = [0:1:length(ytx_mod_filt)-1]/40e6; % Sampling Freq. is 40MHz ytx_mod_filt_up = ytx_mod_filt .* exp(sqrt(-1)*2*pi*5e6*time).'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5. Transmit the signal over a wireless channel using Warplab %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Follow the steps for transmission and reception of data using Warplab. % These are the steps in the matlab script warplab_example_TxRx.m % In this example the vector to transmit is the 'ytx_mod_filt' vector. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.0. Initializaton and definition of parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Load some global definitions (packet types, etc.) warplab_defines % Create Socket handles and intialize nodes [socketHandles, packetNum] = warplab_initialize; % Separate the socket handles for easier access % The first socket handle is always the magic SYNC % The rest of the handles are the handles to the WARP nodes udp_Sync = socketHandles(1); udp_node1 = socketHandles(2); udp_node2 = socketHandles(3); % Define WARPLab parameters. % Note: For this experiment node 1 will be set as the transmitter and node % 2 will be set as the receiver (this is done later in the code), hence, % there is no need to define receive gains for node 1 and there is no % need to define transmitter gains for node 2. TxDelay = 100; % Number of noise samples per Rx capture. In [0:2^14] TxLength =length(ytx_mod_filt_up); % Length of transmission. In [0:2^14-1-TxDelay] CarrierChannel = 12; % Channel in the 2.4 GHz band. In [1:14] Node1_Radio2_TxGain_BB = 3; % Tx Baseband Gain. In [0:3] Node1_Radio2_TxGain_RF = 40; % Tx RF Gain. In [0:63] Node2_Radio2_RxGain_BB = 13; % Rx Baseband Gain. In [0:31] Node2_Radio2_RxGain_RF = 2; % Rx RF Gain. In [1:3] TxMode = 0; % Transmission mode. In [0:1] % 0: Single Transmission % 1: Continuous Transmission. Tx board will continue % transmitting the vector of samples until the user manually % disables the transmitter. Node2_MGC_AGC_Select = 0; % Set MGC_AGC_Select=1 to enable Automatic Gain Control (AGC). % Set MGC_AGC_Select=0 to enable Manual Gain Control (MGC). % By default, the nodes are set to MGC. % Download the WARPLab parameters to the WARP nodes. % The nodes store the TxDelay, TxLength, and TxMode parameters in % registers defined in the WARPLab sysgen model. The nodes set radio % related parameters CarrierChannel, TxGains, and RxGains, using the % radio controller functions. % The TxDelay, TxLength, and TxMode parameters need to be known at the transmitter; % the receiver doesn't require knowledge of these parameters (the receiver % will always capture 2^14 samples). For this exercise node 1 will be set as % the transmitter (this is done later in the code). Since TxDelay, TxLength and % TxMode are only required at the transmitter we download the TxDelay, TxLength and % TxMode parameters only to the transmitter node (node 1). warplab_writeRegister(udp_node1,TX_DELAY,TxDelay); warplab_writeRegister(udp_node1,TX_LENGTH,TxLength); warplab_writeRegister(udp_node1,TX_MODE,TxMode); % The CarrierChannel parameter must be downloaded to all nodes warplab_setRadioParameter(udp_node1,CARRIER_CHANNEL,CarrierChannel); warplab_setRadioParameter(udp_node2,CARRIER_CHANNEL,CarrierChannel); % Node 1 will be set as the transmitter so download Tx gains to node 1. warplab_setRadioParameter(udp_node1,RADIO2_TXGAINS,(Node1_Radio2_TxGain_RF + Node1_Radio2_TxGain_BB*2^16)); % Node 2 will be set as the receiver so download Rx gains to node 2. warplab_setRadioParameter(udp_node2,RADIO2_RXGAINS,(Node2_Radio2_RxGain_BB + Node2_Radio2_RxGain_RF*2^16)); % Set MGC mode in node 2 (receiver) warplab_setAGCParameter(udp_node2,MGC_AGC_SEL, Node2_MGC_AGC_Select); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.1. Generate a vector of samples to transmit and send the samples to the % WARP board (Sample Frequency is 40MHz) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Prepare some data to be transmitted % Scale signal to transmit so that it spans [-1,1] range. We do this to % use the full range of the DAC at the tranmitter scale = 1 / max( [ max(real(ytx_mod_filt_up)) , max(imag(ytx_mod_filt_up)) ] ); ytx_mod_filt_up = scale*ytx_mod_filt_up; Node1_Radio2_TxData = ytx_mod_filt_up.'; % Create a signal to transmit. Signal must be a % row vector % Download the samples to be transmitted % Hints: % 1. The first argument of the 'warplab_writeSMRO' function identifies the % node to which samples will be downloaded to. In this exercise we will set % node 1 as the transmitter node, the id or handle to node 1 is 'udp_node1'. % 2. The second argument of the 'warplab_writeSMRO' function identifies the % transmit buffer where the samples will be written. A node programmed with % the warplab_mimo_2x2_v04.bit bitstream has 2 transmit buffers and a node % programmed with the warplab_mimo_4x4_v04.bit bitstream has 4 transmit % buffers. For this exercise we will transmit from radio 2, hence, samples % must be downloaded to radio 2 Tx buffer, the id for this buffer is % 'RADIO2_TXDATA'. % 3. The third argument of the 'warplab_writeSMWO' function is the % vector of samples to download, it must be a row vector. For this % exercise the 'Node1_Radio2_TxData' vector is the vector of samples to be % transmitted, hence, this is the vector that must be downloaded to radio 2 % Tx buffer. warplab_writeSMWO(udp_node1, RADIO2_TXDATA, Node1_Radio2_TxData); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.2. Prepare WARP boards for transmission and reception and send trigger to % start transmission and reception (trigger is the SYNC packet) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The following lines of code set node 1 as transmitter and node 2 as % receiver; transmission and capture are triggered by sending the SYNC % packet. % Enable transmitter radio path in radio 2 in node 1 (enable radio 2 in % node 1 as transmitter) by sending the RADIO2_TXEN command to node 1 using % the 'warplab_sendCmd' function. % Hints: % 1. The first argument of the 'warplab_sendCmd' function identifies the % node to which the command will be sent to. The id or handle to node 1 is % 'udp_node1'. % 2. The second argument of the 'warplab_sendCmd' function identifies the % command that will be sent. % 3. The third argument of the 'warplab_sendCmd' command is a field that is % not used at the moment, it may be used in future versions of WARPLab to % keep track of packets. Use 'packetNum' as the third argument of the % 'warplab_sendCmd' command. warplab_sendCmd(udp_node1, RADIO2_TXEN, packetNum); % Enable transmission of node1's radio 2 Tx buffer (enable transmission % of samples stored in radio 2 Tx Buffer in node 1) by sending the % RADIO2TXBUFF_TXEN command to node 1 using the 'warplab_sendCmd' function. warplab_sendCmd(udp_node1, RADIO2TXBUFF_TXEN, packetNum); % Enable receiver radio path in radio 2 in node 2 (enable radio 2 in % node 2 as receiver) by sending the RADIO2_RXEN command to node 2 using % the 'warplab_sendCmd' function. % Hint: The id or handle to node 2 is 'udp_node2'. warplab_sendCmd(udp_node2, RADIO2_RXEN, packetNum); % Enable capture in node2's radio 2 Rx Buffer (enable radio 2 rx buffer in % node 2 for storage of samples) by sending the RADIO2RXBUFF_RXEN command to % node 2 using the 'warplab_sendCmd' function. warplab_sendCmd(udp_node2, RADIO2RXBUFF_RXEN, packetNum); % Prime transmitter state machine in node 1. Node 1 will be % waiting for the SYNC packet. Transmission from node 1 will be triggered % when node 1 receives the SYNC packet. warplab_sendCmd(udp_node1, TX_START, packetNum); % Prime receiver state machine in node 2. Node 2 will be waiting % for the SYNC packet. Capture at node 2 will be triggered when node 2 % receives the SYNC packet. warplab_sendCmd(udp_node2, RX_START, packetNum); % Send the SYNC packet warplab_sendSync(udp_Sync); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.3. Read the received smaples from the Warp board %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Read the received samples from the WARP board using the % 'warplab_readSMRO' function. (Read extra 100 samples to account for % jitter in sync trigger) % Hints: % 1. The first argument of the 'warplab_readSMRO' function identifies the % node from which samples will be read. In this exercise we set node 2 as % the receiver node, the id or handle to node 2 is 'udp_node2'. % 2. The second argument of the 'warplab_readSMRO' function identifies the % receive buffer from which samples will be read. A node programmed with % the warplab_mimo_2x2_v04.bit bitstream has 2 receive buffers and a node % programmed with the warplab_mimo_4x4_v04.bit bitstream has 4 receive % buffers. For this exercise samples were captured in node 2 radio 2, % hence, samples must be read from radio 2 Rx buffer, the id for this % buffer is 'RADIO2_RXDATA'. % 3. The third argument of the 'warplab_readSMRO' function is the number of % samples to read; reading of samples always starts from address zero. % For this exercise set third argument of the 'warplab_readSMRO' % function equal to 'TxLength+CaptOffset+100' (Read extra 100 samples to % account for jitter in sync trigger) [Node2_Radio2_RawRxData] = warplab_readSMRO(udp_node2, RADIO2_RXDATA, TxLength+TxDelay+100); % Process the received samples to obtain meaningful data [Node2_Radio2_RxData,Node2_Radio2_RxOTR] = warplab_processRawRxData(Node2_Radio2_RawRxData); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.4. Reset and disable the boards %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Set radio 2 Tx buffer in node 1 back to Tx disabled mode warplab_sendCmd(udp_node1, RADIO2TXBUFF_TXDIS, packetNum); % Disable the transmitter radio warplab_sendCmd(udp_node1, RADIO2_TXDIS, packetNum); % Set radio 2 Rx buffer in node 2 back to Rx disabled mode warplab_sendCmd(udp_node2, RADIO2RXBUFF_RXDIS, packetNum); % Disable the receiver radio warplab_sendCmd(udp_node2, RADIO2_RXDIS, packetNum); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 5.5. Plot the transmitted and received data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure; subplot(2,2,1); plot(real(Node1_Radio2_TxData)); title('Tx Node 1 Radio 2 I'); xlabel('n (samples)'); ylabel('Amplitude'); axis([0 2^14 -1 1]); % Set axis ranges. subplot(2,2,2); plot(imag(Node1_Radio2_TxData)); title('Tx Node 1 Radio 2 Q'); xlabel('n (samples)'); ylabel('Amplitude'); axis([0 2^14 -1 1]); % Set axis ranges. subplot(2,2,3); plot(real(Node2_Radio2_RxData)); title('Rx Node 2 Radio 2 I'); xlabel('n (samples)'); ylabel('Amplitude'); axis([0 2^14 -1 1]); % Set axis ranges. subplot(2,2,4); plot(imag(Node2_Radio2_RxData)); title('Rx Node 2 Radio 2 Q'); xlabel('n (samples)'); ylabel('Amplitude'); axis([0 2^14 -1 1]); % Set axis ranges. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 6. Downconvert from 5MHz to baseband %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% time = [0:1:length(Node2_Radio2_RxData)-1]/40e6; % Sampling Freq. is 40MHz yrx_bb = Node2_Radio2_RxData .* exp(-sqrt(-1)*2*pi*5e6*time); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 7. Filter the received signal with a Matched Filter (matched to the pulse % shaping filter), detect preamble, and downsample output of Matched Filter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Store received samples as a column vector yrx_bb = yrx_bb.'; % Matched filter: Filter received signal using the SRRC filter yrx_bb_mf = rcosflt(yrx_bb,1,nsamp,'Fs/filter',rrcfilter); % Correlate with the reference matrix to find preamble sequence correlation = abs( (yrx_bb_mf(1:corr_window).') * reference_matrix ); preamble_start = find(correlation == max(correlation)); % Start of preamble first_sample_index = preamble_start+length_preamble_upsamp; % Start of % first symbol after preamble % Downsample output of Matched Filter yrx_bb_mf_ds = yrx_bb_mf(first_sample_index:end); yrx_bb_mf_ds = downsample(yrx_bb_mf_ds,nsamp); % Slice symbols of interest (nsym_payload symbols were transmitted so if % yrx_bb_mf_ds has more than nsym_payload elements the extra elements of the % yrx_bb_mf_ds vector are due to the extra samples read from the Rx buffer % and the extra samples added by the delay of the filters) yrx_bb_mf_ds = yrx_bb_mf_ds(1:nsym_payload); % Stem Plot of signal before Matched Filter, after Matched Filter, and % after downsampling % Plots first 30 symbols. % Plots real and imaginary parts in different windows figure; % Create new figure window. subplot(2,1,1) stem(real(yrx_bb(first_sample_index-(1+delay*nsamp):first_sample_index-(1+delay*nsamp)+30*nsamp)),'b'); hold stem(real(yrx_bb_mf(first_sample_index:first_sample_index+30*nsamp)),'r'); stem([1:nsamp:nsamp*30],real(yrx_bb_mf_ds(1:30)),'k'); title('I Symbols'); xlabel('n (sample)'); ylabel('Amplitude'); legend('Before Matched Filter','After Matched Filter','After Downsample'); subplot(2,1,2) stem(imag(yrx_bb(first_sample_index-(1+delay*nsamp):first_sample_index-(1+delay*nsamp)+30*nsamp)),'b'); hold stem(imag(yrx_bb_mf(first_sample_index:first_sample_index+30*nsamp)),'r'); stem([1:nsamp:nsamp*30],imag(yrx_bb_mf_ds(1:30)),'k'); title('Q Symbols'); xlabel('n (sample)'); ylabel('Amplitude'); % Scatter Plot of received and transmitted constellation points h = scatterplot(yrx_bb_mf_ds(1:end),1,0,'g.'); hold on; scatterplot(ytx_mod(nsym_preamble+1:end),1,0,'k*',h); title('Constellations'); legend('Received','Transmitted'); axis([-2 2 -2 2]); % Set axis ranges. hold off; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 8. Demodulate and recover the transmitted bitstream %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Demodulate signal using DQPSK zsym = dpskdemod(yrx_bb_mf_ds,M); % Map Symbols to Bits z = de2bi(zsym,'left-msb'); % Convert integers to bits. % Convert z from a matrix to a vector. z = reshape(z.',prod(size(z)),1); % Plot first 80 transmitted bits and first 80 received bits in a stem plot figure; subplot(2,1,1) stem(x(1:80),'filled'); title('Transmitted Bits'); xlabel('Bit Index'); ylabel('Binary Value'); subplot(2,1,2) stem(z(1:80),'filled'); title('Received Bits'); xlabel('Bit Index'); ylabel('Binary Value'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 9. Compute the Bit Error Rate (BER) and close sockets %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Compare x and z to obtain the number of errors and the bit error rate [number_of_errors,bit_error_rate] = biterr(x(3:length(z)),z(3:length(z))) % We start comparing at three because the first two bits are are always % lost in DQPSK. We compare until minlen because z may be shorter % than x due to the jitter of the synch pulse. % Close sockets pnet('closeall');