function ask_demod(ebn0_db_range) %ASK_DEMOD BER simulation for coherent and noncoherent on-off keying NUM_SYMBOLS = 1000000; % Sweep over the assigned Eb/N0 range ber_coh = zeros(size(ebn0_db_range)); ber_abs = zeros(size(ebn0_db_range)); for n = 1:length(ebn0_db_range) % Generate the Tx and Rx symbols. % Note: Eb is 0.5 on average -> sqrt(0.25) for noise scaling % instead of the usual sqrt(0.5) for real, imaginary parts. ebn0_db = ebn0_db_range(n); noise_sc = sqrt(0.25) * 10^(-ebn0_db/20); symb_tx = 2*randint(NUM_SYMBOLS, 1, 2); % 0 or 1 symb_rx = symb_tx + noise_sc*complex(randn(NUM_SYMBOLS, 1), randn(NUM_SYMBOLS, 1)); % Run both slicers. slice_coh = logical(real(symb_rx) > 0.5); slice_abs = logical(abs(symb_rx) > 0.5); % Count errors, and store the resulting BER. ber_coh(n) = sum(xor(slice_coh, symb_tx)) / NUM_SYMBOLS; ber_abs(n) = sum(xor(slice_abs, symb_tx)) / NUM_SYMBOLS; end % Calculate ideal curves ebn0_db_ideal = linspace(min(ebn0_db_range)-2, max(ebn0_db_range)+2, 100); ebn0_ideal = 10.^(ebn0_db_ideal/10); ber_coh_ideal = qfunc(sqrt(ebn0_ideal)); ber_abs_ideal = 0.5*exp(-0.5*ebn0_ideal) + 0.5*qfunc(sqrt(ebn0_ideal)); % Plot the results: figure; semilogy(ebn0_db_ideal, ber_coh_ideal, 'r:'); hold on; semilogy(ebn0_db_ideal, ber_abs_ideal, 'b:'); semilogy(ebn0_db_range, ber_coh, 'r^'); semilogy(ebn0_db_range, ber_abs, 'bv'); xlabel('Eb/N0 (dB)'); ylabel('Bit Error Rate'); legend('Coherent (ideal)', ... 'Noncoherent (ideal)', ... 'Coherent (simulation)', ... 'Noncoherent (simulation)');